blob: 64cb3303a43f3978dca26b298dfd2af289927ea4 [file] [log] [blame]
Michal Vasko7fbc8162018-09-17 10:35:16 +02001/**
2 * @file parser_yang.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YANG parser
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <errno.h>
22#include <ctype.h>
23#include <string.h>
24#include <dirent.h>
25#include <assert.h>
26
27#include "common.h"
28#include "context.h"
29#include "libyang.h"
Radek Krejci70853c52018-10-15 14:46:16 +020030#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020031
32/* Macro to check YANG's yang-char grammar rule */
33#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
34 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
35 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
36 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
37 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
38 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
39 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
40 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
41 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
42 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
43
44/* These 2 macros checks YANG's identifier grammar rule */
45#define is_yangidentstartchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
46#define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
47 c == '_' || c == '-' || c == '.')
48
Radek Krejcifaa1eac2018-10-30 14:34:55 +010049#define CHECK_UNIQUENESS(CTX, ARRAY, MEMBER, STMT, IDENT) \
50 if (ARRAY) { \
51 for (unsigned int u = 0; u < LY_ARRAY_SIZE(ARRAY) - 1; ++u) { \
52 if (!strcmp((ARRAY)[u].MEMBER, IDENT)) { \
53 LOGVAL_YANG(CTX, LY_VCODE_DUPIDENT, IDENT, STMT); \
54 return LY_EVALID; \
55 } \
56 } \
57 }
58
Radek Krejci9fcacc12018-10-11 15:59:11 +020059#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
60 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
61 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020062
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020063#define MOVE_INPUT(CTX, DATA, COUNT) (*(data))+=COUNT;(CTX)->indent+=COUNT
64
Michal Vaskoea5abea2018-09-18 13:10:54 +020065/**
66 * @brief Loop through all substatements providing, return if there are none.
67 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020068 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020069 * @param[in] DATA Raw data to read from.
70 * @param[out] KW YANG keyword read.
71 * @param[out] WORD Pointer to the keyword itself.
72 * @param[out] WORD_LEN Length of the keyword.
73 * @param[out] ERR Variable for error storing.
74 *
75 * @return In case there are no substatements or a fatal error encountered.
76 */
Radek Krejci6d6556c2018-11-08 09:37:45 +010077#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010078 LY_CHECK_RET(get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020079 if (KW == YANG_SEMICOLON) { \
Radek Krejci6d6556c2018-11-08 09:37:45 +010080 CHECKGOTO; \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010081 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +020082 } \
83 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020084 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020085 return LY_EVALID; \
86 } \
87 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
88 !ERR && (KW != YANG_RIGHT_BRACE); \
89 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
90
Radek Krejci10113652018-11-14 16:56:50 +010091#define YANG_CHECK_STMTVER_RET(CTX, KW, PARENT) \
92 if ((CTX)->mod->version < 2) {LOGVAL_YANG((CTX), LY_VCODE_INCHILDSTMT2, KW, PARENT); return LY_EVALID;}
93
Radek Krejci6d9b9b52018-11-02 12:43:39 +010094static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
95static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
96static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
97static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
98static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
99static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200100
Michal Vaskoea5abea2018-09-18 13:10:54 +0200101/**
102 * @brief Add another character to dynamic buffer, a low-level function.
103 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200104 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200105 *
Radek Krejci404251e2018-10-09 12:06:44 +0200106 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200107 * @param[in, out] input Input string to process.
108 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200109 * @param[in,out] buf Buffer to use, can be moved by realloc().
110 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200111 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200112 *
113 * @return LY_ERR values.
114 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200115static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200116buf_add_char(struct ly_ctx *ctx, const char **input, size_t len, char **buf, size_t *buf_len, size_t *buf_used)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200117{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200118 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200119 *buf_len += 16;
120 *buf = ly_realloc(*buf, *buf_len);
121 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
122 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200123 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200124
Radek Krejci44ceedc2018-10-02 15:54:31 +0200125 (*buf_used) += len;
126 (*input) += len;
127
Michal Vasko7fbc8162018-09-17 10:35:16 +0200128 return LY_SUCCESS;
129}
130
Michal Vaskoea5abea2018-09-18 13:10:54 +0200131/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200132 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200133 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200134 * @param[in] ctx yang parser context for logging.
135 * @param[in] c UTF8 code point of a character to check.
136 * @return LY_ERR values.
137 */
138static LY_ERR
139check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
140{
141 if (!is_yangutf8char(c)) {
142 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
143 return LY_EVALID;
144 }
145 return LY_SUCCESS;
146}
147
148/**
149 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
150 *
151 * @param[in] ctx yang parser context for logging.
152 * @param[in] c UTF8 code point of a character to check.
153 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200154 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
155 * 0 - colon not yet found (no prefix)
156 * 1 - \p c is the colon character
157 * 2 - prefix already processed, now processing the identifier
158 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200159 * If the identifier cannot be prefixed, NULL is expected.
160 * @return LY_ERR values.
161 */
162static LY_ERR
163check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
164{
165 if (first || (prefix && (*prefix) == 1)) {
166 if (!is_yangidentstartchar(c)) {
167 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
168 return LY_EVALID;
169 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200170 if (prefix) {
171 if (first) {
172 (*prefix) = 0;
173 } else {
174 (*prefix) = 2;
175 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200176 }
177 } else if (c == ':' && prefix && (*prefix) == 0) {
178 (*prefix) = 1;
179 } else if (!is_yangidentchar(c)) {
180 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
181 return LY_EVALID;
182 }
183
184 return LY_SUCCESS;
185}
186
187/**
188 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
189 *
190 * @param[in] ctx yang parser context for logging.
191 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
192 * when function returns.
193 * @param[in] arg Type of the input string to select method of checking character validity.
194 * @param[in,out] word_p Word pointer. If buffer (\p word_b) was not yet needed, it is just a pointer to the first
Michal Vaskoea5abea2018-09-18 13:10:54 +0200195 * stored character. If buffer was needed (\p word_b is non-NULL or \p need_buf is set), it is pointing to the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200196 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
197 * @param[in,out] word_b Word buffer. Is kept NULL as long as it is not requested (word is a substring of the data).
Michal Vaskoea5abea2018-09-18 13:10:54 +0200198 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200199 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200200 *
201 * @return LY_ERR values.
202 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200203static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200204buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
205 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200206{
Radek Krejci404251e2018-10-09 12:06:44 +0200207 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200208 unsigned int c;
209 size_t len;
210
211 /* get UTF8 code point (and number of bytes coding the character) */
212 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
213 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
214 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200215 if (c == '\n') {
216 ctx->indent = 0;
217 } else {
218 /* note - even the multibyte character is count as 1 */
219 ++ctx->indent;
220 }
221
Radek Krejci44ceedc2018-10-02 15:54:31 +0200222 /* check character validity */
223 switch (arg) {
224 case Y_IDENTIF_ARG:
225 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
226 break;
227 case Y_PREF_IDENTIF_ARG:
228 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
229 break;
230 case Y_STR_ARG:
231 case Y_MAYBE_STR_ARG:
232 LY_CHECK_RET(check_stringchar(ctx, c));
233 break;
234 }
235
Michal Vasko7fbc8162018-09-17 10:35:16 +0200236 if (word_b && *word_b) {
237 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200238 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200239 return LY_EMEM;
240 }
241
242 /* in case of realloc */
243 *word_p = *word_b;
244 } else if (need_buf) {
245 /* first time we need a buffer, copy everything read up to now */
246 if (*word_len) {
247 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200248 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200249 *buf_len = *word_len;
250 memcpy(*word_b, *word_p, *word_len);
251 }
252
253 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200254 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200255 return LY_EMEM;
256 }
257
258 /* in case of realloc */
259 *word_p = *word_b;
260 } else {
261 /* just remember the first character pointer */
262 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200263 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200264 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200265 /* ... and update the word's length */
266 (*word_len) += len;
267 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200268 }
269
270 return LY_SUCCESS;
271}
272
Michal Vaskoea5abea2018-09-18 13:10:54 +0200273/**
274 * @brief Skip YANG comment in data.
275 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200276 * @param[in] ctx yang parser context for logging.
277 * @param[in,out] data Data to read from, automatically moved after the comment.
278 * @param[in] comment Type of the comment to process:
279 * 1 for a one-line comment,
280 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200281 *
282 * @return LY_ERR values.
283 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200284static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200285skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200286{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200287 /* internal statuses: 0 - comment ended,
288 * 1 - in line comment,
289 * 2 - in block comment,
290 * 3 - in block comment with last read character '*'
291 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200292 while (**data && comment) {
293 switch (comment) {
294 case 1:
295 if (**data == '\n') {
296 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200297 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200298 }
299 break;
300 case 2:
301 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200302 comment = 3;
303 } else if (**data == '\n') {
304 ++ctx->line;
305 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200306 break;
307 case 3:
308 if (**data == '/') {
309 comment = 0;
310 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200311 if (**data == '\n') {
312 ++ctx->line;
313 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200314 comment = 2;
315 }
316 break;
317 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200318 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200319 }
320
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200321 if (**data == '\n') {
322 ctx->indent = 0;
323 } else {
324 ++ctx->indent;
325 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200326 ++(*data);
327 }
328
329 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200330 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200331 return LY_EVALID;
332 }
333
334 return LY_SUCCESS;
335}
336
Michal Vaskoea5abea2018-09-18 13:10:54 +0200337/**
338 * @brief Read a quoted string from data.
339 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200340 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200341 * @param[in,out] data Data to read from, always moved to currently handled character.
342 * @param[in] arg Type of YANG keyword argument expected.
343 * @param[out] word_p Pointer to the read quoted string.
344 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
345 * set to NULL. Otherwise equal to \p word_p.
346 * @param[out] word_len Length of the read quoted string.
347 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
348 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
349 * indenation in the final quoted string.
350 *
351 * @return LY_ERR values.
352 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200353static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200354read_qstring(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len,
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200355 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200356{
357 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
358 * 4 - string finished, now skipping whitespaces looking for +,
359 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200360 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200361 const char *c;
362
363 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200364 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200365 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200366 } else {
367 assert(**data == '\'');
368 string = 1;
369 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200370 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200371
372 while (**data && string) {
373 switch (string) {
374 case 1:
375 switch (**data) {
376 case '\'':
377 /* string may be finished, but check for + */
378 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200379 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200380 break;
381 default:
382 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200383 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200384 break;
385 }
386 break;
387 case 2:
388 switch (**data) {
389 case '\"':
390 /* string may be finished, but check for + */
391 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200392 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200393 break;
394 case '\\':
395 /* special character following */
396 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200397 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200398 break;
399 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200400 if (current_indent < block_indent) {
401 ++current_indent;
402 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200403 } else {
404 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200405 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200406 }
407 break;
408 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200409 if (current_indent < block_indent) {
410 assert(need_buf);
411 current_indent += 8;
412 ctx->indent += 8;
413 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
414 /* store leftover spaces from the tab */
415 c = " ";
416 LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200417 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200418 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200419 } else {
420 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200421 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200422 /* additional characters for indentation - only 1 was count in buf_store_char */
423 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200424 }
425 break;
426 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200427 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200428 /* we will be removing the indents so we need our own buffer */
429 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200430
431 /* remove trailing tabs and spaces */
432 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
433 --(*word_len);
434 }
435
436 /* start indentation */
437 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200438 }
439
440 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200441 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
442
443 /* maintain line number */
444 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200445
446 /* reset context indentation counter for possible string after this one */
447 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200448 break;
449 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200450 /* first non-whitespace character, stop eating indentation */
451 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200452
453 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200454 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200455 break;
456 }
457 break;
458 case 3:
459 /* string encoded characters */
460 switch (**data) {
461 case 'n':
462 c = "\n";
463 break;
464 case 't':
465 c = "\t";
466 break;
467 case '\"':
468 c = *data;
469 break;
470 case '\\':
471 c = *data;
472 break;
473 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200474 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200475 return LY_EVALID;
476 }
477
478 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200479 LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200480
481 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200482 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200483 break;
484 case 4:
485 switch (**data) {
486 case '+':
487 /* string continues */
488 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200489 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200490 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200491 case '\n':
492 ++ctx->line;
493 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200494 case ' ':
495 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200496 /* just skip */
497 break;
498 default:
499 /* string is finished */
500 goto string_end;
501 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200502 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200503 break;
504 case 5:
505 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200506 case '\n':
507 ++ctx->line;
508 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200509 case ' ':
510 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200511 /* skip */
512 break;
513 case '\'':
514 string = 1;
515 break;
516 case '\"':
517 string = 2;
518 break;
519 default:
520 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200521 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200522 return LY_EVALID;
523 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200524 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200525 break;
526 default:
527 return LY_EINT;
528 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200529 }
530
531string_end:
532 return LY_SUCCESS;
533}
534
Michal Vaskoea5abea2018-09-18 13:10:54 +0200535/**
536 * @brief Get another YANG string from the raw data.
537 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200538 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200539 * @param[in,out] data Data to read from, always moved to currently handled character.
540 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200541 * @param[out] word_p Pointer to the read string. Can return NULL if \p arg is #Y_MAYBE_STR_ARG.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200542 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
543 * set to NULL. Otherwise equal to \p word_p.
544 * @param[out] word_len Length of the read string.
545 *
546 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200547 */
548static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200549get_argument(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200550{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200551 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200552
553 /* word buffer - dynamically allocated */
554 *word_b = NULL;
555
556 /* word pointer - just a pointer to data */
557 *word_p = NULL;
558
559 *word_len = 0;
560 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200561 switch (**data) {
562 case '\'':
563 case '\"':
564 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200565 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
566 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
567 "unquoted string character, optsep, semicolon or opening brace");
568 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200569 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100570 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200571 goto str_end;
572 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200573 if ((*data)[1] == '/') {
574 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200575 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100576 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200577 } else if ((*data)[1] == '*') {
578 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200579 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100580 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200581 } else {
582 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100583 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200584 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200585 break;
586 case ' ':
587 if (*word_len) {
588 /* word is finished */
589 goto str_end;
590 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200591 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200592 break;
593 case '\t':
594 if (*word_len) {
595 /* word is finished */
596 goto str_end;
597 }
598 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200599 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200600
601 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200602 break;
603 case '\n':
604 if (*word_len) {
605 /* word is finished */
606 goto str_end;
607 }
608 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200609 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200610
611 /* track line numbers */
612 ++ctx->line;
613
614 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200615 break;
616 case ';':
617 case '{':
618 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
619 /* word is finished */
620 goto str_end;
621 }
622
Radek Krejci44ceedc2018-10-02 15:54:31 +0200623 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200624 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200625 case '}':
626 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
627 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
628 "unquoted string character, optsep, semicolon or opening brace");
629 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200630 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200631 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200632 break;
633 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200634 }
635
636str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200637 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200638 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200639 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
640 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
641 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200642 *word_p = *word_b;
643 }
644
645 return LY_SUCCESS;
646}
647
Michal Vaskoea5abea2018-09-18 13:10:54 +0200648/**
649 * @brief Get another YANG keyword from the raw data.
650 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200651 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200652 * @param[in,out] data Data to read from, always moved to currently handled character.
653 * @param[out] kw YANG keyword read.
654 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
655 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
656 *
657 * @return LY_ERR values.
658 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200659static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200660get_keyword(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200661{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200662 int prefix;
663 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200664 unsigned int c;
665 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200666
667 if (word_p) {
668 *word_p = NULL;
669 *word_len = 0;
670 }
671
672 /* first skip "optsep", comments */
673 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200674 switch (**data) {
675 case '/':
676 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200677 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200678 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100679 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200680 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200681 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200682 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100683 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200684 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200685 /* error - not a comment after all, keyword cannot start with slash */
686 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
687 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200688 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200689 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200690 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200691 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200692 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200693 ctx->indent = 0;
694 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200695 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200696 /* skip whitespaces (optsep) */
697 ++ctx->indent;
698 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200699 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200700 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200701 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200702 break;
703 default:
704 /* either a keyword start or an invalid character */
705 goto keyword_start;
706 }
707
708 ++(*data);
709 }
710
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200711#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
712#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
713#define IF_KW_PREFIX_END }
714
Michal Vasko7fbc8162018-09-17 10:35:16 +0200715keyword_start:
716 word_start = *data;
717 *kw = YANG_NONE;
718
719 /* read the keyword itself */
720 switch (**data) {
721 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200722 MOVE_INPUT(ctx, data, 1);
723 IF_KW("rgument", 7, YANG_ARGUMENT)
724 else IF_KW("ugment", 6, YANG_AUGMENT)
725 else IF_KW("ction", 5, YANG_ACTION)
726 else IF_KW_PREFIX("ny", 2)
727 IF_KW("data", 4, YANG_ANYDATA)
728 else IF_KW("xml", 3, YANG_ANYXML)
729 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200730 break;
731 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200732 MOVE_INPUT(ctx, data, 1);
733 IF_KW("ase", 3, YANG_BASE)
734 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
735 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200736 break;
737 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200738 MOVE_INPUT(ctx, data, 1);
739 IF_KW("ase", 3, YANG_CASE)
740 else IF_KW("hoice", 5, YANG_CHOICE)
741 else IF_KW_PREFIX("on", 2)
742 IF_KW("fig", 3, YANG_CONFIG)
743 else IF_KW_PREFIX("ta", 2)
744 IF_KW("ct", 2, YANG_CONTACT)
745 else IF_KW("iner", 4, YANG_CONTAINER)
746 IF_KW_PREFIX_END
747 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200748 break;
749 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200750 MOVE_INPUT(ctx, data, 1);
751 IF_KW_PREFIX("e", 1)
752 IF_KW("fault", 5, YANG_DEFAULT)
753 else IF_KW("scription", 9, YANG_DESCRIPTION)
754 else IF_KW_PREFIX("viat", 4)
755 IF_KW("e", 1, YANG_DEVIATE)
756 else IF_KW("ion", 3, YANG_DEVIATION)
757 IF_KW_PREFIX_END
758 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200759 break;
760 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200761 MOVE_INPUT(ctx, data, 1);
762 IF_KW("num", 3, YANG_ENUM)
763 else IF_KW_PREFIX("rror-", 5)
764 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
765 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
766 IF_KW_PREFIX_END
767 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200768 break;
769 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200770 MOVE_INPUT(ctx, data, 1);
771 IF_KW("eature", 6, YANG_FEATURE)
772 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200773 break;
774 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200775 MOVE_INPUT(ctx, data, 1);
776 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200777 break;
778 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200779 MOVE_INPUT(ctx, data, 1);
780 IF_KW("dentity", 7, YANG_IDENTITY)
781 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
782 else IF_KW("mport", 5, YANG_IMPORT)
783 else IF_KW_PREFIX("n", 1)
784 IF_KW("clude", 5, YANG_INCLUDE)
785 else IF_KW("put", 3, YANG_INPUT)
786 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200787 break;
788 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200789 MOVE_INPUT(ctx, data, 1);
790 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200791 break;
792 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200793 MOVE_INPUT(ctx, data, 1);
794 IF_KW_PREFIX("e", 1)
795 IF_KW("af-list", 7, YANG_LEAF_LIST)
796 else IF_KW("af", 2, YANG_LEAF)
797 else IF_KW("ngth", 4, YANG_LENGTH)
798 IF_KW_PREFIX_END
799 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200800 break;
801 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200802 MOVE_INPUT(ctx, data, 1);
803 IF_KW_PREFIX("a", 1)
804 IF_KW("ndatory", 7, YANG_MANDATORY)
805 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
806 IF_KW_PREFIX_END
807 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
808 else IF_KW("ust", 3, YANG_MUST)
809 else IF_KW_PREFIX("od", 2)
810 IF_KW("ule", 3, YANG_MODULE)
811 else IF_KW("ifier", 5, YANG_MODIFIER)
812 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200813 break;
814 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200815 MOVE_INPUT(ctx, data, 1);
816 IF_KW("amespace", 8, YANG_NAMESPACE)
817 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200818 break;
819 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200820 MOVE_INPUT(ctx, data, 1);
821 IF_KW_PREFIX("r", 1)
822 IF_KW("dered-by", 8, YANG_ORDERED_BY)
823 else IF_KW("ganization", 10, YANG_ORGANIZATION)
824 IF_KW_PREFIX_END
825 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200826 break;
827 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200828 MOVE_INPUT(ctx, data, 1);
829 IF_KW("ath", 3, YANG_PATH)
830 else IF_KW("attern", 6, YANG_PATTERN)
831 else IF_KW("osition", 7, YANG_POSITION)
832 else IF_KW_PREFIX("re", 2)
833 IF_KW("fix", 3, YANG_PREFIX)
834 else IF_KW("sence", 5, YANG_PRESENCE)
835 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200836 break;
837 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200838 MOVE_INPUT(ctx, data, 1);
839 IF_KW("ange", 4, YANG_RANGE)
840 else IF_KW_PREFIX("e", 1)
841 IF_KW_PREFIX("f", 1)
842 IF_KW("erence", 6, YANG_REFERENCE)
843 else IF_KW("ine", 3, YANG_REFINE)
844 IF_KW_PREFIX_END
845 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
846 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
847 else IF_KW("vision", 6, YANG_REVISION)
848 IF_KW_PREFIX_END
849 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200850 break;
851 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200852 MOVE_INPUT(ctx, data, 1);
853 IF_KW("tatus", 5, YANG_STATUS)
854 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200855 break;
856 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200857 MOVE_INPUT(ctx, data, 1);
858 IF_KW("ypedef", 6, YANG_TYPEDEF)
859 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200860 break;
861 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200862 MOVE_INPUT(ctx, data, 1);
863 IF_KW_PREFIX("ni", 2)
864 IF_KW("que", 3, YANG_UNIQUE)
865 else IF_KW("ts", 2, YANG_UNITS)
866 IF_KW_PREFIX_END
867 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200868 break;
869 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200870 MOVE_INPUT(ctx, data, 1);
871 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200872 break;
873 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200874 MOVE_INPUT(ctx, data, 1);
875 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200876 break;
877 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200878 MOVE_INPUT(ctx, data, 1);
879 IF_KW("ang-version", 11, YANG_YANG_VERSION)
880 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200881 break;
882 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200883 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200884 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200885 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200886 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200887 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200888 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200889 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200890 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200891 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200892 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200893 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200894 default:
895 break;
896 }
897
898 if (*kw != YANG_NONE) {
899 /* make sure we have the whole keyword */
900 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200901 case '\n':
902 ++ctx->line;
903 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200904 case ' ':
905 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200906 /* mandatory "sep" */
907 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200908 case ':':
909 /* keyword is not actually a keyword, but prefix of an extension.
910 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
911 * and we will be checking the keyword (extension instance) itself */
912 prefix = 1;
913 MOVE_INPUT(ctx, data, 1);
914 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200915 case '{':
916 /* allowed only for input and output statements which can be without arguments */
917 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
918 break;
919 }
920 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200921 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200922 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200923 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
924 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200925 return LY_EVALID;
926 }
927 } else {
928 /* still can be an extension */
929 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200930extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200931 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200932 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
933 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200934 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200935 /* check character validity */
936 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200937 }
938 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200939 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200940 return LY_EVALID;
941 }
942
943 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200944 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200945 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200946 return LY_EVALID;
947 }
948
949 *kw = YANG_CUSTOM;
950 }
Radek Krejci626df482018-10-11 15:06:31 +0200951success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200952 if (word_p) {
953 *word_p = (char *)word_start;
954 *word_len = *data - word_start;
955 }
956
957 return LY_SUCCESS;
958}
959
Michal Vaskoea5abea2018-09-18 13:10:54 +0200960/**
961 * @brief Parse extension instance substatements.
962 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200963 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200964 * @param[in,out] data Data to read from, always moved to currently handled character.
965 * @param[in] word Extension instance substatement name (keyword).
966 * @param[in] word_len Extension instance substatement name length.
967 * @param[in,out] child Children of this extension instance to add to.
968 *
969 * @return LY_ERR values.
970 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200971static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200972parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200973 struct lysp_stmt **child)
974{
975 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100976 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200977 enum yang_keyword kw;
978 struct lysp_stmt *stmt, *par_child;
979
980 stmt = calloc(1, sizeof *stmt);
981 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
982
Radek Krejci44ceedc2018-10-02 15:54:31 +0200983 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200984
985 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100986 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200987
Radek Krejci0ae092d2018-09-20 16:43:19 +0200988 if (word) {
989 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200990 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200991 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200992 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200993 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200994 }
995
996 /* insert into parent statements */
997 if (!*child) {
998 *child = stmt;
999 } else {
1000 for (par_child = *child; par_child->next; par_child = par_child->next);
1001 par_child->next = stmt;
1002 }
1003
Radek Krejci6d6556c2018-11-08 09:37:45 +01001004 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001005 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001006 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001007 return ret;
1008}
1009
Michal Vaskoea5abea2018-09-18 13:10:54 +02001010/**
1011 * @brief Parse extension instance.
1012 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001013 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001014 * @param[in,out] data Data to read from, always moved to currently handled character.
1015 * @param[in] ext_name Extension instance substatement name (keyword).
1016 * @param[in] ext_name_len Extension instance substatement name length.
1017 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1018 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1019 * @param[in,out] exts Extension instances to add to.
1020 *
1021 * @return LY_ERR values.
1022 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001023static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001024parse_ext(struct ly_parser_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001025 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1026{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001027 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001028 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001029 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001030 struct lysp_ext_instance *e;
1031 enum yang_keyword kw;
1032
Radek Krejci2c4e7172018-10-19 15:56:26 +02001033 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001034
1035 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001036 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001037 e->insubstmt = insubstmt;
1038 e->insubstmt_index = insubstmt_index;
1039
1040 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001041 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001042
Radek Krejci0ae092d2018-09-20 16:43:19 +02001043 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001044 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001045 }
1046
Radek Krejci6d6556c2018-11-08 09:37:45 +01001047 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001048 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001049 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001050 return ret;
1051}
1052
Michal Vaskoea5abea2018-09-18 13:10:54 +02001053/**
1054 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1055 * description, etc...
1056 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001057 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001058 * @param[in,out] data Data to read from, always moved to currently handled character.
1059 * @param[in] substmt Type of this substatement.
1060 * @param[in] substmt_index Index of this substatement.
1061 * @param[in,out] value Place to store the parsed value.
1062 * @param[in] arg Type of the YANG keyword argument (of the value).
1063 * @param[in,out] exts Extension instances to add to.
1064 *
1065 * @return LY_ERR values.
1066 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001067static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001068parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001069 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1070{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001071 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001072 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001073 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001074 enum yang_keyword kw;
1075
1076 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001077 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001078 return LY_EVALID;
1079 }
1080
1081 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001082 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001083
1084 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001085 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001086
Radek Krejci6d6556c2018-11-08 09:37:45 +01001087 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001088 switch (kw) {
1089 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001090 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001091 break;
1092 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001093 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001094 return LY_EVALID;
1095 }
1096 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001097 return ret;
1098}
1099
Michal Vaskoea5abea2018-09-18 13:10:54 +02001100/**
1101 * @brief Parse the yang-version statement.
1102 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001103 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001104 * @param[in,out] data Data to read from, always moved to currently handled character.
1105 * @param[in] mod Module to store the parsed information in.
1106 *
1107 * @return LY_ERR values.
1108 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001109static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001110parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001111{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001112 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001113 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001114 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001115 enum yang_keyword kw;
1116
1117 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001118 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001119 return LY_EVALID;
1120 }
1121
1122 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001123 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001124
1125 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1126 mod->version = LYS_VERSION_1_0;
1127 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1128 mod->version = LYS_VERSION_1_1;
1129 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001130 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131 free(buf);
1132 return LY_EVALID;
1133 }
1134 free(buf);
1135
Radek Krejci6d6556c2018-11-08 09:37:45 +01001136 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001137 switch (kw) {
1138 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001139 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001140 break;
1141 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001142 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001143 return LY_EVALID;
1144 }
1145 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001146 return ret;
1147}
1148
Michal Vaskoea5abea2018-09-18 13:10:54 +02001149/**
1150 * @brief Parse the belongs-to statement.
1151 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001152 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001153 * @param[in,out] data Data to read from, always moved to currently handled character.
1154 * @param[in,out] belongsto Place to store the parsed value.
1155 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1156 * @param[in,out] exts Extension instances to add to.
1157 *
1158 * @return LY_ERR values.
1159 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001160static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001161parse_belongsto(struct ly_parser_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001162{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001163 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001164 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001165 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001166 enum yang_keyword kw;
1167
1168 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001169 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001170 return LY_EVALID;
1171 }
1172
1173 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001174 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175
Radek Krejci44ceedc2018-10-02 15:54:31 +02001176 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001177 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001178 switch (kw) {
1179 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001180 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001181 break;
1182 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001183 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184 break;
1185 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001186 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001187 return LY_EVALID;
1188 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001190 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001191checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001192 /* mandatory substatements */
1193 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001194 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001195 return LY_EVALID;
1196 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001197 return ret;
1198}
1199
Michal Vaskoea5abea2018-09-18 13:10:54 +02001200/**
1201 * @brief Parse the revision-date statement.
1202 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001203 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001204 * @param[in,out] data Data to read from, always moved to currently handled character.
1205 * @param[in,out] rev Array to store the parsed value in.
1206 * @param[in,out] exts Extension instances to add to.
1207 *
1208 * @return LY_ERR values.
1209 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001210static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001211parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001212{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001213 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001214 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001215 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001216 enum yang_keyword kw;
1217
1218 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001219 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001220 return LY_EVALID;
1221 }
1222
1223 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001224 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001225
1226 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001227 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001228 free(buf);
1229 return LY_EVALID;
1230 }
1231
1232 /* store value and spend buf if allocated */
1233 strncpy(rev, word, word_len);
1234 free(buf);
1235
Radek Krejci6d6556c2018-11-08 09:37:45 +01001236 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001237 switch (kw) {
1238 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001239 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001240 break;
1241 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001242 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001243 return LY_EVALID;
1244 }
1245 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001246 return ret;
1247}
1248
Michal Vaskoea5abea2018-09-18 13:10:54 +02001249/**
1250 * @brief Parse the include statement.
1251 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001252 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001253 * @param[in,out] data Data to read from, always moved to currently handled character.
1254 * @param[in,out] includes Parsed includes to add to.
1255 *
1256 * @return LY_ERR values.
1257 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001258static LY_ERR
Radek Krejcid33273d2018-10-25 14:55:52 +02001259parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001260{
Radek Krejcid33273d2018-10-25 14:55:52 +02001261 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001262 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001263 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001264 enum yang_keyword kw;
1265 struct lysp_include *inc;
1266
Radek Krejcid33273d2018-10-25 14:55:52 +02001267 LY_ARRAY_NEW_RET(ctx->ctx, mod->includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001268
1269 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001270 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001271
Radek Krejci086c7132018-10-26 15:29:04 +02001272 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1273
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001274 /* submodules share the namespace with the module names, so there must not be
1275 * a module of the same name in the context, no need for revision matching */
1276 if (!strcmp(ctx->mod->name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
1277 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1278 return LY_EVALID;
1279 }
1280
Radek Krejci6d6556c2018-11-08 09:37:45 +01001281 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001282 switch (kw) {
1283 case YANG_DESCRIPTION:
Radek Krejci10113652018-11-14 16:56:50 +01001284 YANG_CHECK_STMTVER_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001285 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001286 break;
1287 case YANG_REFERENCE:
Radek Krejci10113652018-11-14 16:56:50 +01001288 YANG_CHECK_STMTVER_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001289 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001290 break;
1291 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001292 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001293 break;
1294 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001295 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001296 break;
1297 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001298 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001299 return LY_EVALID;
1300 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001301 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001302 return ret;
1303}
1304
Michal Vaskoea5abea2018-09-18 13:10:54 +02001305/**
1306 * @brief Parse the import statement.
1307 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001308 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001309 * @param[in,out] data Data to read from, always moved to currently handled character.
1310 * @param[in,out] imports Parsed imports to add to.
1311 *
1312 * @return LY_ERR values.
1313 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001314static LY_ERR
Radek Krejci70853c52018-10-15 14:46:16 +02001315parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *module)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001316{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001317 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001318 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001319 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001320 enum yang_keyword kw;
1321 struct lysp_import *imp;
1322
Radek Krejci2c4e7172018-10-19 15:56:26 +02001323 LY_ARRAY_NEW_RET(ctx->ctx, module->imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001324
1325 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001326 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001327 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001328
Radek Krejci6d6556c2018-11-08 09:37:45 +01001329 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001330 switch (kw) {
1331 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001332 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
Radek Krejci70853c52018-10-15 14:46:16 +02001333 LY_CHECK_RET(lysp_check_prefix(ctx, module, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001334 break;
1335 case YANG_DESCRIPTION:
Radek Krejci10113652018-11-14 16:56:50 +01001336 YANG_CHECK_STMTVER_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001337 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001338 break;
1339 case YANG_REFERENCE:
Radek Krejci10113652018-11-14 16:56:50 +01001340 YANG_CHECK_STMTVER_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001341 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001342 break;
1343 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001344 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001345 break;
1346 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001347 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001348 break;
1349 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001350 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001351 return LY_EVALID;
1352 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001353 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001354 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001355checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001356 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001357 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001358
1359 return ret;
1360}
1361
Michal Vaskoea5abea2018-09-18 13:10:54 +02001362/**
1363 * @brief Parse the revision statement.
1364 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001365 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001366 * @param[in,out] data Data to read from, always moved to currently handled character.
1367 * @param[in,out] revs Parsed revisions to add to.
1368 *
1369 * @return LY_ERR values.
1370 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001371static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001372parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001373{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001374 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001375 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001376 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001377 enum yang_keyword kw;
1378 struct lysp_revision *rev;
1379
Radek Krejci2c4e7172018-10-19 15:56:26 +02001380 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001381
1382 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001383 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001384
1385 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001386 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001387 return LY_EVALID;
1388 }
1389
Radek Krejcib7db73a2018-10-24 14:18:40 +02001390 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001391 free(buf);
1392
Radek Krejci6d6556c2018-11-08 09:37:45 +01001393 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001394 switch (kw) {
1395 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001396 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001397 break;
1398 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001399 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001400 break;
1401 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001402 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001403 break;
1404 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001405 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001406 return LY_EVALID;
1407 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001408 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001409 return ret;
1410}
1411
Michal Vaskoea5abea2018-09-18 13:10:54 +02001412/**
1413 * @brief Parse a generic text field that can have more instances such as base.
1414 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001415 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001416 * @param[in,out] data Data to read from, always moved to currently handled character.
1417 * @param[in] substmt Type of this substatement.
1418 * @param[in,out] texts Parsed values to add to.
1419 * @param[in] arg Type of the expected argument.
1420 * @param[in,out] exts Extension instances to add to.
1421 *
1422 * @return LY_ERR values.
1423 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001424static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001425parse_text_fields(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001426 struct lysp_ext_instance **exts)
1427{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001428 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001429 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001430 const char **item;
1431 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001432 enum yang_keyword kw;
1433
1434 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001435 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001436
1437 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001438 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001439
Radek Krejci151a5b72018-10-19 14:21:44 +02001440 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001441 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001442 switch (kw) {
1443 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001444 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001445 break;
1446 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001447 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001448 return LY_EVALID;
1449 }
1450 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001451 return ret;
1452}
1453
Michal Vaskoea5abea2018-09-18 13:10:54 +02001454/**
1455 * @brief Parse the config statement.
1456 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001457 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001458 * @param[in,out] data Data to read from, always moved to currently handled character.
1459 * @param[in,out] flags Flags to add to.
1460 * @param[in,out] exts Extension instances to add to.
1461 *
1462 * @return LY_ERR values.
1463 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001464static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001465parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001466{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001467 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001468 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001469 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001470 enum yang_keyword kw;
1471
1472 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001473 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001474 return LY_EVALID;
1475 }
1476
1477 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001478 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001479
1480 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1481 *flags |= LYS_CONFIG_W;
1482 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1483 *flags |= LYS_CONFIG_R;
1484 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001485 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001486 free(buf);
1487 return LY_EVALID;
1488 }
1489 free(buf);
1490
Radek Krejci6d6556c2018-11-08 09:37:45 +01001491 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001492 switch (kw) {
1493 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001494 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001495 break;
1496 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001497 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001498 return LY_EVALID;
1499 }
1500 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001501 return ret;
1502}
1503
Michal Vaskoea5abea2018-09-18 13:10:54 +02001504/**
1505 * @brief Parse the mandatory statement.
1506 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001507 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001508 * @param[in,out] data Data to read from, always moved to currently handled character.
1509 * @param[in,out] flags Flags to add to.
1510 * @param[in,out] exts Extension instances to add to.
1511 *
1512 * @return LY_ERR values.
1513 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001514static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001515parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001516{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001517 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001518 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001519 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001520 enum yang_keyword kw;
1521
1522 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001523 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001524 return LY_EVALID;
1525 }
1526
1527 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001528 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001529
1530 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1531 *flags |= LYS_MAND_TRUE;
1532 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1533 *flags |= LYS_MAND_FALSE;
1534 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001535 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001536 free(buf);
1537 return LY_EVALID;
1538 }
1539 free(buf);
1540
Radek Krejci6d6556c2018-11-08 09:37:45 +01001541 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001542 switch (kw) {
1543 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001544 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001545 break;
1546 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001547 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001548 return LY_EVALID;
1549 }
1550 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001551 return ret;
1552}
1553
Michal Vaskoea5abea2018-09-18 13:10:54 +02001554/**
1555 * @brief Parse a restriction such as range or length.
1556 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001557 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001558 * @param[in,out] data Data to read from, always moved to currently handled character.
1559 * @param[in] restr_kw Type of this particular restriction.
1560 * @param[in,out] exts Extension instances to add to.
1561 *
1562 * @return LY_ERR values.
1563 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001564static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001565parse_restr(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr *restr)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001566{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001567 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001568 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001569 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001570 enum yang_keyword kw;
1571
1572 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001573 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001574
Radek Krejci44ceedc2018-10-02 15:54:31 +02001575 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001576 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001577 switch (kw) {
1578 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001579 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001580 break;
1581 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001582 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001583 break;
1584 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001585 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001586 break;
1587 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001588 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001589 break;
1590 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001591 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001592 break;
1593 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001594 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001595 return LY_EVALID;
1596 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001597 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001598 return ret;
1599}
1600
Michal Vaskoea5abea2018-09-18 13:10:54 +02001601/**
1602 * @brief Parse a restriction that can have more instances such as must.
1603 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001604 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001605 * @param[in,out] data Data to read from, always moved to currently handled character.
1606 * @param[in] restr_kw Type of this particular restriction.
1607 * @param[in,out] restrs Restrictions to add to.
1608 *
1609 * @return LY_ERR values.
1610 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001611static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001612parse_restrs(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr **restrs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001613{
1614 struct lysp_restr *restr;
1615
Radek Krejci2c4e7172018-10-19 15:56:26 +02001616 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001617 return parse_restr(ctx, data, restr_kw, restr);
1618}
1619
Michal Vaskoea5abea2018-09-18 13:10:54 +02001620/**
1621 * @brief Parse the status statement.
1622 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001623 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001624 * @param[in,out] data Data to read from, always moved to currently handled character.
1625 * @param[in,out] flags Flags to add to.
1626 * @param[in,out] exts Extension instances to add to.
1627 *
1628 * @return LY_ERR values.
1629 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001630static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001631parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001632{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001633 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001634 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001635 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001636 enum yang_keyword kw;
1637
1638 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001639 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001640 return LY_EVALID;
1641 }
1642
1643 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001644 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001645
1646 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1647 *flags |= LYS_STATUS_CURR;
1648 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1649 *flags |= LYS_STATUS_DEPRC;
1650 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1651 *flags |= LYS_STATUS_OBSLT;
1652 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001653 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001654 free(buf);
1655 return LY_EVALID;
1656 }
1657 free(buf);
1658
Radek Krejci6d6556c2018-11-08 09:37:45 +01001659 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001660 switch (kw) {
1661 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001662 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001663 break;
1664 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001665 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001666 return LY_EVALID;
1667 }
1668 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001669 return ret;
1670}
1671
Michal Vaskoea5abea2018-09-18 13:10:54 +02001672/**
1673 * @brief Parse the when statement.
1674 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001675 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001676 * @param[in,out] data Data to read from, always moved to currently handled character.
1677 * @param[in,out] when_p When pointer to parse to.
1678 *
1679 * @return LY_ERR values.
1680 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001681static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001682parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001683{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001684 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001685 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001686 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001687 enum yang_keyword kw;
1688 struct lysp_when *when;
1689
1690 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001691 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001692 return LY_EVALID;
1693 }
1694
1695 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001696 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001697 *when_p = when;
1698
1699 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001700 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001701 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001702
Radek Krejci6d6556c2018-11-08 09:37:45 +01001703 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001704 switch (kw) {
1705 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001706 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001707 break;
1708 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001709 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001710 break;
1711 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001712 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001713 break;
1714 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001715 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001716 return LY_EVALID;
1717 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001718 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001719 return ret;
1720}
1721
Michal Vaskoea5abea2018-09-18 13:10:54 +02001722/**
1723 * @brief Parse the anydata or anyxml statement.
1724 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001725 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001726 * @param[in,out] data Data to read from, always moved to currently handled character.
1727 * @param[in] kw Type of this particular keyword.
1728 * @param[in,out] siblings Siblings to add to.
1729 *
1730 * @return LY_ERR values.
1731 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001732static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001733parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001734{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001735 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001736 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001737 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001738 struct lysp_node *iter;
1739 struct lysp_node_anydata *any;
1740
1741 /* create structure */
1742 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001743 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001744 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001745 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001746
1747 /* insert into siblings */
1748 if (!*siblings) {
1749 *siblings = (struct lysp_node *)any;
1750 } else {
1751 for (iter = *siblings; iter->next; iter = iter->next);
1752 iter->next = (struct lysp_node *)any;
1753 }
1754
1755 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001756 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001757 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001758
1759 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001760 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001761 switch (kw) {
1762 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001763 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001764 break;
1765 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001766 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001767 break;
1768 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001769 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001770 break;
1771 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001772 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001773 break;
1774 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001775 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001776 break;
1777 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001778 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001779 break;
1780 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001781 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001782 break;
1783 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001784 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001785 break;
1786 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001787 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001788 break;
1789 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001790 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001791 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001792 return LY_EVALID;
1793 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001794 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001795 return ret;
1796}
1797
Michal Vaskoea5abea2018-09-18 13:10:54 +02001798/**
1799 * @brief Parse the value or position statement. Substatement of type enum statement.
1800 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001801 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001802 * @param[in,out] data Data to read from, always moved to currently handled character.
1803 * @param[in] val_kw Type of this particular keyword.
1804 * @param[in,out] value Value to write to.
1805 * @param[in,out] flags Flags to write to.
1806 * @param[in,out] exts Extension instances to add to.
1807 *
1808 * @return LY_ERR values.
1809 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001810static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001811parse_type_enum_value_pos(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword val_kw, int64_t *value, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001812 struct lysp_ext_instance **exts)
1813{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001814 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001815 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001816 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001817 long int num;
1818 unsigned long int unum;
1819 enum yang_keyword kw;
1820
1821 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001822 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001823 return LY_EVALID;
1824 }
1825 *flags |= LYS_SET_VALUE;
1826
1827 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001828 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001829
1830 if (!word_len || (word[0] == '+') || ((word[0] == '0') && (word_len > 1)) || ((val_kw == YANG_VALUE) && !strncmp(word, "-0", 2))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001831 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001832 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833 }
1834
1835 errno = 0;
1836 if (val_kw == YANG_VALUE) {
1837 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001838 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
1839 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1840 goto error;
1841 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001842 } else {
1843 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001844 if (unum > UINT64_C(4294967295)) {
1845 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1846 goto error;
1847 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001848 }
1849 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001850 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001851 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001852 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001853 }
1854 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001855 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001856 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001857 }
1858 if (val_kw == YANG_VALUE) {
1859 *value = num;
1860 } else {
1861 *value = unum;
1862 }
1863 free(buf);
1864
Radek Krejci6d6556c2018-11-08 09:37:45 +01001865 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001866 switch (kw) {
1867 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001868 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, val_kw == YANG_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001869 break;
1870 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001871 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001872 return LY_EVALID;
1873 }
1874 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001875 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001876
1877error:
1878 free(buf);
1879 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001880}
1881
Michal Vaskoea5abea2018-09-18 13:10:54 +02001882/**
1883 * @brief Parse the enum or bit statement. Substatement of type statement.
1884 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001885 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001886 * @param[in,out] data Data to read from, always moved to currently handled character.
1887 * @param[in] enum_kw Type of this particular keyword.
1888 * @param[in,out] enums Enums or bits to add to.
1889 *
1890 * @return LY_ERR values.
1891 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001892static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001893parse_type_enum(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword enum_kw, struct lysp_type_enum **enums)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001894{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001895 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001896 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001897 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001898 enum yang_keyword kw;
1899 struct lysp_type_enum *enm;
1900
Radek Krejci2c4e7172018-10-19 15:56:26 +02001901 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001902
1903 /* get value */
Radek Krejci8b764662018-11-14 14:15:13 +01001904 LY_CHECK_RET(get_argument(ctx, data, enum_kw == YANG_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, &word, &buf, &word_len));
1905 if (enum_kw == YANG_ENUM) {
1906 if (!word_len) {
1907 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
1908 free(buf);
1909 return LY_EVALID;
1910 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
1911 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
1912 word_len, word);
1913 free(buf);
1914 return LY_EVALID;
1915 } else {
1916 for (u = 0; u < word_len; ++u) {
1917 if (iscntrl(word[u])) {
1918 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1919 word_len, word, u + 1);
1920 break;
1921 }
1922 }
1923 }
1924 } else { /* YANG_BIT */
1925
1926 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001927 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001928
Radek Krejci8b764662018-11-14 14:15:13 +01001929 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1930
Radek Krejci6d6556c2018-11-08 09:37:45 +01001931 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001932 switch (kw) {
1933 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001934 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001935 break;
1936 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01001937 YANG_CHECK_STMTVER_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001938 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001939 break;
1940 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001941 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001942 break;
1943 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001944 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001945 break;
1946 case YANG_VALUE:
1947 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001948 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949 break;
1950 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001951 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001952 break;
1953 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001954 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001955 return LY_EVALID;
1956 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001957 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001958 return ret;
1959}
1960
Michal Vaskoea5abea2018-09-18 13:10:54 +02001961/**
1962 * @brief Parse the fraction-digits statement. Substatement of type statement.
1963 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001964 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001965 * @param[in,out] data Data to read from, always moved to currently handled character.
1966 * @param[in,out] fracdig Value to write to.
1967 * @param[in,out] exts Extension instances to add to.
1968 *
1969 * @return LY_ERR values.
1970 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001971static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001972parse_type_fracdigits(struct ly_parser_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001973{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001974 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001975 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001976 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001977 unsigned long int num;
1978 enum yang_keyword kw;
1979
1980 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001981 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001982 return LY_EVALID;
1983 }
1984
1985 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001986 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001987
1988 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001989 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001990 free(buf);
1991 return LY_EVALID;
1992 }
1993
1994 errno = 0;
1995 num = strtoul(word, &ptr, 10);
1996 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001997 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001998 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001999 free(buf);
2000 return LY_EVALID;
2001 }
2002 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002003 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002004 free(buf);
2005 return LY_EVALID;
2006 }
2007 *fracdig = num;
2008 free(buf);
2009
Radek Krejci6d6556c2018-11-08 09:37:45 +01002010 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002011 switch (kw) {
2012 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002013 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002014 break;
2015 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002016 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002017 return LY_EVALID;
2018 }
2019 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002020 return ret;
2021}
2022
Michal Vaskoea5abea2018-09-18 13:10:54 +02002023/**
2024 * @brief Parse the require-instance statement. Substatement of type statement.
2025 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002026 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002027 * @param[in,out] data Data to read from, always moved to currently handled character.
2028 * @param[in,out] reqinst Value to write to.
2029 * @param[in,out] flags Flags to write to.
2030 * @param[in,out] exts Extension instances to add to.
2031 *
2032 * @return LY_ERR values.
2033 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002034static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002035parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002036 struct lysp_ext_instance **exts)
2037{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002038 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002039 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002040 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002041 enum yang_keyword kw;
2042
2043 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002044 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002045 return LY_EVALID;
2046 }
2047 *flags |= LYS_SET_REQINST;
2048
2049 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002050 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002051
2052 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2053 *reqinst = 1;
2054 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002055 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002056 free(buf);
2057 return LY_EVALID;
2058 }
2059 free(buf);
2060
Radek Krejci6d6556c2018-11-08 09:37:45 +01002061 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002062 switch (kw) {
2063 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002064 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002065 break;
2066 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002067 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002068 return LY_EVALID;
2069 }
2070 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002071 return ret;
2072}
2073
Michal Vaskoea5abea2018-09-18 13:10:54 +02002074/**
2075 * @brief Parse the modifier statement. Substatement of type pattern statement.
2076 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002077 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002078 * @param[in,out] data Data to read from, always moved to currently handled character.
2079 * @param[in,out] pat Value to write to.
2080 * @param[in,out] exts Extension instances to add to.
2081 *
2082 * @return LY_ERR values.
2083 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002084static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002085parse_type_pattern_modifier(struct ly_parser_ctx *ctx, const char **data, const char **pat, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002086{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002087 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002088 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002089 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002090 enum yang_keyword kw;
2091
2092 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002093 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002094 return LY_EVALID;
2095 }
2096
2097 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002098 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002099
2100 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002101 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002102 free(buf);
2103 return LY_EVALID;
2104 }
2105 free(buf);
2106
2107 /* replace the value in the dictionary */
2108 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002109 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002110 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002111 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002112
2113 assert(buf[0] == 0x06);
2114 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002115 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002116
Radek Krejci6d6556c2018-11-08 09:37:45 +01002117 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002118 switch (kw) {
2119 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002120 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002121 break;
2122 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002123 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002124 return LY_EVALID;
2125 }
2126 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002127 return ret;
2128}
2129
Michal Vaskoea5abea2018-09-18 13:10:54 +02002130/**
2131 * @brief Parse the pattern statement. Substatement of type statement.
2132 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002133 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002134 * @param[in,out] data Data to read from, always moved to currently handled character.
2135 * @param[in,out] patterns Restrictions to add to.
2136 *
2137 * @return LY_ERR values.
2138 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002139static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002140parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002141{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002142 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002143 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002144 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002145 enum yang_keyword kw;
2146 struct lysp_restr *restr;
2147
Radek Krejci2c4e7172018-10-19 15:56:26 +02002148 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002149
2150 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002151 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002152
2153 /* add special meaning first byte */
2154 if (buf) {
2155 buf = realloc(buf, word_len + 2);
2156 word = buf;
2157 } else {
2158 buf = malloc(word_len + 2);
2159 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002160 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002161 memmove(buf + 1, word, word_len);
2162 buf[0] = 0x06; /* pattern's default regular-match flag */
2163 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2164 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002165
Radek Krejci6d6556c2018-11-08 09:37:45 +01002166 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002167 switch (kw) {
2168 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002169 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002170 break;
2171 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002172 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002173 break;
2174 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002175 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002176 break;
2177 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002178 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002179 break;
2180 case YANG_MODIFIER:
Radek Krejci10113652018-11-14 16:56:50 +01002181 YANG_CHECK_STMTVER_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002182 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002183 break;
2184 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002185 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002186 break;
2187 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002188 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189 return LY_EVALID;
2190 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002191 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002192 return ret;
2193}
2194
Michal Vaskoea5abea2018-09-18 13:10:54 +02002195/**
2196 * @brief Parse the type statement.
2197 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002198 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002199 * @param[in,out] data Data to read from, always moved to currently handled character.
2200 * @param[in,out] type Type to wrote to.
2201 *
2202 * @return LY_ERR values.
2203 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002204static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002205parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002206{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002207 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002208 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002209 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002210 enum yang_keyword kw;
2211 struct lysp_type *nest_type;
2212
2213 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002214 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002215 return LY_EVALID;
2216 }
2217
2218 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002219 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002220 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002221
Radek Krejci6d6556c2018-11-08 09:37:45 +01002222 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002223 switch (kw) {
2224 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002225 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002226 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002227 break;
2228 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002229 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002230 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002231 break;
2232 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002233 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002234 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002235 break;
2236 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002237 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002238 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002239 break;
2240 case YANG_LENGTH:
2241 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002242 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002243 return LY_EVALID;
2244 }
2245 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002246 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002247
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002248 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002249 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002250 break;
2251 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002252 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002253 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002254 break;
2255 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002256 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002257 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002258 break;
2259 case YANG_RANGE:
2260 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002261 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002262 return LY_EVALID;
2263 }
2264 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002265 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002266
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002267 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002268 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002269 break;
2270 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002271 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002272 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002273 break;
2274 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002275 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2276 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002277 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002278 break;
2279 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002280 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002281 break;
2282 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002283 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002284 return LY_EVALID;
2285 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002286 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002287 return ret;
2288}
2289
Michal Vaskoea5abea2018-09-18 13:10:54 +02002290/**
2291 * @brief Parse the leaf statement.
2292 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002293 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002294 * @param[in,out] data Data to read from, always moved to currently handled character.
2295 * @param[in,out] siblings Siblings to add to.
2296 *
2297 * @return LY_ERR values.
2298 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002299static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002300parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002301{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002302 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002303 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002304 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002305 enum yang_keyword kw;
2306 struct lysp_node *iter;
2307 struct lysp_node_leaf *leaf;
2308
2309 /* create structure */
2310 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002311 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002312 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002313 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002314
2315 /* insert into siblings */
2316 if (!*siblings) {
2317 *siblings = (struct lysp_node *)leaf;
2318 } else {
2319 for (iter = *siblings; iter->next; iter = iter->next);
2320 iter->next = (struct lysp_node *)leaf;
2321 }
2322
2323 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002324 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002325 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002326
2327 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002328 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002329 switch (kw) {
2330 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002331 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002332 break;
2333 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002334 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002335 break;
2336 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002337 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002338 break;
2339 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002340 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002341 break;
2342 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002343 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002344 break;
2345 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002346 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002347 break;
2348 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002349 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002350 break;
2351 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002352 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002353 break;
2354 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002355 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002356 break;
2357 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002358 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002359 break;
2360 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002361 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002362 break;
2363 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002364 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002365 break;
2366 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002367 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002368 return LY_EVALID;
2369 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002370 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002371 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002372checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002373 /* mandatory substatements */
2374 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002375 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002376 return LY_EVALID;
2377 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002378 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
2379 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
2380 return LY_EVALID;
2381 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002382
2383 return ret;
2384}
2385
Michal Vaskoea5abea2018-09-18 13:10:54 +02002386/**
2387 * @brief Parse the max-elements statement.
2388 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002389 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002390 * @param[in,out] data Data to read from, always moved to currently handled character.
2391 * @param[in,out] max Value to write to.
2392 * @param[in,out] flags Flags to write to.
2393 * @param[in,out] exts Extension instances to add to.
2394 *
2395 * @return LY_ERR values.
2396 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002397static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002398parse_maxelements(struct ly_parser_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002399{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002400 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002401 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002402 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002403 unsigned long int num;
2404 enum yang_keyword kw;
2405
2406 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002407 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002408 return LY_EVALID;
2409 }
2410 *flags |= LYS_SET_MAX;
2411
2412 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002413 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002414
2415 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002416 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002417 free(buf);
2418 return LY_EVALID;
2419 }
2420
2421 if (strncmp(word, "unbounded", word_len)) {
2422 errno = 0;
2423 num = strtoul(word, &ptr, 10);
2424 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002425 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002426 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002427 free(buf);
2428 return LY_EVALID;
2429 }
2430 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002431 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002432 free(buf);
2433 return LY_EVALID;
2434 }
2435
2436 *max = num;
2437 }
2438 free(buf);
2439
Radek Krejci6d6556c2018-11-08 09:37:45 +01002440 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002441 switch (kw) {
2442 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002443 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002444 break;
2445 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002446 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002447 return LY_EVALID;
2448 }
2449 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002450 return ret;
2451}
2452
Michal Vaskoea5abea2018-09-18 13:10:54 +02002453/**
2454 * @brief Parse the min-elements statement.
2455 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002456 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002457 * @param[in,out] data Data to read from, always moved to currently handled character.
2458 * @param[in,out] min Value to write to.
2459 * @param[in,out] flags Flags to write to.
2460 * @param[in,out] exts Extension instances to add to.
2461 *
2462 * @return LY_ERR values.
2463 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002464static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002465parse_minelements(struct ly_parser_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002466{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002467 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002468 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002469 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002470 unsigned long int num;
2471 enum yang_keyword kw;
2472
2473 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002474 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002475 return LY_EVALID;
2476 }
2477 *flags |= LYS_SET_MIN;
2478
2479 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002480 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002481
2482 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002483 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002484 free(buf);
2485 return LY_EVALID;
2486 }
2487
2488 errno = 0;
2489 num = strtoul(word, &ptr, 10);
2490 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002491 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002492 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002493 free(buf);
2494 return LY_EVALID;
2495 }
2496 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002497 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002498 free(buf);
2499 return LY_EVALID;
2500 }
2501 *min = num;
2502 free(buf);
2503
Radek Krejci6d6556c2018-11-08 09:37:45 +01002504 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002505 switch (kw) {
2506 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002507 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002508 break;
2509 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002510 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002511 return LY_EVALID;
2512 }
2513 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002514 return ret;
2515}
2516
Michal Vaskoea5abea2018-09-18 13:10:54 +02002517/**
2518 * @brief Parse the ordered-by statement.
2519 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002520 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002521 * @param[in,out] data Data to read from, always moved to currently handled character.
2522 * @param[in,out] flags Flags to write to.
2523 * @param[in,out] exts Extension instances to add to.
2524 *
2525 * @return LY_ERR values.
2526 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002527static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002528parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002529{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002530 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002531 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002532 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002533 enum yang_keyword kw;
2534
2535 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002536 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002537 return LY_EVALID;
2538 }
2539
2540 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002541 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002542
2543 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2544 *flags |= LYS_ORDBY_SYSTEM;
2545 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2546 *flags |= LYS_ORDBY_USER;
2547 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002548 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002549 free(buf);
2550 return LY_EVALID;
2551 }
2552 free(buf);
2553
Radek Krejci6d6556c2018-11-08 09:37:45 +01002554 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002555 switch (kw) {
2556 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002557 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002558 break;
2559 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002560 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002561 return LY_EVALID;
2562 }
2563 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002564 return ret;
2565}
2566
Michal Vaskoea5abea2018-09-18 13:10:54 +02002567/**
2568 * @brief Parse the leaf-list statement.
2569 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002570 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002571 * @param[in,out] data Data to read from, always moved to currently handled character.
2572 * @param[in,out] siblings Siblings to add to.
2573 *
2574 * @return LY_ERR values.
2575 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002576static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002577parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002578{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002579 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002580 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002581 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002582 enum yang_keyword kw;
2583 struct lysp_node *iter;
2584 struct lysp_node_leaflist *llist;
2585
2586 /* create structure */
2587 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002588 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002589 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002590 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002591
2592 /* insert into siblings */
2593 if (!*siblings) {
2594 *siblings = (struct lysp_node *)llist;
2595 } else {
2596 for (iter = *siblings; iter->next; iter = iter->next);
2597 iter->next = (struct lysp_node *)llist;
2598 }
2599
2600 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002601 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002602 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002603
2604 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002605 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002606 switch (kw) {
2607 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002608 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002609 break;
2610 case YANG_DEFAULT:
Radek Krejci10113652018-11-14 16:56:50 +01002611 YANG_CHECK_STMTVER_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002612 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002613 break;
2614 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002615 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002616 break;
2617 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002618 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619 break;
2620 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002621 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002622 break;
2623 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002624 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002625 break;
2626 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002627 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628 break;
2629 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002630 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002631 break;
2632 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002633 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002634 break;
2635 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002636 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002637 break;
2638 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002639 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002640 break;
2641 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002642 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002643 break;
2644 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002645 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002646 break;
2647 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002648 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002649 break;
2650 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002651 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002652 return LY_EVALID;
2653 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002654 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002655 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002656checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002657 /* mandatory substatements */
2658 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002659 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002660 return LY_EVALID;
2661 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002662 if ((llist->min) && (llist->dflts)) {
2663 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
2664 return LY_EVALID;
2665 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002666 if (llist->max && llist->min > llist->max) {
2667 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
2668 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2669 llist->min, llist->max);
2670 return LY_EVALID;
2671 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002672
2673 return ret;
2674}
2675
Michal Vaskoea5abea2018-09-18 13:10:54 +02002676/**
2677 * @brief Parse the refine statement.
2678 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002679 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002680 * @param[in,out] data Data to read from, always moved to currently handled character.
2681 * @param[in,out] refines Refines to add to.
2682 *
2683 * @return LY_ERR values.
2684 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002685static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002686parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002687{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002688 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002689 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002690 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002691 enum yang_keyword kw;
2692 struct lysp_refine *rf;
2693
Radek Krejci2c4e7172018-10-19 15:56:26 +02002694 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695
2696 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002697 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002698 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002699
Radek Krejci6d6556c2018-11-08 09:37:45 +01002700 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002701 switch (kw) {
2702 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002703 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002704 break;
2705 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002706 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 +02002707 break;
2708 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002709 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 +02002710 break;
2711 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01002712 YANG_CHECK_STMTVER_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002713 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 +02002714 break;
2715 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002716 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002717 break;
2718 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002719 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002720 break;
2721 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002722 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002723 break;
2724 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002725 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002726 break;
2727 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002728 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 +02002729 break;
2730 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002731 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 +02002732 break;
2733 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002734 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002735 break;
2736 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002737 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002738 return LY_EVALID;
2739 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002740 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002741 return ret;
2742}
2743
Michal Vaskoea5abea2018-09-18 13:10:54 +02002744/**
2745 * @brief Parse the typedef statement.
2746 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002747 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002748 * @param[in,out] data Data to read from, always moved to currently handled character.
2749 * @param[in,out] typedefs Typedefs to add to.
2750 *
2751 * @return LY_ERR values.
2752 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002753static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002754parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002755{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002756 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002757 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002758 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002759 enum yang_keyword kw;
2760 struct lysp_tpdf *tpdf;
2761
Radek Krejci2c4e7172018-10-19 15:56:26 +02002762 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002763
2764 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002765 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002766 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002767
2768 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002769 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002770 switch (kw) {
2771 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002772 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 +02002773 break;
2774 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002775 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 +02002776 break;
2777 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002778 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 +02002779 break;
2780 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002781 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002782 break;
2783 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002784 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002785 break;
2786 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002787 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 +02002788 break;
2789 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002790 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002791 break;
2792 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002793 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002794 return LY_EVALID;
2795 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002797 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002798checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002799 /* mandatory substatements */
2800 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002801 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002802 return LY_EVALID;
2803 }
2804
Radek Krejcibbe09a92018-11-08 09:36:54 +01002805 /* store data for collision check */
2806 if (parent) {
2807 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2808 }
2809
Michal Vasko7fbc8162018-09-17 10:35:16 +02002810 return ret;
2811}
2812
Michal Vaskoea5abea2018-09-18 13:10:54 +02002813/**
2814 * @brief Parse the input or output statement.
2815 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002816 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002817 * @param[in,out] data Data to read from, always moved to currently handled character.
2818 * @param[in] kw Type of this particular keyword
2819 * @param[in,out] inout_p Input/output pointer to write to.
2820 *
2821 * @return LY_ERR values.
2822 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002823static LY_ERR
Radek Krejci10113652018-11-14 16:56:50 +01002824parse_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 +02002825{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002826 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002827 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002828 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002829 struct lysp_action_inout *inout;
Radek Krejci10113652018-11-14 16:56:50 +01002830 enum yang_keyword kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002831
2832 if (*inout_p) {
Radek Krejci10113652018-11-14 16:56:50 +01002833 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002834 return LY_EVALID;
2835 }
2836
2837 /* create structure */
2838 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002839 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002840 *inout_p = inout;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002841 inout->nodetype = LYS_INOUT;
2842 inout->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002843
2844 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002845 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846 switch (kw) {
2847 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01002848 YANG_CHECK_STMTVER_RET(ctx, "anydata", ly_stmt2str(inout_kw));
2849 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002850 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002851 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002852 break;
2853 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002854 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002855 break;
2856 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002857 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002858 break;
2859 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002860 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002861 break;
2862 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002863 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002864 break;
2865 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002866 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002867 break;
2868 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002869 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002870 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002871 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002872 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout, data, &inout->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002873 break;
2874 case YANG_MUST:
Radek Krejci10113652018-11-14 16:56:50 +01002875 YANG_CHECK_STMTVER_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002876 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002877 break;
2878 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002879 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout, &inout->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002880 break;
2881 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002882 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002883 break;
2884 default:
Radek Krejci10113652018-11-14 16:56:50 +01002885 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002886 return LY_EVALID;
2887 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002888 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002889 return ret;
2890}
2891
Michal Vaskoea5abea2018-09-18 13:10:54 +02002892/**
2893 * @brief Parse the action statement.
2894 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002895 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002896 * @param[in,out] data Data to read from, always moved to currently handled character.
2897 * @param[in,out] actions Actions to add to.
2898 *
2899 * @return LY_ERR values.
2900 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002901static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002902parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002903{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002904 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002905 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002906 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002907 enum yang_keyword kw;
2908 struct lysp_action *act;
2909
Radek Krejci2c4e7172018-10-19 15:56:26 +02002910 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002911
2912 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002913 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002914 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002915 act->nodetype = LYS_ACTION;
2916 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002917
Radek Krejci6d6556c2018-11-08 09:37:45 +01002918 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002919 switch (kw) {
2920 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002921 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 +02002922 break;
2923 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002924 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 +02002925 break;
2926 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002927 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 +02002928 break;
2929 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002930 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002931 break;
2932
2933 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002934 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002935 break;
2936 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002937 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002938 break;
2939
2940 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002941 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002942 break;
2943 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002944 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002945 break;
2946 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002947 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002948 break;
2949 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002950 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002951 return LY_EVALID;
2952 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002953 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002954 return ret;
2955}
2956
Michal Vaskoea5abea2018-09-18 13:10:54 +02002957/**
2958 * @brief Parse the notification statement.
2959 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002960 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002961 * @param[in,out] data Data to read from, always moved to currently handled character.
2962 * @param[in,out] notifs Notifications to add to.
2963 *
2964 * @return LY_ERR values.
2965 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002966static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002967parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002968{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002969 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002970 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002971 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002972 enum yang_keyword kw;
2973 struct lysp_notif *notif;
2974
Radek Krejci2c4e7172018-10-19 15:56:26 +02002975 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002976
2977 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002978 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002979 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002980 notif->nodetype = LYS_NOTIF;
2981 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002982
Radek Krejci6d6556c2018-11-08 09:37:45 +01002983 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002984 switch (kw) {
2985 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002986 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 +02002987 break;
2988 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002989 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 +02002990 break;
2991 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002992 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 +02002993 break;
2994 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002995 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002996 break;
2997
2998 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01002999 YANG_CHECK_STMTVER_RET(ctx, "anydata", "notification");
3000 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003001 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003002 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003003 break;
3004 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003005 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003006 break;
3007 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003008 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003009 break;
3010 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003011 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003012 break;
3013 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003014 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003015 break;
3016 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003017 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003018 break;
3019 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003020 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003021 break;
3022
3023 case YANG_MUST:
Radek Krejci10113652018-11-14 16:56:50 +01003024 YANG_CHECK_STMTVER_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003025 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003026 break;
3027 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003028 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003029 break;
3030 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003031 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032 break;
3033 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003034 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003035 break;
3036 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003037 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003038 return LY_EVALID;
3039 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003040 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003041 return ret;
3042}
3043
Michal Vaskoea5abea2018-09-18 13:10:54 +02003044/**
3045 * @brief Parse the grouping statement.
3046 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003047 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003048 * @param[in,out] data Data to read from, always moved to currently handled character.
3049 * @param[in,out] groupings Groupings to add to.
3050 *
3051 * @return LY_ERR values.
3052 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003053static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003054parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003055{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003056 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003057 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003058 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003059 enum yang_keyword kw;
3060 struct lysp_grp *grp;
3061
Radek Krejci2c4e7172018-10-19 15:56:26 +02003062 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003063
3064 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003065 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003066 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003067 grp->nodetype = LYS_GROUPING;
3068 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003069
Radek Krejci6d6556c2018-11-08 09:37:45 +01003070 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071 switch (kw) {
3072 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003073 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 +02003074 break;
3075 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003076 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 +02003077 break;
3078 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003079 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003080 break;
3081
3082 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003083 YANG_CHECK_STMTVER_RET(ctx, "anydata", "grouping");
3084 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003085 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003086 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003087 break;
3088 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003089 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003090 break;
3091 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003092 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003093 break;
3094 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003095 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003096 break;
3097 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003098 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003099 break;
3100 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003101 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003102 break;
3103 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003104 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003105 break;
3106
3107 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003108 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003109 break;
3110 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003111 YANG_CHECK_STMTVER_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003112 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003113 break;
3114 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003115 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003116 break;
3117 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003118 YANG_CHECK_STMTVER_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003119 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003120 break;
3121 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003122 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003123 break;
3124 default:
Radek Krejci10113652018-11-14 16:56:50 +01003125 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003126 return LY_EVALID;
3127 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003128 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003129 return ret;
3130}
3131
Michal Vaskoea5abea2018-09-18 13:10:54 +02003132/**
3133 * @brief Parse the refine statement.
3134 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003135 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003136 * @param[in,out] data Data to read from, always moved to currently handled character.
3137 * @param[in,out] augments Augments to add to.
3138 *
3139 * @return LY_ERR values.
3140 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003141static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003142parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003143{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003144 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003145 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003146 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003147 enum yang_keyword kw;
3148 struct lysp_augment *aug;
3149
Radek Krejci2c4e7172018-10-19 15:56:26 +02003150 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003151
3152 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003153 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003154 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003155 aug->nodetype = LYS_AUGMENT;
3156 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003157
Radek Krejci6d6556c2018-11-08 09:37:45 +01003158 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003159 switch (kw) {
3160 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003161 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 +02003162 break;
3163 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003164 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 +02003165 break;
3166 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003167 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 +02003168 break;
3169 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003170 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003171 break;
3172 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003174 break;
3175
3176 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003177 YANG_CHECK_STMTVER_RET(ctx, "anydata", "augment");
3178 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003179 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003180 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003181 break;
3182 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003183 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003184 break;
3185 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003186 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003187 break;
3188 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003189 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003190 break;
3191 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003192 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003193 break;
3194 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003195 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003196 break;
3197 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003198 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003199 break;
3200 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003201 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003202 break;
3203
3204 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003205 YANG_CHECK_STMTVER_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003206 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003207 break;
3208 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003209 YANG_CHECK_STMTVER_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003210 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003211 break;
3212 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003213 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003214 break;
3215 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003216 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003217 return LY_EVALID;
3218 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003219 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003220 return ret;
3221}
3222
Michal Vaskoea5abea2018-09-18 13:10:54 +02003223/**
3224 * @brief Parse the uses statement.
3225 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003226 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003227 * @param[in,out] data Data to read from, always moved to currently handled character.
3228 * @param[in,out] siblings Siblings to add to.
3229 *
3230 * @return LY_ERR values.
3231 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003232static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003233parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003234{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003235 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003236 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003237 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003238 enum yang_keyword kw;
3239 struct lysp_node *iter;
3240 struct lysp_node_uses *uses;
3241
3242 /* create structure */
3243 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003244 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003245 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003246 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003247
3248 /* insert into siblings */
3249 if (!*siblings) {
3250 *siblings = (struct lysp_node *)uses;
3251 } else {
3252 for (iter = *siblings; iter->next; iter = iter->next);
3253 iter->next = (struct lysp_node *)uses;
3254 }
3255
3256 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003257 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003258 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003259
3260 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003261 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003262 switch (kw) {
3263 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003264 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 +02003265 break;
3266 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003267 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 +02003268 break;
3269 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003270 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 +02003271 break;
3272 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003273 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003274 break;
3275 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003276 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003277 break;
3278
3279 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003280 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003281 break;
3282 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003283 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003284 break;
3285 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003286 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003287 break;
3288 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003289 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003290 return LY_EVALID;
3291 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003292 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003293 return ret;
3294}
3295
Michal Vaskoea5abea2018-09-18 13:10:54 +02003296/**
3297 * @brief Parse the case statement.
3298 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003299 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003300 * @param[in,out] data Data to read from, always moved to currently handled character.
3301 * @param[in,out] siblings Siblings to add to.
3302 *
3303 * @return LY_ERR values.
3304 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003305static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003306parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003307{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003308 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003309 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003310 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003311 enum yang_keyword kw;
3312 struct lysp_node *iter;
3313 struct lysp_node_case *cas;
3314
3315 /* create structure */
3316 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003317 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003318 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003319 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003320
3321 /* insert into siblings */
3322 if (!*siblings) {
3323 *siblings = (struct lysp_node *)cas;
3324 } else {
3325 for (iter = *siblings; iter->next; iter = iter->next);
3326 iter->next = (struct lysp_node *)cas;
3327 }
3328
3329 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003330 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003331 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003332
3333 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003334 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003335 switch (kw) {
3336 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003337 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 +02003338 break;
3339 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003340 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 +02003341 break;
3342 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003343 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 +02003344 break;
3345 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003346 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003347 break;
3348 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003349 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003350 break;
3351
3352 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003353 YANG_CHECK_STMTVER_RET(ctx, "anydata", "case");
3354 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003355 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003356 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003357 break;
3358 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003359 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003360 break;
3361 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003362 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003363 break;
3364 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003365 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003366 break;
3367 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003368 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003369 break;
3370 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003371 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003372 break;
3373 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003374 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003375 break;
3376 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003377 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003378 break;
3379 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003380 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003381 return LY_EVALID;
3382 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003383 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003384 return ret;
3385}
3386
Michal Vaskoea5abea2018-09-18 13:10:54 +02003387/**
3388 * @brief Parse the choice statement.
3389 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003390 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003391 * @param[in,out] data Data to read from, always moved to currently handled character.
3392 * @param[in,out] siblings Siblings to add to.
3393 *
3394 * @return LY_ERR values.
3395 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003396static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003397parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003398{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003399 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003400 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003401 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003402 enum yang_keyword kw;
3403 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003404 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003405
3406 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003407 choice = calloc(1, sizeof *choice);
3408 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3409 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003410 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003411
3412 /* insert into siblings */
3413 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003414 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003415 } else {
3416 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003417 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003418 }
3419
3420 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003421 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003422 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003423
3424 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003425 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003426 switch (kw) {
3427 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003428 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003429 break;
3430 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003431 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 +02003432 break;
3433 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003434 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 +02003435 break;
3436 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003437 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003438 break;
3439 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003440 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 +02003441 break;
3442 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003443 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003444 break;
3445 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003446 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003447 break;
3448 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003449 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 +02003450 break;
3451
3452 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003453 YANG_CHECK_STMTVER_RET(ctx, "anydata", "choice");
3454 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003455 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003456 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003457 break;
3458 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003459 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003460 break;
3461 case YANG_CHOICE:
Radek Krejci10113652018-11-14 16:56:50 +01003462 YANG_CHECK_STMTVER_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003463 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003464 break;
3465 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003466 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003467 break;
3468 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003469 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003470 break;
3471 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003472 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003473 break;
3474 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003475 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003476 break;
3477 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003478 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003479 break;
3480 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003481 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003482 return LY_EVALID;
3483 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003484 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003485 return ret;
3486}
3487
Michal Vaskoea5abea2018-09-18 13:10:54 +02003488/**
3489 * @brief Parse the container statement.
3490 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003491 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003492 * @param[in,out] data Data to read from, always moved to currently handled character.
3493 * @param[in,out] siblings Siblings to add to.
3494 *
3495 * @return LY_ERR values.
3496 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003497static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003498parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003499{
3500 LY_ERR ret = 0;
3501 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003502 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003503 enum yang_keyword kw;
3504 struct lysp_node *iter;
3505 struct lysp_node_container *cont;
3506
3507 /* create structure */
3508 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003509 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003510 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003511 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003512
3513 /* insert into siblings */
3514 if (!*siblings) {
3515 *siblings = (struct lysp_node *)cont;
3516 } else {
3517 for (iter = *siblings; iter->next; iter = iter->next);
3518 iter->next = (struct lysp_node *)cont;
3519 }
3520
3521 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003522 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003523 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003524
3525 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003526 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003527 switch (kw) {
3528 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003529 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530 break;
3531 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003532 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 +02003533 break;
3534 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003535 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 +02003536 break;
3537 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003538 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 +02003539 break;
3540 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003541 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003542 break;
3543 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003544 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003545 break;
3546 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003547 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 +02003548 break;
3549
3550 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003551 YANG_CHECK_STMTVER_RET(ctx, "anydata", "container");
3552 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003553 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003554 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003555 break;
3556 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003557 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 break;
3559 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003560 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561 break;
3562 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003563 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003564 break;
3565 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003566 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567 break;
3568 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003569 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003570 break;
3571 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003572 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003573 break;
3574
3575 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003576 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003577 break;
3578 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003579 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003580 break;
3581 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003582 YANG_CHECK_STMTVER_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003583 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584 break;
3585 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003586 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003587 break;
3588 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003589 YANG_CHECK_STMTVER_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003590 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003591 break;
3592 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003593 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003594 break;
3595 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003596 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003597 return LY_EVALID;
3598 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003599 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003600 return ret;
3601}
3602
Michal Vaskoea5abea2018-09-18 13:10:54 +02003603/**
3604 * @brief Parse the list statement.
3605 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003606 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003607 * @param[in,out] data Data to read from, always moved to currently handled character.
3608 * @param[in,out] siblings Siblings to add to.
3609 *
3610 * @return LY_ERR values.
3611 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003612static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003613parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003614{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003615 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003616 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003617 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003618 enum yang_keyword kw;
3619 struct lysp_node *iter;
3620 struct lysp_node_list *list;
3621
3622 /* create structure */
3623 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003624 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003625 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003626 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003627
3628 /* insert into siblings */
3629 if (!*siblings) {
3630 *siblings = (struct lysp_node *)list;
3631 } else {
3632 for (iter = *siblings; iter->next; iter = iter->next);
3633 iter->next = (struct lysp_node *)list;
3634 }
3635
3636 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003637 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003638 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003639
3640 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003641 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003642 switch (kw) {
3643 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003644 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003645 break;
3646 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003647 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 +02003648 break;
3649 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003650 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 +02003651 break;
3652 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003653 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 +02003654 break;
3655 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003656 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003657 break;
3658 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003659 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003660 break;
3661 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003662 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 +02003663 break;
3664 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003665 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003666 break;
3667 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003668 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003669 break;
3670 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003671 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003672 break;
3673 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003674 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 +02003675 break;
3676
3677 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003678 YANG_CHECK_STMTVER_RET(ctx, "anydata", "list");
3679 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003680 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003681 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003682 break;
3683 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003684 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003685 break;
3686 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003687 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003688 break;
3689 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003690 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003691 break;
3692 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003693 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003694 break;
3695 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003696 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003697 break;
3698 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003699 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003700 break;
3701
3702 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003703 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003704 break;
3705 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003706 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003707 break;
3708 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003709 YANG_CHECK_STMTVER_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003710 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003711 break;
3712 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003713 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003714 break;
3715 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003716 YANG_CHECK_STMTVER_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003717 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003718 break;
3719 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003720 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003721 break;
3722 default:
Radek Krejci10113652018-11-14 16:56:50 +01003723 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003724 return LY_EVALID;
3725 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003726 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003727
3728 return ret;
3729}
3730
Michal Vaskoea5abea2018-09-18 13:10:54 +02003731/**
3732 * @brief Parse the yin-element statement.
3733 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003734 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003735 * @param[in,out] data Data to read from, always moved to currently handled character.
3736 * @param[in,out] flags Flags to write to.
3737 * @param[in,out] exts Extension instances to add to.
3738 *
3739 * @return LY_ERR values.
3740 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003741static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003742parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003743{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003744 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003745 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003746 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003747 enum yang_keyword kw;
3748
3749 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003750 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003751 return LY_EVALID;
3752 }
3753
3754 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003755 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003756
3757 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3758 *flags |= LYS_YINELEM_TRUE;
3759 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3760 *flags |= LYS_YINELEM_FALSE;
3761 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003762 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003763 free(buf);
3764 return LY_EVALID;
3765 }
3766 free(buf);
3767
Radek Krejci6d6556c2018-11-08 09:37:45 +01003768 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003769 switch (kw) {
3770 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003771 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3772 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003773 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003774 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003775 return LY_EVALID;
3776 }
3777 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003778 return ret;
3779}
3780
Michal Vaskoea5abea2018-09-18 13:10:54 +02003781/**
3782 * @brief Parse the yin-element statement.
3783 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003784 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003785 * @param[in,out] data Data to read from, always moved to currently handled character.
3786 * @param[in,out] argument Value to write to.
3787 * @param[in,out] flags Flags to write to.
3788 * @param[in,out] exts Extension instances to add to.
3789 *
3790 * @return LY_ERR values.
3791 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003792static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003793parse_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 +02003794{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003795 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003796 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003797 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003798 enum yang_keyword kw;
3799
3800 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003801 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003802 return LY_EVALID;
3803 }
3804
3805 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003806 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003807 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003808
Radek Krejci6d6556c2018-11-08 09:37:45 +01003809 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003810 switch (kw) {
3811 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003812 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003813 break;
3814 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003815 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003816 break;
3817 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003818 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003819 return LY_EVALID;
3820 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003821 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003822 return ret;
3823}
3824
Michal Vaskoea5abea2018-09-18 13:10:54 +02003825/**
3826 * @brief Parse the extension statement.
3827 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003828 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003829 * @param[in,out] data Data to read from, always moved to currently handled character.
3830 * @param[in,out] extensions Extensions to add to.
3831 *
3832 * @return LY_ERR values.
3833 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003834static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003835parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003836{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003837 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003838 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003839 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003840 enum yang_keyword kw;
3841 struct lysp_ext *ex;
3842
Radek Krejci2c4e7172018-10-19 15:56:26 +02003843 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003844
3845 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003846 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003847 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003848
Radek Krejci6d6556c2018-11-08 09:37:45 +01003849 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003850 switch (kw) {
3851 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003852 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 +02003853 break;
3854 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003855 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 +02003856 break;
3857 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003858 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003859 break;
3860 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003861 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003862 break;
3863 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003864 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003865 break;
3866 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003867 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003868 return LY_EVALID;
3869 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003870 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003871 return ret;
3872}
3873
Michal Vaskoea5abea2018-09-18 13:10:54 +02003874/**
3875 * @brief Parse the deviate statement.
3876 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003877 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003878 * @param[in,out] data Data to read from, always moved to currently handled character.
3879 * @param[in,out] deviates Deviates to add to.
3880 *
3881 * @return LY_ERR values.
3882 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003883static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003884parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003885{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003886 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003887 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003888 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003889 enum yang_keyword kw;
3890 struct lysp_deviate *iter, *d;
3891 struct lysp_deviate_add *d_add = NULL;
3892 struct lysp_deviate_rpl *d_rpl = NULL;
3893 struct lysp_deviate_del *d_del = NULL;
3894 const char **d_units, ***d_uniques, ***d_dflts;
3895 struct lysp_restr **d_musts;
3896 uint16_t *d_flags;
3897 uint32_t *d_min, *d_max;
3898
3899 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003900 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003901
3902 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3903 dev_mod = LYS_DEV_NOT_SUPPORTED;
3904 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3905 dev_mod = LYS_DEV_ADD;
3906 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3907 dev_mod = LYS_DEV_REPLACE;
3908 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3909 dev_mod = LYS_DEV_DELETE;
3910 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003911 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003912 free(buf);
3913 return LY_EVALID;
3914 }
3915 free(buf);
3916
3917 /* create structure */
3918 switch (dev_mod) {
3919 case LYS_DEV_NOT_SUPPORTED:
3920 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003921 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 break;
3923 case LYS_DEV_ADD:
3924 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003925 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003926 d = (struct lysp_deviate *)d_add;
3927 d_units = &d_add->units;
3928 d_uniques = &d_add->uniques;
3929 d_dflts = &d_add->dflts;
3930 d_musts = &d_add->musts;
3931 d_flags = &d_add->flags;
3932 d_min = &d_add->min;
3933 d_max = &d_add->max;
3934 break;
3935 case LYS_DEV_REPLACE:
3936 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003937 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003938 d = (struct lysp_deviate *)d_rpl;
3939 d_units = &d_rpl->units;
3940 d_flags = &d_rpl->flags;
3941 d_min = &d_rpl->min;
3942 d_max = &d_rpl->max;
3943 break;
3944 case LYS_DEV_DELETE:
3945 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003946 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003947 d = (struct lysp_deviate *)d_del;
3948 d_units = &d_del->units;
3949 d_uniques = &d_del->uniques;
3950 d_dflts = &d_del->dflts;
3951 d_musts = &d_del->musts;
3952 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003953 break;
3954 default:
3955 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003956 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003957 }
3958 d->mod = dev_mod;
3959
3960 /* insert into siblings */
3961 if (!*deviates) {
3962 *deviates = d;
3963 } else {
3964 for (iter = *deviates; iter->next; iter = iter->next);
3965 iter->next = d;
3966 }
3967
Radek Krejci6d6556c2018-11-08 09:37:45 +01003968 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003969 switch (kw) {
3970 case YANG_CONFIG:
3971 switch (dev_mod) {
3972 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003973 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003974 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003975 return LY_EVALID;
3976 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003977 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003978 break;
3979 }
3980 break;
3981 case YANG_DEFAULT:
3982 switch (dev_mod) {
3983 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003984 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003985 return LY_EVALID;
3986 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003987 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 +02003988 break;
3989 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003990 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 +02003991 break;
3992 }
3993 break;
3994 case YANG_MANDATORY:
3995 switch (dev_mod) {
3996 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003997 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003998 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003999 return LY_EVALID;
4000 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004001 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004002 break;
4003 }
4004 break;
4005 case YANG_MAX_ELEMENTS:
4006 switch (dev_mod) {
4007 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004008 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004009 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004010 return LY_EVALID;
4011 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004012 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004013 break;
4014 }
4015 break;
4016 case YANG_MIN_ELEMENTS:
4017 switch (dev_mod) {
4018 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004019 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004020 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004021 return LY_EVALID;
4022 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004023 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004024 break;
4025 }
4026 break;
4027 case YANG_MUST:
4028 switch (dev_mod) {
4029 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004030 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004031 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004032 return LY_EVALID;
4033 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004034 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004035 break;
4036 }
4037 break;
4038 case YANG_TYPE:
4039 switch (dev_mod) {
4040 case LYS_DEV_NOT_SUPPORTED:
4041 case LYS_DEV_ADD:
4042 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004043 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004044 return LY_EVALID;
4045 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004046 if (d_rpl->type) {
4047 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4048 return LY_EVALID;
4049 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004050 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004051 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004052 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004053 break;
4054 }
4055 break;
4056 case YANG_UNIQUE:
4057 switch (dev_mod) {
4058 case LYS_DEV_NOT_SUPPORTED:
4059 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004060 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004061 return LY_EVALID;
4062 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004063 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004064 break;
4065 }
4066 break;
4067 case YANG_UNITS:
4068 switch (dev_mod) {
4069 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004070 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004071 return LY_EVALID;
4072 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004073 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 +02004074 break;
4075 }
4076 break;
4077 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004078 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004079 break;
4080 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004081 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004082 return LY_EVALID;
4083 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004084 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004085 return ret;
4086}
4087
Michal Vaskoea5abea2018-09-18 13:10:54 +02004088/**
4089 * @brief Parse the deviation statement.
4090 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004091 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004092 * @param[in,out] data Data to read from, always moved to currently handled character.
4093 * @param[in,out] deviations Deviations to add to.
4094 *
4095 * @return LY_ERR values.
4096 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004097static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004098parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004099{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004100 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004101 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004102 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004103 enum yang_keyword kw;
4104 struct lysp_deviation *dev;
4105
Radek Krejci2c4e7172018-10-19 15:56:26 +02004106 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004107
4108 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004109 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004110 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004111
Radek Krejci6d6556c2018-11-08 09:37:45 +01004112 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004113 switch (kw) {
4114 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004115 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 +02004116 break;
4117 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004118 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004119 break;
4120 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004121 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 +02004122 break;
4123 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004124 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004125 break;
4126 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004127 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004128 return LY_EVALID;
4129 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004130 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004131 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004132checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004133 /* mandatory substatements */
4134 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004135 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004136 return LY_EVALID;
4137 }
4138
4139 return ret;
4140}
4141
Michal Vaskoea5abea2018-09-18 13:10:54 +02004142/**
4143 * @brief Parse the feature statement.
4144 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004145 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004146 * @param[in,out] data Data to read from, always moved to currently handled character.
4147 * @param[in,out] features Features to add to.
4148 *
4149 * @return LY_ERR values.
4150 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004151static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004152parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004153{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004154 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004155 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004156 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004157 enum yang_keyword kw;
4158 struct lysp_feature *feat;
4159
Radek Krejci2c4e7172018-10-19 15:56:26 +02004160 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004161
4162 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004163 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004164 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004165
4166 CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
4167
Radek Krejci6d6556c2018-11-08 09:37:45 +01004168 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004169 switch (kw) {
4170 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004171 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 +02004172 break;
4173 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004174 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 +02004175 break;
4176 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004177 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 +02004178 break;
4179 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004180 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004181 break;
4182 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004183 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004184 break;
4185 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004186 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004187 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004188 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004189 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004190 return ret;
4191}
4192
Michal Vaskoea5abea2018-09-18 13:10:54 +02004193/**
4194 * @brief Parse the identity statement.
4195 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004196 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004197 * @param[in,out] data Data to read from, always moved to currently handled character.
4198 * @param[in,out] identities Identities to add to.
4199 *
4200 * @return LY_ERR values.
4201 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004202static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004203parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004204{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004205 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004206 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004207 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004208 enum yang_keyword kw;
4209 struct lysp_ident *ident;
4210
Radek Krejci2c4e7172018-10-19 15:56:26 +02004211 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004212
4213 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004214 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004215 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004216
4217 CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
4218
Radek Krejci6d6556c2018-11-08 09:37:45 +01004219 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004220 switch (kw) {
4221 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004222 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 +02004223 break;
4224 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01004225 YANG_CHECK_STMTVER_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004226 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 +02004227 break;
4228 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004229 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 +02004230 break;
4231 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004232 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004233 break;
4234 case YANG_BASE:
Radek Krejci10113652018-11-14 16:56:50 +01004235 if (ident->bases && ctx->mod->version < 2) {
4236 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4237 return LY_EVALID;
4238 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004239 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 +02004240 break;
4241 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004242 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004243 break;
4244 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004245 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004246 return LY_EVALID;
4247 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004248 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004249 return ret;
4250}
4251
Michal Vaskoea5abea2018-09-18 13:10:54 +02004252/**
4253 * @brief Parse the module or submodule statement.
4254 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004255 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004256 * @param[in,out] data Data to read from, always moved to currently handled character.
4257 * @param[in,out] mod Module to write to.
4258 *
4259 * @return LY_ERR values.
4260 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004261static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004262parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004263{
4264 LY_ERR ret = 0;
4265 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004266 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004267 enum yang_keyword kw, prev_kw = 0;
4268 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejcie9e987e2018-10-31 12:50:27 +01004269 struct lysp_module *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004270
4271 /* (sub)module name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004272 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004273 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004274
Radek Krejci6d6556c2018-11-08 09:37:45 +01004275 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004276
Radek Krejcie3846472018-10-15 15:24:51 +02004277#define CHECK_ORDER(SECTION) \
4278 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4279
Michal Vasko7fbc8162018-09-17 10:35:16 +02004280 switch (kw) {
4281 /* module header */
4282 case YANG_NAMESPACE:
4283 case YANG_PREFIX:
4284 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004285 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004286 return LY_EVALID;
4287 }
Radek Krejcie3846472018-10-15 15:24:51 +02004288 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4289 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004290 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004291 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004292 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004293 return LY_EVALID;
4294 }
Radek Krejcie3846472018-10-15 15:24:51 +02004295 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4296 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004297 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004298 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004299 break;
4300 /* linkage */
4301 case YANG_INCLUDE:
4302 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004303 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004304 break;
4305 /* meta */
4306 case YANG_ORGANIZATION:
4307 case YANG_CONTACT:
4308 case YANG_DESCRIPTION:
4309 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004310 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004311 break;
4312
4313 /* revision */
4314 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004315 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004317 /* body */
4318 case YANG_ANYDATA:
4319 case YANG_ANYXML:
4320 case YANG_AUGMENT:
4321 case YANG_CHOICE:
4322 case YANG_CONTAINER:
4323 case YANG_DEVIATION:
4324 case YANG_EXTENSION:
4325 case YANG_FEATURE:
4326 case YANG_GROUPING:
4327 case YANG_IDENTITY:
4328 case YANG_LEAF:
4329 case YANG_LEAF_LIST:
4330 case YANG_LIST:
4331 case YANG_NOTIFICATION:
4332 case YANG_RPC:
4333 case YANG_TYPEDEF:
4334 case YANG_USES:
4335 case YANG_CUSTOM:
4336 mod_stmt = Y_MOD_BODY;
4337 break;
4338 default:
4339 /* error handled in the next switch */
4340 break;
4341 }
Radek Krejcie3846472018-10-15 15:24:51 +02004342#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004343
Radek Krejcie3846472018-10-15 15:24:51 +02004344 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004345 switch (kw) {
4346 /* module header */
4347 case YANG_YANG_VERSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004348 LY_CHECK_RET(parse_yangversion(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004349 break;
4350 case YANG_NAMESPACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004351 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 +02004352 break;
4353 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004354 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 +02004355 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004356 break;
4357 case YANG_BELONGS_TO:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004358 LY_CHECK_RET(parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004359 break;
4360
4361 /* linkage */
4362 case YANG_INCLUDE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004363 LY_CHECK_RET(parse_include(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004364 break;
4365 case YANG_IMPORT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004366 LY_CHECK_RET(parse_import(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004367 break;
4368
4369 /* meta */
4370 case YANG_ORGANIZATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004371 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 +02004372 break;
4373 case YANG_CONTACT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004374 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 +02004375 break;
4376 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004377 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 +02004378 break;
4379 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004380 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 +02004381 break;
4382
4383 /* revision */
4384 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004385 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004386 break;
4387
4388 /* body */
4389 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01004390 YANG_CHECK_STMTVER_RET(ctx, "anydata", mod->submodule ? "submodule" : "module");
4391 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004392 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004393 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004394 break;
4395 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004396 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004397 break;
4398 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004399 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004400 break;
4401 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004402 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004403 break;
4404 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004405 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004406 break;
4407 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004408 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004409 break;
4410 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004411 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004412 break;
4413
4414 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004415 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004416 break;
4417 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004418 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004419 break;
4420 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004421 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422 break;
4423 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004424 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004425 break;
4426 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004427 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428 break;
4429 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004430 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004431 break;
4432 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004433 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004434 break;
4435 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004436 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004437 break;
4438 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004439 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004440 break;
4441 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004442 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004443 break;
4444
4445 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004446 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004447 return LY_EVALID;
4448 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004449 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004450 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004451checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004452 /* mandatory substatements */
4453 if (mod->submodule) {
4454 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004455 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004456 return LY_EVALID;
4457 }
4458 } else {
4459 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004460 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004461 return LY_EVALID;
4462 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004463 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004464 return LY_EVALID;
4465 }
4466 }
4467
Radek Krejcie9e987e2018-10-31 12:50:27 +01004468 /* submodules share the namespace with the module names, so there must not be
4469 * a submodule of the same name in the context, no need for revision matching */
4470 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL);
4471 if (dup && (!mod->submodule || strcmp(dup->belongsto, mod->belongsto))) {
4472 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4473 mod->submodule ? "submodules" : "module and submodule", mod->name);
4474 return LY_EVALID;
4475 }
4476
Michal Vasko7fbc8162018-09-17 10:35:16 +02004477 return ret;
4478}
4479
Radek Krejcid4557c62018-09-17 11:42:09 +02004480LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01004481yang_parse(struct ly_parser_ctx *context, const char *data, struct lysp_module **mod_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004482{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004483 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004484 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004485 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004486 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004487 struct lysp_module *mod = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004488
4489 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004490 ret = get_keyword(context, &data, &kw, &word, &word_len);
4491 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004492
4493 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004494 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004495 ly_stmt2str(kw));
Radek Krejcibbe09a92018-11-08 09:36:54 +01004496 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004497 }
4498
4499 mod = calloc(1, sizeof *mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004500 LY_CHECK_ERR_GOTO(!mod, LOGMEM(context->ctx), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004501 if (kw == YANG_SUBMODULE) {
4502 mod->submodule = 1;
4503 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01004504 mod->parsing = 1;
4505 mod->ctx = context->ctx;
4506 context->mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004507
4508 /* substatements */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004509 ret = parse_sub_module(context, &data, mod);
4510 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004511
4512 /* read some trailing spaces or new lines */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004513 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4514 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004515
4516 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004517 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004518 word_len, word);
4519 free(buf);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004520 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004521 }
4522 assert(!buf);
4523
Radek Krejcibbe09a92018-11-08 09:36:54 +01004524 mod->parsing = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004525 *mod_p = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004526
Radek Krejcibbe09a92018-11-08 09:36:54 +01004527cleanup:
4528 if (ret) {
4529 lysp_module_free(mod);
4530 }
4531
Michal Vasko7fbc8162018-09-17 10:35:16 +02004532 return ret;
4533}