blob: 340551e3cf90b623090c650510956a26a2927a71 [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);
Radek Krejci8b764662018-11-14 14:15:13 +01001928 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1929
Radek Krejci6d6556c2018-11-08 09:37:45 +01001930 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001931 switch (kw) {
1932 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001933 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 +02001934 break;
1935 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01001936 YANG_CHECK_STMTVER_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001937 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 +02001938 break;
1939 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001940 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 +02001941 break;
1942 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001943 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001944 break;
1945 case YANG_VALUE:
1946 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001947 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001948 break;
1949 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001950 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001951 break;
1952 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001953 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001954 return LY_EVALID;
1955 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001956 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001957 return ret;
1958}
1959
Michal Vaskoea5abea2018-09-18 13:10:54 +02001960/**
1961 * @brief Parse the fraction-digits statement. Substatement of type statement.
1962 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001963 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001964 * @param[in,out] data Data to read from, always moved to currently handled character.
1965 * @param[in,out] fracdig Value to write to.
1966 * @param[in,out] exts Extension instances to add to.
1967 *
1968 * @return LY_ERR values.
1969 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001970static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001971parse_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 +02001972{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001973 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001974 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001975 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001976 unsigned long int num;
1977 enum yang_keyword kw;
1978
1979 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001980 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001981 return LY_EVALID;
1982 }
1983
1984 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001985 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001986
1987 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001988 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001989 free(buf);
1990 return LY_EVALID;
1991 }
1992
1993 errno = 0;
1994 num = strtoul(word, &ptr, 10);
1995 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001996 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001997 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001998 free(buf);
1999 return LY_EVALID;
2000 }
2001 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002002 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002003 free(buf);
2004 return LY_EVALID;
2005 }
2006 *fracdig = num;
2007 free(buf);
2008
Radek Krejci6d6556c2018-11-08 09:37:45 +01002009 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002010 switch (kw) {
2011 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002012 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002013 break;
2014 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002015 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002016 return LY_EVALID;
2017 }
2018 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002019 return ret;
2020}
2021
Michal Vaskoea5abea2018-09-18 13:10:54 +02002022/**
2023 * @brief Parse the require-instance statement. Substatement of type statement.
2024 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002025 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002026 * @param[in,out] data Data to read from, always moved to currently handled character.
2027 * @param[in,out] reqinst Value to write to.
2028 * @param[in,out] flags Flags to write to.
2029 * @param[in,out] exts Extension instances to add to.
2030 *
2031 * @return LY_ERR values.
2032 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002033static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002034parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002035 struct lysp_ext_instance **exts)
2036{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002037 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002038 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002039 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002040 enum yang_keyword kw;
2041
2042 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002043 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002044 return LY_EVALID;
2045 }
2046 *flags |= LYS_SET_REQINST;
2047
2048 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002049 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002050
2051 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2052 *reqinst = 1;
2053 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002054 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002055 free(buf);
2056 return LY_EVALID;
2057 }
2058 free(buf);
2059
Radek Krejci6d6556c2018-11-08 09:37:45 +01002060 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002061 switch (kw) {
2062 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002063 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002064 break;
2065 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002066 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002067 return LY_EVALID;
2068 }
2069 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002070 return ret;
2071}
2072
Michal Vaskoea5abea2018-09-18 13:10:54 +02002073/**
2074 * @brief Parse the modifier statement. Substatement of type pattern statement.
2075 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002076 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002077 * @param[in,out] data Data to read from, always moved to currently handled character.
2078 * @param[in,out] pat Value to write to.
2079 * @param[in,out] exts Extension instances to add to.
2080 *
2081 * @return LY_ERR values.
2082 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002083static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002084parse_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 +02002085{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002086 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002087 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002088 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002089 enum yang_keyword kw;
2090
2091 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002092 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002093 return LY_EVALID;
2094 }
2095
2096 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002097 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002098
2099 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002100 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002101 free(buf);
2102 return LY_EVALID;
2103 }
2104 free(buf);
2105
2106 /* replace the value in the dictionary */
2107 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002108 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002109 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002110 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002111
2112 assert(buf[0] == 0x06);
2113 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002114 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002115
Radek Krejci6d6556c2018-11-08 09:37:45 +01002116 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002117 switch (kw) {
2118 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002119 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002120 break;
2121 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002122 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002123 return LY_EVALID;
2124 }
2125 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002126 return ret;
2127}
2128
Michal Vaskoea5abea2018-09-18 13:10:54 +02002129/**
2130 * @brief Parse the pattern statement. Substatement of type statement.
2131 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002132 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002133 * @param[in,out] data Data to read from, always moved to currently handled character.
2134 * @param[in,out] patterns Restrictions to add to.
2135 *
2136 * @return LY_ERR values.
2137 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002138static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002139parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002140{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002141 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002142 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002143 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002144 enum yang_keyword kw;
2145 struct lysp_restr *restr;
2146
Radek Krejci2c4e7172018-10-19 15:56:26 +02002147 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002148
2149 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002150 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002151
2152 /* add special meaning first byte */
2153 if (buf) {
2154 buf = realloc(buf, word_len + 2);
2155 word = buf;
2156 } else {
2157 buf = malloc(word_len + 2);
2158 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002159 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002160 memmove(buf + 1, word, word_len);
2161 buf[0] = 0x06; /* pattern's default regular-match flag */
2162 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2163 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002164
Radek Krejci6d6556c2018-11-08 09:37:45 +01002165 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002166 switch (kw) {
2167 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002168 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 +02002169 break;
2170 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002171 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 +02002172 break;
2173 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002174 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 +02002175 break;
2176 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002177 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 +02002178 break;
2179 case YANG_MODIFIER:
Radek Krejci10113652018-11-14 16:56:50 +01002180 YANG_CHECK_STMTVER_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002181 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002182 break;
2183 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002184 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002185 break;
2186 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002187 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002188 return LY_EVALID;
2189 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002190 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002191 return ret;
2192}
2193
Michal Vaskoea5abea2018-09-18 13:10:54 +02002194/**
2195 * @brief Parse the type statement.
2196 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002197 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002198 * @param[in,out] data Data to read from, always moved to currently handled character.
2199 * @param[in,out] type Type to wrote to.
2200 *
2201 * @return LY_ERR values.
2202 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002203static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002204parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002205{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002206 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002207 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002208 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002209 enum yang_keyword kw;
2210 struct lysp_type *nest_type;
2211
2212 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002213 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002214 return LY_EVALID;
2215 }
2216
2217 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002218 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002219 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002220
Radek Krejci6d6556c2018-11-08 09:37:45 +01002221 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002222 switch (kw) {
2223 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002224 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 +01002225 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002226 break;
2227 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002228 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002229 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002230 break;
2231 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002232 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002233 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002234 break;
2235 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002236 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002237 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002238 break;
2239 case YANG_LENGTH:
2240 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002241 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002242 return LY_EVALID;
2243 }
2244 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002245 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002246
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002247 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002248 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002249 break;
2250 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002251 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 +01002252 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002253 break;
2254 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002255 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002256 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002257 break;
2258 case YANG_RANGE:
2259 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002260 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002261 return LY_EVALID;
2262 }
2263 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002264 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002266 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002267 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002268 break;
2269 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002270 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002271 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002272 break;
2273 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002274 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2275 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002276 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002277 break;
2278 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002279 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002280 break;
2281 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002282 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002283 return LY_EVALID;
2284 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002285 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002286 return ret;
2287}
2288
Michal Vaskoea5abea2018-09-18 13:10:54 +02002289/**
2290 * @brief Parse the leaf statement.
2291 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002292 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002293 * @param[in,out] data Data to read from, always moved to currently handled character.
2294 * @param[in,out] siblings Siblings to add to.
2295 *
2296 * @return LY_ERR values.
2297 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002298static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002299parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002300{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002301 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002302 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002303 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002304 enum yang_keyword kw;
2305 struct lysp_node *iter;
2306 struct lysp_node_leaf *leaf;
2307
2308 /* create structure */
2309 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002310 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002311 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002312 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002313
2314 /* insert into siblings */
2315 if (!*siblings) {
2316 *siblings = (struct lysp_node *)leaf;
2317 } else {
2318 for (iter = *siblings; iter->next; iter = iter->next);
2319 iter->next = (struct lysp_node *)leaf;
2320 }
2321
2322 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002323 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002324 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002325
2326 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002327 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002328 switch (kw) {
2329 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002330 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002331 break;
2332 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002333 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 +02002334 break;
2335 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002336 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 +02002337 break;
2338 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002339 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 +02002340 break;
2341 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002342 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002343 break;
2344 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002345 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002346 break;
2347 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002348 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 +02002349 break;
2350 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002351 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002352 break;
2353 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002354 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002355 break;
2356 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002357 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 +02002358 break;
2359 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002360 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002361 break;
2362 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002363 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002364 break;
2365 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002366 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002367 return LY_EVALID;
2368 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002369 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002370 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002371checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002372 /* mandatory substatements */
2373 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002374 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002375 return LY_EVALID;
2376 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002377 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
2378 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
2379 return LY_EVALID;
2380 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002381
2382 return ret;
2383}
2384
Michal Vaskoea5abea2018-09-18 13:10:54 +02002385/**
2386 * @brief Parse the max-elements statement.
2387 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002388 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002389 * @param[in,out] data Data to read from, always moved to currently handled character.
2390 * @param[in,out] max Value to write to.
2391 * @param[in,out] flags Flags to write to.
2392 * @param[in,out] exts Extension instances to add to.
2393 *
2394 * @return LY_ERR values.
2395 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002396static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002397parse_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 +02002398{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002399 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002400 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002401 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002402 unsigned long int num;
2403 enum yang_keyword kw;
2404
2405 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002406 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002407 return LY_EVALID;
2408 }
2409 *flags |= LYS_SET_MAX;
2410
2411 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002412 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002413
2414 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002415 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002416 free(buf);
2417 return LY_EVALID;
2418 }
2419
2420 if (strncmp(word, "unbounded", word_len)) {
2421 errno = 0;
2422 num = strtoul(word, &ptr, 10);
2423 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002424 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002425 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002426 free(buf);
2427 return LY_EVALID;
2428 }
2429 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002430 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002431 free(buf);
2432 return LY_EVALID;
2433 }
2434
2435 *max = num;
2436 }
2437 free(buf);
2438
Radek Krejci6d6556c2018-11-08 09:37:45 +01002439 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002440 switch (kw) {
2441 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002442 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002443 break;
2444 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002445 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002446 return LY_EVALID;
2447 }
2448 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002449 return ret;
2450}
2451
Michal Vaskoea5abea2018-09-18 13:10:54 +02002452/**
2453 * @brief Parse the min-elements statement.
2454 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002455 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002456 * @param[in,out] data Data to read from, always moved to currently handled character.
2457 * @param[in,out] min Value to write to.
2458 * @param[in,out] flags Flags to write to.
2459 * @param[in,out] exts Extension instances to add to.
2460 *
2461 * @return LY_ERR values.
2462 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002463static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002464parse_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 +02002465{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002466 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002467 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002468 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002469 unsigned long int num;
2470 enum yang_keyword kw;
2471
2472 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002473 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002474 return LY_EVALID;
2475 }
2476 *flags |= LYS_SET_MIN;
2477
2478 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002479 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002480
2481 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002482 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002483 free(buf);
2484 return LY_EVALID;
2485 }
2486
2487 errno = 0;
2488 num = strtoul(word, &ptr, 10);
2489 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002490 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002491 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002492 free(buf);
2493 return LY_EVALID;
2494 }
2495 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002496 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002497 free(buf);
2498 return LY_EVALID;
2499 }
2500 *min = num;
2501 free(buf);
2502
Radek Krejci6d6556c2018-11-08 09:37:45 +01002503 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002504 switch (kw) {
2505 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002506 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002507 break;
2508 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002509 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002510 return LY_EVALID;
2511 }
2512 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002513 return ret;
2514}
2515
Michal Vaskoea5abea2018-09-18 13:10:54 +02002516/**
2517 * @brief Parse the ordered-by statement.
2518 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002519 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002520 * @param[in,out] data Data to read from, always moved to currently handled character.
2521 * @param[in,out] flags Flags to write to.
2522 * @param[in,out] exts Extension instances to add to.
2523 *
2524 * @return LY_ERR values.
2525 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002526static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002527parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002528{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002529 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002530 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002531 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002532 enum yang_keyword kw;
2533
2534 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002535 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002536 return LY_EVALID;
2537 }
2538
2539 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002540 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002541
2542 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2543 *flags |= LYS_ORDBY_SYSTEM;
2544 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2545 *flags |= LYS_ORDBY_USER;
2546 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002547 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002548 free(buf);
2549 return LY_EVALID;
2550 }
2551 free(buf);
2552
Radek Krejci6d6556c2018-11-08 09:37:45 +01002553 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002554 switch (kw) {
2555 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002556 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002557 break;
2558 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002559 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002560 return LY_EVALID;
2561 }
2562 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002563 return ret;
2564}
2565
Michal Vaskoea5abea2018-09-18 13:10:54 +02002566/**
2567 * @brief Parse the leaf-list statement.
2568 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002569 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002570 * @param[in,out] data Data to read from, always moved to currently handled character.
2571 * @param[in,out] siblings Siblings to add to.
2572 *
2573 * @return LY_ERR values.
2574 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002575static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002576parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002577{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002578 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002579 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002580 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002581 enum yang_keyword kw;
2582 struct lysp_node *iter;
2583 struct lysp_node_leaflist *llist;
2584
2585 /* create structure */
2586 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002587 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002588 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002589 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002590
2591 /* insert into siblings */
2592 if (!*siblings) {
2593 *siblings = (struct lysp_node *)llist;
2594 } else {
2595 for (iter = *siblings; iter->next; iter = iter->next);
2596 iter->next = (struct lysp_node *)llist;
2597 }
2598
2599 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002600 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002601 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002602
2603 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002604 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002605 switch (kw) {
2606 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002607 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002608 break;
2609 case YANG_DEFAULT:
Radek Krejci10113652018-11-14 16:56:50 +01002610 YANG_CHECK_STMTVER_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002611 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 +02002612 break;
2613 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002614 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 +02002615 break;
2616 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002617 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 +02002618 break;
2619 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002620 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002621 break;
2622 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002623 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002624 break;
2625 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002626 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002627 break;
2628 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002629 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002630 break;
2631 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002632 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 +02002633 break;
2634 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002635 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636 break;
2637 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002638 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002639 break;
2640 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002641 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 +02002642 break;
2643 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002644 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002645 break;
2646 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002647 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002648 break;
2649 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002650 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002651 return LY_EVALID;
2652 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002653 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002654 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002655checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002656 /* mandatory substatements */
2657 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002658 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002659 return LY_EVALID;
2660 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002661 if ((llist->min) && (llist->dflts)) {
2662 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
2663 return LY_EVALID;
2664 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002665 if (llist->max && llist->min > llist->max) {
2666 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
2667 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2668 llist->min, llist->max);
2669 return LY_EVALID;
2670 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671
2672 return ret;
2673}
2674
Michal Vaskoea5abea2018-09-18 13:10:54 +02002675/**
2676 * @brief Parse the refine statement.
2677 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002678 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002679 * @param[in,out] data Data to read from, always moved to currently handled character.
2680 * @param[in,out] refines Refines to add to.
2681 *
2682 * @return LY_ERR values.
2683 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002684static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002685parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002686{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002687 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002688 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002689 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002690 enum yang_keyword kw;
2691 struct lysp_refine *rf;
2692
Radek Krejci2c4e7172018-10-19 15:56:26 +02002693 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002694
2695 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002696 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002697 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002698
Radek Krejci6d6556c2018-11-08 09:37:45 +01002699 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002700 switch (kw) {
2701 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002702 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002703 break;
2704 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002705 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 +02002706 break;
2707 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002708 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 +02002709 break;
2710 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01002711 YANG_CHECK_STMTVER_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002712 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 +02002713 break;
2714 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002715 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002716 break;
2717 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002718 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002719 break;
2720 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002721 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002722 break;
2723 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002724 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002725 break;
2726 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002727 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 +02002728 break;
2729 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002730 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 +02002731 break;
2732 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002733 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002734 break;
2735 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002736 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002737 return LY_EVALID;
2738 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002739 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002740 return ret;
2741}
2742
Michal Vaskoea5abea2018-09-18 13:10:54 +02002743/**
2744 * @brief Parse the typedef statement.
2745 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002746 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002747 * @param[in,out] data Data to read from, always moved to currently handled character.
2748 * @param[in,out] typedefs Typedefs to add to.
2749 *
2750 * @return LY_ERR values.
2751 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002752static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002753parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002754{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002755 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002756 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002757 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002758 enum yang_keyword kw;
2759 struct lysp_tpdf *tpdf;
2760
Radek Krejci2c4e7172018-10-19 15:56:26 +02002761 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002762
2763 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002764 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002765 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002766
2767 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002768 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002769 switch (kw) {
2770 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002771 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 +02002772 break;
2773 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002774 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 +02002775 break;
2776 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002777 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 +02002778 break;
2779 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002780 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002781 break;
2782 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002783 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002784 break;
2785 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002786 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 +02002787 break;
2788 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002789 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790 break;
2791 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002792 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002793 return LY_EVALID;
2794 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002795 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002796 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002797checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002798 /* mandatory substatements */
2799 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002800 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002801 return LY_EVALID;
2802 }
2803
Radek Krejcibbe09a92018-11-08 09:36:54 +01002804 /* store data for collision check */
2805 if (parent) {
2806 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2807 }
2808
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809 return ret;
2810}
2811
Michal Vaskoea5abea2018-09-18 13:10:54 +02002812/**
2813 * @brief Parse the input or output statement.
2814 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002815 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002816 * @param[in,out] data Data to read from, always moved to currently handled character.
2817 * @param[in] kw Type of this particular keyword
2818 * @param[in,out] inout_p Input/output pointer to write to.
2819 *
2820 * @return LY_ERR values.
2821 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002822static LY_ERR
Radek Krejci10113652018-11-14 16:56:50 +01002823parse_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 +02002824{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002825 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002826 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002827 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002828 struct lysp_action_inout *inout;
Radek Krejci10113652018-11-14 16:56:50 +01002829 enum yang_keyword kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002830
2831 if (*inout_p) {
Radek Krejci10113652018-11-14 16:56:50 +01002832 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002833 return LY_EVALID;
2834 }
2835
2836 /* create structure */
2837 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002838 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002839 *inout_p = inout;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002840 inout->nodetype = LYS_INOUT;
2841 inout->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002842
2843 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002844 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002845 switch (kw) {
2846 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01002847 YANG_CHECK_STMTVER_RET(ctx, "anydata", ly_stmt2str(inout_kw));
2848 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002849 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002850 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002851 break;
2852 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002853 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002854 break;
2855 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002856 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 break;
2858 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002859 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 break;
2861 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002862 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863 break;
2864 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002865 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002866 break;
2867 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002868 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002869 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002870 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002871 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout, data, &inout->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002872 break;
2873 case YANG_MUST:
Radek Krejci10113652018-11-14 16:56:50 +01002874 YANG_CHECK_STMTVER_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002875 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002876 break;
2877 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002878 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout, &inout->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002879 break;
2880 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002881 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002882 break;
2883 default:
Radek Krejci10113652018-11-14 16:56:50 +01002884 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002885 return LY_EVALID;
2886 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002887 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002888 return ret;
2889}
2890
Michal Vaskoea5abea2018-09-18 13:10:54 +02002891/**
2892 * @brief Parse the action statement.
2893 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002894 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002895 * @param[in,out] data Data to read from, always moved to currently handled character.
2896 * @param[in,out] actions Actions to add to.
2897 *
2898 * @return LY_ERR values.
2899 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002900static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002901parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002902{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002903 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002904 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002905 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002906 enum yang_keyword kw;
2907 struct lysp_action *act;
2908
Radek Krejci2c4e7172018-10-19 15:56:26 +02002909 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002910
2911 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002912 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002913 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002914 act->nodetype = LYS_ACTION;
2915 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002916
Radek Krejci6d6556c2018-11-08 09:37:45 +01002917 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918 switch (kw) {
2919 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002920 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 +02002921 break;
2922 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002923 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 +02002924 break;
2925 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002926 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 +02002927 break;
2928 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002929 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002930 break;
2931
2932 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002933 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002934 break;
2935 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002936 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002937 break;
2938
2939 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002940 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002941 break;
2942 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002943 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002944 break;
2945 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002946 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002947 break;
2948 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002949 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002950 return LY_EVALID;
2951 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002952 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002953 return ret;
2954}
2955
Michal Vaskoea5abea2018-09-18 13:10:54 +02002956/**
2957 * @brief Parse the notification statement.
2958 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002959 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002960 * @param[in,out] data Data to read from, always moved to currently handled character.
2961 * @param[in,out] notifs Notifications to add to.
2962 *
2963 * @return LY_ERR values.
2964 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002965static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002966parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002967{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002968 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002969 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002970 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002971 enum yang_keyword kw;
2972 struct lysp_notif *notif;
2973
Radek Krejci2c4e7172018-10-19 15:56:26 +02002974 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975
2976 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002977 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002978 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002979 notif->nodetype = LYS_NOTIF;
2980 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002981
Radek Krejci6d6556c2018-11-08 09:37:45 +01002982 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002983 switch (kw) {
2984 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002985 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 +02002986 break;
2987 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002988 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 +02002989 break;
2990 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002991 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 +02002992 break;
2993 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002994 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002995 break;
2996
2997 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01002998 YANG_CHECK_STMTVER_RET(ctx, "anydata", "notification");
2999 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003000 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003001 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003002 break;
3003 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003004 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003005 break;
3006 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003007 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003008 break;
3009 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003010 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003011 break;
3012 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003013 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003014 break;
3015 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003016 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003017 break;
3018 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003019 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003020 break;
3021
3022 case YANG_MUST:
Radek Krejci10113652018-11-14 16:56:50 +01003023 YANG_CHECK_STMTVER_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003024 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003025 break;
3026 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003027 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003028 break;
3029 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003030 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003031 break;
3032 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003033 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003034 break;
3035 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003036 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003037 return LY_EVALID;
3038 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003039 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003040 return ret;
3041}
3042
Michal Vaskoea5abea2018-09-18 13:10:54 +02003043/**
3044 * @brief Parse the grouping statement.
3045 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003046 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003047 * @param[in,out] data Data to read from, always moved to currently handled character.
3048 * @param[in,out] groupings Groupings to add to.
3049 *
3050 * @return LY_ERR values.
3051 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003052static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003053parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003054{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003055 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003056 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003057 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003058 enum yang_keyword kw;
3059 struct lysp_grp *grp;
3060
Radek Krejci2c4e7172018-10-19 15:56:26 +02003061 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003062
3063 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003064 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003065 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003066 grp->nodetype = LYS_GROUPING;
3067 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003068
Radek Krejci6d6556c2018-11-08 09:37:45 +01003069 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003070 switch (kw) {
3071 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003072 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 +02003073 break;
3074 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003075 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 +02003076 break;
3077 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003078 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079 break;
3080
3081 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003082 YANG_CHECK_STMTVER_RET(ctx, "anydata", "grouping");
3083 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003084 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003085 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003086 break;
3087 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003088 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003089 break;
3090 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003091 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003092 break;
3093 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003094 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003095 break;
3096 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003097 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003098 break;
3099 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003100 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003101 break;
3102 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003103 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003104 break;
3105
3106 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003107 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003108 break;
3109 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003110 YANG_CHECK_STMTVER_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003111 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003112 break;
3113 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003114 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003115 break;
3116 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003117 YANG_CHECK_STMTVER_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003118 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003119 break;
3120 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003121 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003122 break;
3123 default:
Radek Krejci10113652018-11-14 16:56:50 +01003124 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003125 return LY_EVALID;
3126 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003127 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003128 return ret;
3129}
3130
Michal Vaskoea5abea2018-09-18 13:10:54 +02003131/**
3132 * @brief Parse the refine statement.
3133 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003134 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003135 * @param[in,out] data Data to read from, always moved to currently handled character.
3136 * @param[in,out] augments Augments to add to.
3137 *
3138 * @return LY_ERR values.
3139 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003140static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003141parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003142{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003143 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003144 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003145 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003146 enum yang_keyword kw;
3147 struct lysp_augment *aug;
3148
Radek Krejci2c4e7172018-10-19 15:56:26 +02003149 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003150
3151 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003152 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003153 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003154 aug->nodetype = LYS_AUGMENT;
3155 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003156
Radek Krejci6d6556c2018-11-08 09:37:45 +01003157 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003158 switch (kw) {
3159 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003160 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 +02003161 break;
3162 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003163 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 +02003164 break;
3165 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003166 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 +02003167 break;
3168 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003169 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003170 break;
3171 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003172 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003173 break;
3174
3175 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003176 YANG_CHECK_STMTVER_RET(ctx, "anydata", "augment");
3177 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003178 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003179 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003180 break;
3181 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003182 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003183 break;
3184 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003185 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003186 break;
3187 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003188 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003189 break;
3190 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003191 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003192 break;
3193 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003194 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003195 break;
3196 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003197 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003198 break;
3199 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003200 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003201 break;
3202
3203 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003204 YANG_CHECK_STMTVER_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003205 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003206 break;
3207 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003208 YANG_CHECK_STMTVER_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003209 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003210 break;
3211 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003212 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003213 break;
3214 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003215 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003216 return LY_EVALID;
3217 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003218 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003219 return ret;
3220}
3221
Michal Vaskoea5abea2018-09-18 13:10:54 +02003222/**
3223 * @brief Parse the uses statement.
3224 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003225 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003226 * @param[in,out] data Data to read from, always moved to currently handled character.
3227 * @param[in,out] siblings Siblings to add to.
3228 *
3229 * @return LY_ERR values.
3230 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003231static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003232parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003233{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003234 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003235 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003236 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003237 enum yang_keyword kw;
3238 struct lysp_node *iter;
3239 struct lysp_node_uses *uses;
3240
3241 /* create structure */
3242 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003243 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003244 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003245 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003246
3247 /* insert into siblings */
3248 if (!*siblings) {
3249 *siblings = (struct lysp_node *)uses;
3250 } else {
3251 for (iter = *siblings; iter->next; iter = iter->next);
3252 iter->next = (struct lysp_node *)uses;
3253 }
3254
3255 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003256 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003257 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003258
3259 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003260 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003261 switch (kw) {
3262 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003263 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 +02003264 break;
3265 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003266 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 +02003267 break;
3268 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003269 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 +02003270 break;
3271 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003272 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003273 break;
3274 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003275 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003276 break;
3277
3278 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003279 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003280 break;
3281 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003282 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003283 break;
3284 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003285 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003286 break;
3287 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003288 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003289 return LY_EVALID;
3290 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003291 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003292 return ret;
3293}
3294
Michal Vaskoea5abea2018-09-18 13:10:54 +02003295/**
3296 * @brief Parse the case statement.
3297 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003298 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003299 * @param[in,out] data Data to read from, always moved to currently handled character.
3300 * @param[in,out] siblings Siblings to add to.
3301 *
3302 * @return LY_ERR values.
3303 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003304static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003305parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003306{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003307 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003308 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003309 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003310 enum yang_keyword kw;
3311 struct lysp_node *iter;
3312 struct lysp_node_case *cas;
3313
3314 /* create structure */
3315 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003316 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003317 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003318 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003319
3320 /* insert into siblings */
3321 if (!*siblings) {
3322 *siblings = (struct lysp_node *)cas;
3323 } else {
3324 for (iter = *siblings; iter->next; iter = iter->next);
3325 iter->next = (struct lysp_node *)cas;
3326 }
3327
3328 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003329 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003330 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003331
3332 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003333 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003334 switch (kw) {
3335 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003336 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 +02003337 break;
3338 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003339 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 +02003340 break;
3341 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003342 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 +02003343 break;
3344 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003345 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003346 break;
3347 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003348 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003349 break;
3350
3351 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003352 YANG_CHECK_STMTVER_RET(ctx, "anydata", "case");
3353 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003354 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003355 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003356 break;
3357 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003358 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003359 break;
3360 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003361 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003362 break;
3363 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003364 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003365 break;
3366 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003367 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003368 break;
3369 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003370 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003371 break;
3372 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003373 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003374 break;
3375 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003376 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003377 break;
3378 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003379 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003380 return LY_EVALID;
3381 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003382 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003383 return ret;
3384}
3385
Michal Vaskoea5abea2018-09-18 13:10:54 +02003386/**
3387 * @brief Parse the choice statement.
3388 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003389 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003390 * @param[in,out] data Data to read from, always moved to currently handled character.
3391 * @param[in,out] siblings Siblings to add to.
3392 *
3393 * @return LY_ERR values.
3394 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003395static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003396parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003397{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003398 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003399 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003400 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003401 enum yang_keyword kw;
3402 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003403 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003404
3405 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003406 choice = calloc(1, sizeof *choice);
3407 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3408 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003409 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003410
3411 /* insert into siblings */
3412 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003413 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003414 } else {
3415 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003416 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003417 }
3418
3419 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003420 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003421 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422
3423 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003424 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003425 switch (kw) {
3426 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003427 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003428 break;
3429 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003430 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 +02003431 break;
3432 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003433 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 +02003434 break;
3435 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003436 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003437 break;
3438 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003439 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 +02003440 break;
3441 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003442 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003443 break;
3444 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003445 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003446 break;
3447 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003448 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 +02003449 break;
3450
3451 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003452 YANG_CHECK_STMTVER_RET(ctx, "anydata", "choice");
3453 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003454 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003455 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003456 break;
3457 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003458 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003459 break;
3460 case YANG_CHOICE:
Radek Krejci10113652018-11-14 16:56:50 +01003461 YANG_CHECK_STMTVER_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003462 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003463 break;
3464 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003465 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003466 break;
3467 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003468 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003469 break;
3470 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003471 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003472 break;
3473 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003474 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003475 break;
3476 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003477 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003478 break;
3479 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003480 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003481 return LY_EVALID;
3482 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003484 return ret;
3485}
3486
Michal Vaskoea5abea2018-09-18 13:10:54 +02003487/**
3488 * @brief Parse the container statement.
3489 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003490 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003491 * @param[in,out] data Data to read from, always moved to currently handled character.
3492 * @param[in,out] siblings Siblings to add to.
3493 *
3494 * @return LY_ERR values.
3495 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003496static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003497parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003498{
3499 LY_ERR ret = 0;
3500 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003501 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003502 enum yang_keyword kw;
3503 struct lysp_node *iter;
3504 struct lysp_node_container *cont;
3505
3506 /* create structure */
3507 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003508 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003509 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003510 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003511
3512 /* insert into siblings */
3513 if (!*siblings) {
3514 *siblings = (struct lysp_node *)cont;
3515 } else {
3516 for (iter = *siblings; iter->next; iter = iter->next);
3517 iter->next = (struct lysp_node *)cont;
3518 }
3519
3520 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003521 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003522 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003523
3524 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003525 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003526 switch (kw) {
3527 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003528 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003529 break;
3530 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003531 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 +02003532 break;
3533 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003534 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 +02003535 break;
3536 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003537 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 +02003538 break;
3539 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003540 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003541 break;
3542 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003543 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003544 break;
3545 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003546 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 +02003547 break;
3548
3549 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003550 YANG_CHECK_STMTVER_RET(ctx, "anydata", "container");
3551 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003552 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003553 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003554 break;
3555 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003556 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003557 break;
3558 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003559 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003560 break;
3561 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003562 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563 break;
3564 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003565 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003566 break;
3567 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003568 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569 break;
3570 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003571 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003572 break;
3573
3574 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003575 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003576 break;
3577 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003578 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003579 break;
3580 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003581 YANG_CHECK_STMTVER_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003582 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003583 break;
3584 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003585 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003586 break;
3587 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003588 YANG_CHECK_STMTVER_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003589 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590 break;
3591 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003592 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003593 break;
3594 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003595 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003596 return LY_EVALID;
3597 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003598 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003599 return ret;
3600}
3601
Michal Vaskoea5abea2018-09-18 13:10:54 +02003602/**
3603 * @brief Parse the list statement.
3604 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003605 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003606 * @param[in,out] data Data to read from, always moved to currently handled character.
3607 * @param[in,out] siblings Siblings to add to.
3608 *
3609 * @return LY_ERR values.
3610 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003611static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003612parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003614 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003615 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003616 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003617 enum yang_keyword kw;
3618 struct lysp_node *iter;
3619 struct lysp_node_list *list;
3620
3621 /* create structure */
3622 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003623 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003624 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003625 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003626
3627 /* insert into siblings */
3628 if (!*siblings) {
3629 *siblings = (struct lysp_node *)list;
3630 } else {
3631 for (iter = *siblings; iter->next; iter = iter->next);
3632 iter->next = (struct lysp_node *)list;
3633 }
3634
3635 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003636 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003637 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003638
3639 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003640 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003641 switch (kw) {
3642 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003643 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003644 break;
3645 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003646 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 +02003647 break;
3648 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003649 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 +02003650 break;
3651 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003652 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 +02003653 break;
3654 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003655 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003656 break;
3657 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003658 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003659 break;
3660 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003661 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 +02003662 break;
3663 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003664 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003665 break;
3666 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003667 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003668 break;
3669 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003670 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003671 break;
3672 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003673 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 +02003674 break;
3675
3676 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003677 YANG_CHECK_STMTVER_RET(ctx, "anydata", "list");
3678 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003679 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003680 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003681 break;
3682 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003683 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003684 break;
3685 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003686 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003687 break;
3688 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003689 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003690 break;
3691 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003692 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003693 break;
3694 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003695 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003696 break;
3697 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003698 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003699 break;
3700
3701 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003702 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003703 break;
3704 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003705 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003706 break;
3707 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003708 YANG_CHECK_STMTVER_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003709 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003710 break;
3711 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003712 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003713 break;
3714 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003715 YANG_CHECK_STMTVER_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003716 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003717 break;
3718 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003719 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003720 break;
3721 default:
Radek Krejci10113652018-11-14 16:56:50 +01003722 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003723 return LY_EVALID;
3724 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003726 LY_CHECK_RET(ret);
3727checks:
3728 if (list->max && list->min > list->max) {
3729 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
3730 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3731 list->min, list->max);
3732 return LY_EVALID;
3733 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003734
3735 return ret;
3736}
3737
Michal Vaskoea5abea2018-09-18 13:10:54 +02003738/**
3739 * @brief Parse the yin-element statement.
3740 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003741 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003742 * @param[in,out] data Data to read from, always moved to currently handled character.
3743 * @param[in,out] flags Flags to write to.
3744 * @param[in,out] exts Extension instances to add to.
3745 *
3746 * @return LY_ERR values.
3747 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003748static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003749parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003750{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003751 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003752 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003753 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003754 enum yang_keyword kw;
3755
3756 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003757 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003758 return LY_EVALID;
3759 }
3760
3761 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003762 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003763
3764 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3765 *flags |= LYS_YINELEM_TRUE;
3766 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3767 *flags |= LYS_YINELEM_FALSE;
3768 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003769 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003770 free(buf);
3771 return LY_EVALID;
3772 }
3773 free(buf);
3774
Radek Krejci6d6556c2018-11-08 09:37:45 +01003775 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003776 switch (kw) {
3777 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003778 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3779 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003780 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003781 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003782 return LY_EVALID;
3783 }
3784 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003785 return ret;
3786}
3787
Michal Vaskoea5abea2018-09-18 13:10:54 +02003788/**
3789 * @brief Parse the yin-element statement.
3790 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003791 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003792 * @param[in,out] data Data to read from, always moved to currently handled character.
3793 * @param[in,out] argument Value to write to.
3794 * @param[in,out] flags Flags to write to.
3795 * @param[in,out] exts Extension instances to add to.
3796 *
3797 * @return LY_ERR values.
3798 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003799static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003800parse_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 +02003801{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003802 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003803 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003804 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003805 enum yang_keyword kw;
3806
3807 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003808 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003809 return LY_EVALID;
3810 }
3811
3812 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003813 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003814 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003815
Radek Krejci6d6556c2018-11-08 09:37:45 +01003816 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003817 switch (kw) {
3818 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003819 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003820 break;
3821 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003822 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003823 break;
3824 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003825 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003826 return LY_EVALID;
3827 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003828 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003829 return ret;
3830}
3831
Michal Vaskoea5abea2018-09-18 13:10:54 +02003832/**
3833 * @brief Parse the extension statement.
3834 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003835 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003836 * @param[in,out] data Data to read from, always moved to currently handled character.
3837 * @param[in,out] extensions Extensions to add to.
3838 *
3839 * @return LY_ERR values.
3840 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003841static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003842parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003843{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003844 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003845 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003846 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003847 enum yang_keyword kw;
3848 struct lysp_ext *ex;
3849
Radek Krejci2c4e7172018-10-19 15:56:26 +02003850 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003851
3852 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003853 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003854 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003855
Radek Krejci6d6556c2018-11-08 09:37:45 +01003856 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857 switch (kw) {
3858 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003859 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 +02003860 break;
3861 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003862 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 +02003863 break;
3864 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003865 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003866 break;
3867 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003868 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003869 break;
3870 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003871 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003872 break;
3873 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003874 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875 return LY_EVALID;
3876 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003877 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003878 return ret;
3879}
3880
Michal Vaskoea5abea2018-09-18 13:10:54 +02003881/**
3882 * @brief Parse the deviate statement.
3883 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003884 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003885 * @param[in,out] data Data to read from, always moved to currently handled character.
3886 * @param[in,out] deviates Deviates to add to.
3887 *
3888 * @return LY_ERR values.
3889 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003890static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003891parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003892{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003893 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003894 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003895 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003896 enum yang_keyword kw;
3897 struct lysp_deviate *iter, *d;
3898 struct lysp_deviate_add *d_add = NULL;
3899 struct lysp_deviate_rpl *d_rpl = NULL;
3900 struct lysp_deviate_del *d_del = NULL;
3901 const char **d_units, ***d_uniques, ***d_dflts;
3902 struct lysp_restr **d_musts;
3903 uint16_t *d_flags;
3904 uint32_t *d_min, *d_max;
3905
3906 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003907 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908
3909 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3910 dev_mod = LYS_DEV_NOT_SUPPORTED;
3911 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3912 dev_mod = LYS_DEV_ADD;
3913 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3914 dev_mod = LYS_DEV_REPLACE;
3915 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3916 dev_mod = LYS_DEV_DELETE;
3917 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003918 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003919 free(buf);
3920 return LY_EVALID;
3921 }
3922 free(buf);
3923
3924 /* create structure */
3925 switch (dev_mod) {
3926 case LYS_DEV_NOT_SUPPORTED:
3927 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003928 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003929 break;
3930 case LYS_DEV_ADD:
3931 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003932 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003933 d = (struct lysp_deviate *)d_add;
3934 d_units = &d_add->units;
3935 d_uniques = &d_add->uniques;
3936 d_dflts = &d_add->dflts;
3937 d_musts = &d_add->musts;
3938 d_flags = &d_add->flags;
3939 d_min = &d_add->min;
3940 d_max = &d_add->max;
3941 break;
3942 case LYS_DEV_REPLACE:
3943 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003944 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003945 d = (struct lysp_deviate *)d_rpl;
3946 d_units = &d_rpl->units;
3947 d_flags = &d_rpl->flags;
3948 d_min = &d_rpl->min;
3949 d_max = &d_rpl->max;
3950 break;
3951 case LYS_DEV_DELETE:
3952 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003953 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003954 d = (struct lysp_deviate *)d_del;
3955 d_units = &d_del->units;
3956 d_uniques = &d_del->uniques;
3957 d_dflts = &d_del->dflts;
3958 d_musts = &d_del->musts;
3959 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003960 break;
3961 default:
3962 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003963 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003964 }
3965 d->mod = dev_mod;
3966
3967 /* insert into siblings */
3968 if (!*deviates) {
3969 *deviates = d;
3970 } else {
3971 for (iter = *deviates; iter->next; iter = iter->next);
3972 iter->next = d;
3973 }
3974
Radek Krejci6d6556c2018-11-08 09:37:45 +01003975 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003976 switch (kw) {
3977 case YANG_CONFIG:
3978 switch (dev_mod) {
3979 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003980 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003981 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003982 return LY_EVALID;
3983 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003984 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003985 break;
3986 }
3987 break;
3988 case YANG_DEFAULT:
3989 switch (dev_mod) {
3990 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003991 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003992 return LY_EVALID;
3993 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003994 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 +02003995 break;
3996 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003997 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 +02003998 break;
3999 }
4000 break;
4001 case YANG_MANDATORY:
4002 switch (dev_mod) {
4003 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004004 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004005 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004006 return LY_EVALID;
4007 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004008 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004009 break;
4010 }
4011 break;
4012 case YANG_MAX_ELEMENTS:
4013 switch (dev_mod) {
4014 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004015 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004016 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017 return LY_EVALID;
4018 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004019 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004020 break;
4021 }
4022 break;
4023 case YANG_MIN_ELEMENTS:
4024 switch (dev_mod) {
4025 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004026 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004027 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004028 return LY_EVALID;
4029 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004030 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004031 break;
4032 }
4033 break;
4034 case YANG_MUST:
4035 switch (dev_mod) {
4036 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004037 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004038 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004039 return LY_EVALID;
4040 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004041 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004042 break;
4043 }
4044 break;
4045 case YANG_TYPE:
4046 switch (dev_mod) {
4047 case LYS_DEV_NOT_SUPPORTED:
4048 case LYS_DEV_ADD:
4049 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004050 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004051 return LY_EVALID;
4052 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004053 if (d_rpl->type) {
4054 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4055 return LY_EVALID;
4056 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004057 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004058 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004059 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004060 break;
4061 }
4062 break;
4063 case YANG_UNIQUE:
4064 switch (dev_mod) {
4065 case LYS_DEV_NOT_SUPPORTED:
4066 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004067 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004068 return LY_EVALID;
4069 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004070 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 +02004071 break;
4072 }
4073 break;
4074 case YANG_UNITS:
4075 switch (dev_mod) {
4076 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004077 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004078 return LY_EVALID;
4079 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004080 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 +02004081 break;
4082 }
4083 break;
4084 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004085 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004086 break;
4087 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004088 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004089 return LY_EVALID;
4090 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004091 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004092 return ret;
4093}
4094
Michal Vaskoea5abea2018-09-18 13:10:54 +02004095/**
4096 * @brief Parse the deviation statement.
4097 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004098 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004099 * @param[in,out] data Data to read from, always moved to currently handled character.
4100 * @param[in,out] deviations Deviations to add to.
4101 *
4102 * @return LY_ERR values.
4103 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004104static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004105parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004106{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004107 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004108 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004109 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004110 enum yang_keyword kw;
4111 struct lysp_deviation *dev;
4112
Radek Krejci2c4e7172018-10-19 15:56:26 +02004113 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004114
4115 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004116 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004117 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004118
Radek Krejci6d6556c2018-11-08 09:37:45 +01004119 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004120 switch (kw) {
4121 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004122 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 +02004123 break;
4124 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004125 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004126 break;
4127 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004128 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 +02004129 break;
4130 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004131 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004132 break;
4133 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004134 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004135 return LY_EVALID;
4136 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004137 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004138 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004139checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004140 /* mandatory substatements */
4141 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004142 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004143 return LY_EVALID;
4144 }
4145
4146 return ret;
4147}
4148
Michal Vaskoea5abea2018-09-18 13:10:54 +02004149/**
4150 * @brief Parse the feature statement.
4151 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004152 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004153 * @param[in,out] data Data to read from, always moved to currently handled character.
4154 * @param[in,out] features Features to add to.
4155 *
4156 * @return LY_ERR values.
4157 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004158static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004159parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004160{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004161 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004162 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004163 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004164 enum yang_keyword kw;
4165 struct lysp_feature *feat;
4166
Radek Krejci2c4e7172018-10-19 15:56:26 +02004167 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004168
4169 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004170 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004171 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004172
Radek Krejci6d6556c2018-11-08 09:37:45 +01004173 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004174 switch (kw) {
4175 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004176 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 +02004177 break;
4178 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004179 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 +02004180 break;
4181 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004182 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 +02004183 break;
4184 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004185 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004186 break;
4187 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004188 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004189 break;
4190 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004191 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004192 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004193 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004194 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004195 return ret;
4196}
4197
Michal Vaskoea5abea2018-09-18 13:10:54 +02004198/**
4199 * @brief Parse the identity statement.
4200 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004201 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004202 * @param[in,out] data Data to read from, always moved to currently handled character.
4203 * @param[in,out] identities Identities to add to.
4204 *
4205 * @return LY_ERR values.
4206 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004207static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004208parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004209{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004210 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004211 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004212 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004213 enum yang_keyword kw;
4214 struct lysp_ident *ident;
4215
Radek Krejci2c4e7172018-10-19 15:56:26 +02004216 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004217
4218 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004219 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004220 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004221
Radek Krejci6d6556c2018-11-08 09:37:45 +01004222 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004223 switch (kw) {
4224 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004225 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 +02004226 break;
4227 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01004228 YANG_CHECK_STMTVER_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004229 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 +02004230 break;
4231 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004232 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 +02004233 break;
4234 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004235 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236 break;
4237 case YANG_BASE:
Radek Krejci10113652018-11-14 16:56:50 +01004238 if (ident->bases && ctx->mod->version < 2) {
4239 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4240 return LY_EVALID;
4241 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004242 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 +02004243 break;
4244 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004245 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004246 break;
4247 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004248 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004249 return LY_EVALID;
4250 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004251 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004252 return ret;
4253}
4254
Michal Vaskoea5abea2018-09-18 13:10:54 +02004255/**
4256 * @brief Parse the module or submodule statement.
4257 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004258 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004259 * @param[in,out] data Data to read from, always moved to currently handled character.
4260 * @param[in,out] mod Module to write to.
4261 *
4262 * @return LY_ERR values.
4263 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004264static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004265parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004266{
4267 LY_ERR ret = 0;
4268 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004269 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004270 enum yang_keyword kw, prev_kw = 0;
4271 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejcie9e987e2018-10-31 12:50:27 +01004272 struct lysp_module *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004273
4274 /* (sub)module name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004275 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004276 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004277
Radek Krejci6d6556c2018-11-08 09:37:45 +01004278 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004279
Radek Krejcie3846472018-10-15 15:24:51 +02004280#define CHECK_ORDER(SECTION) \
4281 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4282
Michal Vasko7fbc8162018-09-17 10:35:16 +02004283 switch (kw) {
4284 /* module header */
4285 case YANG_NAMESPACE:
4286 case YANG_PREFIX:
4287 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004288 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004289 return LY_EVALID;
4290 }
Radek Krejcie3846472018-10-15 15:24:51 +02004291 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4292 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004293 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004294 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004295 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004296 return LY_EVALID;
4297 }
Radek Krejcie3846472018-10-15 15:24:51 +02004298 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4299 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004300 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004301 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004302 break;
4303 /* linkage */
4304 case YANG_INCLUDE:
4305 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004306 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004307 break;
4308 /* meta */
4309 case YANG_ORGANIZATION:
4310 case YANG_CONTACT:
4311 case YANG_DESCRIPTION:
4312 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004313 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004314 break;
4315
4316 /* revision */
4317 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004318 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004319 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004320 /* body */
4321 case YANG_ANYDATA:
4322 case YANG_ANYXML:
4323 case YANG_AUGMENT:
4324 case YANG_CHOICE:
4325 case YANG_CONTAINER:
4326 case YANG_DEVIATION:
4327 case YANG_EXTENSION:
4328 case YANG_FEATURE:
4329 case YANG_GROUPING:
4330 case YANG_IDENTITY:
4331 case YANG_LEAF:
4332 case YANG_LEAF_LIST:
4333 case YANG_LIST:
4334 case YANG_NOTIFICATION:
4335 case YANG_RPC:
4336 case YANG_TYPEDEF:
4337 case YANG_USES:
4338 case YANG_CUSTOM:
4339 mod_stmt = Y_MOD_BODY;
4340 break;
4341 default:
4342 /* error handled in the next switch */
4343 break;
4344 }
Radek Krejcie3846472018-10-15 15:24:51 +02004345#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004346
Radek Krejcie3846472018-10-15 15:24:51 +02004347 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004348 switch (kw) {
4349 /* module header */
4350 case YANG_YANG_VERSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004351 LY_CHECK_RET(parse_yangversion(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004352 break;
4353 case YANG_NAMESPACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004354 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 +02004355 break;
4356 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004357 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 +02004358 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004359 break;
4360 case YANG_BELONGS_TO:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004361 LY_CHECK_RET(parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004362 break;
4363
4364 /* linkage */
4365 case YANG_INCLUDE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004366 LY_CHECK_RET(parse_include(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004367 break;
4368 case YANG_IMPORT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004369 LY_CHECK_RET(parse_import(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004370 break;
4371
4372 /* meta */
4373 case YANG_ORGANIZATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004374 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 +02004375 break;
4376 case YANG_CONTACT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004377 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 +02004378 break;
4379 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004380 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 +02004381 break;
4382 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004383 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 +02004384 break;
4385
4386 /* revision */
4387 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004388 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004389 break;
4390
4391 /* body */
4392 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01004393 YANG_CHECK_STMTVER_RET(ctx, "anydata", mod->submodule ? "submodule" : "module");
4394 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004395 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004396 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004397 break;
4398 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004399 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004400 break;
4401 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004402 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004403 break;
4404 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004405 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004406 break;
4407 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004408 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004409 break;
4410 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004411 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004412 break;
4413 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004414 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004415 break;
4416
4417 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004418 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004419 break;
4420 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004421 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422 break;
4423 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004424 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004425 break;
4426 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004427 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428 break;
4429 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004430 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004431 break;
4432 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004433 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004434 break;
4435 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004436 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004437 break;
4438 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004439 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004440 break;
4441 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004442 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004443 break;
4444 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004445 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004446 break;
4447
4448 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004449 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004450 return LY_EVALID;
4451 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004452 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004453 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004454checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004455 /* mandatory substatements */
4456 if (mod->submodule) {
4457 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004458 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004459 return LY_EVALID;
4460 }
4461 } else {
4462 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004463 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004464 return LY_EVALID;
4465 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004466 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004467 return LY_EVALID;
4468 }
4469 }
4470
Radek Krejcie9e987e2018-10-31 12:50:27 +01004471 /* submodules share the namespace with the module names, so there must not be
4472 * a submodule of the same name in the context, no need for revision matching */
4473 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL);
4474 if (dup && (!mod->submodule || strcmp(dup->belongsto, mod->belongsto))) {
4475 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4476 mod->submodule ? "submodules" : "module and submodule", mod->name);
4477 return LY_EVALID;
4478 }
4479
Michal Vasko7fbc8162018-09-17 10:35:16 +02004480 return ret;
4481}
4482
Radek Krejcid4557c62018-09-17 11:42:09 +02004483LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01004484yang_parse(struct ly_parser_ctx *context, const char *data, struct lysp_module **mod_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004485{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004486 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004487 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004488 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004489 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004490 struct lysp_module *mod = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004491
4492 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004493 ret = get_keyword(context, &data, &kw, &word, &word_len);
4494 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004495
4496 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004497 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004498 ly_stmt2str(kw));
Radek Krejcibbe09a92018-11-08 09:36:54 +01004499 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004500 }
4501
4502 mod = calloc(1, sizeof *mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004503 LY_CHECK_ERR_GOTO(!mod, LOGMEM(context->ctx), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004504 if (kw == YANG_SUBMODULE) {
4505 mod->submodule = 1;
4506 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01004507 mod->parsing = 1;
4508 mod->ctx = context->ctx;
4509 context->mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004510
4511 /* substatements */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004512 ret = parse_sub_module(context, &data, mod);
4513 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004514
4515 /* read some trailing spaces or new lines */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004516 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4517 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004518
4519 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004520 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004521 word_len, word);
4522 free(buf);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004523 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004524 }
4525 assert(!buf);
4526
Radek Krejcibbe09a92018-11-08 09:36:54 +01004527 mod->parsing = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004528 *mod_p = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004529
Radek Krejcibbe09a92018-11-08 09:36:54 +01004530cleanup:
4531 if (ret) {
4532 lysp_module_free(mod);
4533 }
4534
Michal Vasko7fbc8162018-09-17 10:35:16 +02004535 return ret;
4536}