blob: f45426a580e863402a0fa56261c4595b547651e3 [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 Krejci6d9b9b52018-11-02 12:43:39 +010091static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
92static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
93static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
94static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
95static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
96static 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 +020097
Michal Vaskoea5abea2018-09-18 13:10:54 +020098/**
99 * @brief Add another character to dynamic buffer, a low-level function.
100 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200101 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200102 *
Radek Krejci404251e2018-10-09 12:06:44 +0200103 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200104 * @param[in, out] input Input string to process.
105 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200106 * @param[in,out] buf Buffer to use, can be moved by realloc().
107 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200108 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200109 *
110 * @return LY_ERR values.
111 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200112static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200113buf_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 +0200114{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200115 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200116 *buf_len += 16;
117 *buf = ly_realloc(*buf, *buf_len);
118 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
119 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200120 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200121
Radek Krejci44ceedc2018-10-02 15:54:31 +0200122 (*buf_used) += len;
123 (*input) += len;
124
Michal Vasko7fbc8162018-09-17 10:35:16 +0200125 return LY_SUCCESS;
126}
127
Michal Vaskoea5abea2018-09-18 13:10:54 +0200128/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200129 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200130 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200131 * @param[in] ctx yang parser context for logging.
132 * @param[in] c UTF8 code point of a character to check.
133 * @return LY_ERR values.
134 */
135static LY_ERR
136check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
137{
138 if (!is_yangutf8char(c)) {
139 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
140 return LY_EVALID;
141 }
142 return LY_SUCCESS;
143}
144
145/**
146 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
147 *
148 * @param[in] ctx yang parser context for logging.
149 * @param[in] c UTF8 code point of a character to check.
150 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200151 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
152 * 0 - colon not yet found (no prefix)
153 * 1 - \p c is the colon character
154 * 2 - prefix already processed, now processing the identifier
155 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200156 * If the identifier cannot be prefixed, NULL is expected.
157 * @return LY_ERR values.
158 */
159static LY_ERR
160check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
161{
162 if (first || (prefix && (*prefix) == 1)) {
163 if (!is_yangidentstartchar(c)) {
164 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
165 return LY_EVALID;
166 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200167 if (prefix) {
168 if (first) {
169 (*prefix) = 0;
170 } else {
171 (*prefix) = 2;
172 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200173 }
174 } else if (c == ':' && prefix && (*prefix) == 0) {
175 (*prefix) = 1;
176 } else if (!is_yangidentchar(c)) {
177 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
178 return LY_EVALID;
179 }
180
181 return LY_SUCCESS;
182}
183
184/**
185 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
186 *
187 * @param[in] ctx yang parser context for logging.
188 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
189 * when function returns.
190 * @param[in] arg Type of the input string to select method of checking character validity.
191 * @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 +0200192 * 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 +0200193 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
194 * @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 +0200195 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200196 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200197 *
198 * @return LY_ERR values.
199 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200200static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200201buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
202 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200203{
Radek Krejci404251e2018-10-09 12:06:44 +0200204 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200205 unsigned int c;
206 size_t len;
207
208 /* get UTF8 code point (and number of bytes coding the character) */
209 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
210 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
211 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200212 if (c == '\n') {
213 ctx->indent = 0;
214 } else {
215 /* note - even the multibyte character is count as 1 */
216 ++ctx->indent;
217 }
218
Radek Krejci44ceedc2018-10-02 15:54:31 +0200219 /* check character validity */
220 switch (arg) {
221 case Y_IDENTIF_ARG:
222 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
223 break;
224 case Y_PREF_IDENTIF_ARG:
225 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
226 break;
227 case Y_STR_ARG:
228 case Y_MAYBE_STR_ARG:
229 LY_CHECK_RET(check_stringchar(ctx, c));
230 break;
231 }
232
Michal Vasko7fbc8162018-09-17 10:35:16 +0200233 if (word_b && *word_b) {
234 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200235 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200236 return LY_EMEM;
237 }
238
239 /* in case of realloc */
240 *word_p = *word_b;
241 } else if (need_buf) {
242 /* first time we need a buffer, copy everything read up to now */
243 if (*word_len) {
244 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200245 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200246 *buf_len = *word_len;
247 memcpy(*word_b, *word_p, *word_len);
248 }
249
250 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200251 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200252 return LY_EMEM;
253 }
254
255 /* in case of realloc */
256 *word_p = *word_b;
257 } else {
258 /* just remember the first character pointer */
259 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200260 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200261 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200262 /* ... and update the word's length */
263 (*word_len) += len;
264 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200265 }
266
267 return LY_SUCCESS;
268}
269
Michal Vaskoea5abea2018-09-18 13:10:54 +0200270/**
271 * @brief Skip YANG comment in data.
272 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200273 * @param[in] ctx yang parser context for logging.
274 * @param[in,out] data Data to read from, automatically moved after the comment.
275 * @param[in] comment Type of the comment to process:
276 * 1 for a one-line comment,
277 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200278 *
279 * @return LY_ERR values.
280 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200281static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200282skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200283{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200284 /* internal statuses: 0 - comment ended,
285 * 1 - in line comment,
286 * 2 - in block comment,
287 * 3 - in block comment with last read character '*'
288 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200289 while (**data && comment) {
290 switch (comment) {
291 case 1:
292 if (**data == '\n') {
293 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200294 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200295 }
296 break;
297 case 2:
298 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200299 comment = 3;
300 } else if (**data == '\n') {
301 ++ctx->line;
302 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200303 break;
304 case 3:
305 if (**data == '/') {
306 comment = 0;
307 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200308 if (**data == '\n') {
309 ++ctx->line;
310 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200311 comment = 2;
312 }
313 break;
314 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200315 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200316 }
317
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200318 if (**data == '\n') {
319 ctx->indent = 0;
320 } else {
321 ++ctx->indent;
322 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200323 ++(*data);
324 }
325
326 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200327 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200328 return LY_EVALID;
329 }
330
331 return LY_SUCCESS;
332}
333
Michal Vaskoea5abea2018-09-18 13:10:54 +0200334/**
335 * @brief Read a quoted string from data.
336 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200337 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200338 * @param[in,out] data Data to read from, always moved to currently handled character.
339 * @param[in] arg Type of YANG keyword argument expected.
340 * @param[out] word_p Pointer to the read quoted string.
341 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
342 * set to NULL. Otherwise equal to \p word_p.
343 * @param[out] word_len Length of the read quoted string.
344 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
345 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
346 * indenation in the final quoted string.
347 *
348 * @return LY_ERR values.
349 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200350static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200351read_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 +0200352 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200353{
354 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
355 * 4 - string finished, now skipping whitespaces looking for +,
356 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200357 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200358 const char *c;
359
360 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200361 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200362 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200363 } else {
364 assert(**data == '\'');
365 string = 1;
366 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200367 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200368
369 while (**data && string) {
370 switch (string) {
371 case 1:
372 switch (**data) {
373 case '\'':
374 /* string may be finished, but check for + */
375 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200376 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200377 break;
378 default:
379 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200380 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 +0200381 break;
382 }
383 break;
384 case 2:
385 switch (**data) {
386 case '\"':
387 /* string may be finished, but check for + */
388 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200389 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200390 break;
391 case '\\':
392 /* special character following */
393 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200394 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200395 break;
396 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200397 if (current_indent < block_indent) {
398 ++current_indent;
399 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200400 } else {
401 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200402 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 +0200403 }
404 break;
405 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200406 if (current_indent < block_indent) {
407 assert(need_buf);
408 current_indent += 8;
409 ctx->indent += 8;
410 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
411 /* store leftover spaces from the tab */
412 c = " ";
413 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 +0200414 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200415 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200416 } else {
417 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200418 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 +0200419 /* additional characters for indentation - only 1 was count in buf_store_char */
420 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200421 }
422 break;
423 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200424 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200425 /* we will be removing the indents so we need our own buffer */
426 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200427
428 /* remove trailing tabs and spaces */
429 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
430 --(*word_len);
431 }
432
433 /* start indentation */
434 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200435 }
436
437 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200438 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
439
440 /* maintain line number */
441 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200442
443 /* reset context indentation counter for possible string after this one */
444 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200445 break;
446 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200447 /* first non-whitespace character, stop eating indentation */
448 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200449
450 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200451 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 +0200452 break;
453 }
454 break;
455 case 3:
456 /* string encoded characters */
457 switch (**data) {
458 case 'n':
459 c = "\n";
460 break;
461 case 't':
462 c = "\t";
463 break;
464 case '\"':
465 c = *data;
466 break;
467 case '\\':
468 c = *data;
469 break;
470 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200471 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200472 return LY_EVALID;
473 }
474
475 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200476 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 +0200477
478 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200479 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200480 break;
481 case 4:
482 switch (**data) {
483 case '+':
484 /* string continues */
485 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200486 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200487 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200488 case '\n':
489 ++ctx->line;
490 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200491 case ' ':
492 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200493 /* just skip */
494 break;
495 default:
496 /* string is finished */
497 goto string_end;
498 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200499 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200500 break;
501 case 5:
502 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200503 case '\n':
504 ++ctx->line;
505 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200506 case ' ':
507 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200508 /* skip */
509 break;
510 case '\'':
511 string = 1;
512 break;
513 case '\"':
514 string = 2;
515 break;
516 default:
517 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200518 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200519 return LY_EVALID;
520 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200521 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200522 break;
523 default:
524 return LY_EINT;
525 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200526 }
527
528string_end:
529 return LY_SUCCESS;
530}
531
Michal Vaskoea5abea2018-09-18 13:10:54 +0200532/**
533 * @brief Get another YANG string from the raw data.
534 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200535 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200536 * @param[in,out] data Data to read from, always moved to currently handled character.
537 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200538 * @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 +0200539 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
540 * set to NULL. Otherwise equal to \p word_p.
541 * @param[out] word_len Length of the read string.
542 *
543 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200544 */
545static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200546get_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 +0200547{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200548 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200549
550 /* word buffer - dynamically allocated */
551 *word_b = NULL;
552
553 /* word pointer - just a pointer to data */
554 *word_p = NULL;
555
556 *word_len = 0;
557 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200558 switch (**data) {
559 case '\'':
560 case '\"':
561 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200562 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
563 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
564 "unquoted string character, optsep, semicolon or opening brace");
565 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200566 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100567 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200568 goto str_end;
569 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200570 if ((*data)[1] == '/') {
571 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200572 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100573 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200574 } else if ((*data)[1] == '*') {
575 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200576 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100577 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200578 } else {
579 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100580 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 +0200581 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200582 break;
583 case ' ':
584 if (*word_len) {
585 /* word is finished */
586 goto str_end;
587 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200588 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200589 break;
590 case '\t':
591 if (*word_len) {
592 /* word is finished */
593 goto str_end;
594 }
595 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200596 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200597
598 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200599 break;
600 case '\n':
601 if (*word_len) {
602 /* word is finished */
603 goto str_end;
604 }
605 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200606 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200607
608 /* track line numbers */
609 ++ctx->line;
610
611 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200612 break;
613 case ';':
614 case '{':
615 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
616 /* word is finished */
617 goto str_end;
618 }
619
Radek Krejci44ceedc2018-10-02 15:54:31 +0200620 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200621 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200622 case '}':
623 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
624 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
625 "unquoted string character, optsep, semicolon or opening brace");
626 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200627 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200628 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 +0200629 break;
630 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200631 }
632
633str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200634 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200635 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200636 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
637 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
638 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200639 *word_p = *word_b;
640 }
641
642 return LY_SUCCESS;
643}
644
Michal Vaskoea5abea2018-09-18 13:10:54 +0200645/**
646 * @brief Get another YANG keyword from the raw data.
647 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200648 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200649 * @param[in,out] data Data to read from, always moved to currently handled character.
650 * @param[out] kw YANG keyword read.
651 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
652 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
653 *
654 * @return LY_ERR values.
655 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200656static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200657get_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 +0200658{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200659 int prefix;
660 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200661 unsigned int c;
662 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200663
664 if (word_p) {
665 *word_p = NULL;
666 *word_len = 0;
667 }
668
669 /* first skip "optsep", comments */
670 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200671 switch (**data) {
672 case '/':
673 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200674 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200675 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100676 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200677 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200678 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200679 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100680 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200681 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200682 /* error - not a comment after all, keyword cannot start with slash */
683 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
684 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200685 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200686 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200687 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200688 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200689 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200690 ctx->indent = 0;
691 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200692 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200693 /* skip whitespaces (optsep) */
694 ++ctx->indent;
695 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200696 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200697 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200698 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200699 break;
700 default:
701 /* either a keyword start or an invalid character */
702 goto keyword_start;
703 }
704
705 ++(*data);
706 }
707
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200708#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
709#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
710#define IF_KW_PREFIX_END }
711
Michal Vasko7fbc8162018-09-17 10:35:16 +0200712keyword_start:
713 word_start = *data;
714 *kw = YANG_NONE;
715
716 /* read the keyword itself */
717 switch (**data) {
718 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200719 MOVE_INPUT(ctx, data, 1);
720 IF_KW("rgument", 7, YANG_ARGUMENT)
721 else IF_KW("ugment", 6, YANG_AUGMENT)
722 else IF_KW("ction", 5, YANG_ACTION)
723 else IF_KW_PREFIX("ny", 2)
724 IF_KW("data", 4, YANG_ANYDATA)
725 else IF_KW("xml", 3, YANG_ANYXML)
726 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200727 break;
728 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200729 MOVE_INPUT(ctx, data, 1);
730 IF_KW("ase", 3, YANG_BASE)
731 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
732 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200733 break;
734 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200735 MOVE_INPUT(ctx, data, 1);
736 IF_KW("ase", 3, YANG_CASE)
737 else IF_KW("hoice", 5, YANG_CHOICE)
738 else IF_KW_PREFIX("on", 2)
739 IF_KW("fig", 3, YANG_CONFIG)
740 else IF_KW_PREFIX("ta", 2)
741 IF_KW("ct", 2, YANG_CONTACT)
742 else IF_KW("iner", 4, YANG_CONTAINER)
743 IF_KW_PREFIX_END
744 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200745 break;
746 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200747 MOVE_INPUT(ctx, data, 1);
748 IF_KW_PREFIX("e", 1)
749 IF_KW("fault", 5, YANG_DEFAULT)
750 else IF_KW("scription", 9, YANG_DESCRIPTION)
751 else IF_KW_PREFIX("viat", 4)
752 IF_KW("e", 1, YANG_DEVIATE)
753 else IF_KW("ion", 3, YANG_DEVIATION)
754 IF_KW_PREFIX_END
755 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200756 break;
757 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200758 MOVE_INPUT(ctx, data, 1);
759 IF_KW("num", 3, YANG_ENUM)
760 else IF_KW_PREFIX("rror-", 5)
761 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
762 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
763 IF_KW_PREFIX_END
764 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200765 break;
766 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200767 MOVE_INPUT(ctx, data, 1);
768 IF_KW("eature", 6, YANG_FEATURE)
769 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200770 break;
771 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200772 MOVE_INPUT(ctx, data, 1);
773 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200774 break;
775 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200776 MOVE_INPUT(ctx, data, 1);
777 IF_KW("dentity", 7, YANG_IDENTITY)
778 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
779 else IF_KW("mport", 5, YANG_IMPORT)
780 else IF_KW_PREFIX("n", 1)
781 IF_KW("clude", 5, YANG_INCLUDE)
782 else IF_KW("put", 3, YANG_INPUT)
783 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200784 break;
785 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200786 MOVE_INPUT(ctx, data, 1);
787 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200788 break;
789 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200790 MOVE_INPUT(ctx, data, 1);
791 IF_KW_PREFIX("e", 1)
792 IF_KW("af-list", 7, YANG_LEAF_LIST)
793 else IF_KW("af", 2, YANG_LEAF)
794 else IF_KW("ngth", 4, YANG_LENGTH)
795 IF_KW_PREFIX_END
796 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200797 break;
798 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200799 MOVE_INPUT(ctx, data, 1);
800 IF_KW_PREFIX("a", 1)
801 IF_KW("ndatory", 7, YANG_MANDATORY)
802 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
803 IF_KW_PREFIX_END
804 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
805 else IF_KW("ust", 3, YANG_MUST)
806 else IF_KW_PREFIX("od", 2)
807 IF_KW("ule", 3, YANG_MODULE)
808 else IF_KW("ifier", 5, YANG_MODIFIER)
809 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200810 break;
811 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200812 MOVE_INPUT(ctx, data, 1);
813 IF_KW("amespace", 8, YANG_NAMESPACE)
814 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200815 break;
816 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200817 MOVE_INPUT(ctx, data, 1);
818 IF_KW_PREFIX("r", 1)
819 IF_KW("dered-by", 8, YANG_ORDERED_BY)
820 else IF_KW("ganization", 10, YANG_ORGANIZATION)
821 IF_KW_PREFIX_END
822 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200823 break;
824 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200825 MOVE_INPUT(ctx, data, 1);
826 IF_KW("ath", 3, YANG_PATH)
827 else IF_KW("attern", 6, YANG_PATTERN)
828 else IF_KW("osition", 7, YANG_POSITION)
829 else IF_KW_PREFIX("re", 2)
830 IF_KW("fix", 3, YANG_PREFIX)
831 else IF_KW("sence", 5, YANG_PRESENCE)
832 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200833 break;
834 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200835 MOVE_INPUT(ctx, data, 1);
836 IF_KW("ange", 4, YANG_RANGE)
837 else IF_KW_PREFIX("e", 1)
838 IF_KW_PREFIX("f", 1)
839 IF_KW("erence", 6, YANG_REFERENCE)
840 else IF_KW("ine", 3, YANG_REFINE)
841 IF_KW_PREFIX_END
842 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
843 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
844 else IF_KW("vision", 6, YANG_REVISION)
845 IF_KW_PREFIX_END
846 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200847 break;
848 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200849 MOVE_INPUT(ctx, data, 1);
850 IF_KW("tatus", 5, YANG_STATUS)
851 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200852 break;
853 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200854 MOVE_INPUT(ctx, data, 1);
855 IF_KW("ypedef", 6, YANG_TYPEDEF)
856 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200857 break;
858 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200859 MOVE_INPUT(ctx, data, 1);
860 IF_KW_PREFIX("ni", 2)
861 IF_KW("que", 3, YANG_UNIQUE)
862 else IF_KW("ts", 2, YANG_UNITS)
863 IF_KW_PREFIX_END
864 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200865 break;
866 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200867 MOVE_INPUT(ctx, data, 1);
868 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200869 break;
870 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200871 MOVE_INPUT(ctx, data, 1);
872 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200873 break;
874 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200875 MOVE_INPUT(ctx, data, 1);
876 IF_KW("ang-version", 11, YANG_YANG_VERSION)
877 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200878 break;
879 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200880 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200881 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200882 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200883 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200884 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200885 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200886 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200887 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200888 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200889 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200890 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200891 default:
892 break;
893 }
894
895 if (*kw != YANG_NONE) {
896 /* make sure we have the whole keyword */
897 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200898 case '\n':
899 ++ctx->line;
900 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200901 case ' ':
902 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200903 /* mandatory "sep" */
904 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200905 case ':':
906 /* keyword is not actually a keyword, but prefix of an extension.
907 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
908 * and we will be checking the keyword (extension instance) itself */
909 prefix = 1;
910 MOVE_INPUT(ctx, data, 1);
911 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200912 case '{':
913 /* allowed only for input and output statements which can be without arguments */
914 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
915 break;
916 }
917 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200918 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200919 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200920 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
921 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200922 return LY_EVALID;
923 }
924 } else {
925 /* still can be an extension */
926 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200927extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200928 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200929 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
930 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200931 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200932 /* check character validity */
933 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200934 }
935 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200936 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200937 return LY_EVALID;
938 }
939
940 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200941 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200942 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200943 return LY_EVALID;
944 }
945
946 *kw = YANG_CUSTOM;
947 }
Radek Krejci626df482018-10-11 15:06:31 +0200948success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200949 if (word_p) {
950 *word_p = (char *)word_start;
951 *word_len = *data - word_start;
952 }
953
954 return LY_SUCCESS;
955}
956
Michal Vaskoea5abea2018-09-18 13:10:54 +0200957/**
958 * @brief Parse extension instance substatements.
959 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200960 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200961 * @param[in,out] data Data to read from, always moved to currently handled character.
962 * @param[in] word Extension instance substatement name (keyword).
963 * @param[in] word_len Extension instance substatement name length.
964 * @param[in,out] child Children of this extension instance to add to.
965 *
966 * @return LY_ERR values.
967 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200968static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200969parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200970 struct lysp_stmt **child)
971{
972 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100973 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200974 enum yang_keyword kw;
975 struct lysp_stmt *stmt, *par_child;
976
977 stmt = calloc(1, sizeof *stmt);
978 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
979
Radek Krejci44ceedc2018-10-02 15:54:31 +0200980 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200981
982 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100983 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200984
Radek Krejci0ae092d2018-09-20 16:43:19 +0200985 if (word) {
986 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200987 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200988 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200989 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200990 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200991 }
992
993 /* insert into parent statements */
994 if (!*child) {
995 *child = stmt;
996 } else {
997 for (par_child = *child; par_child->next; par_child = par_child->next);
998 par_child->next = stmt;
999 }
1000
Radek Krejci6d6556c2018-11-08 09:37:45 +01001001 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001002 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001003 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001004 return ret;
1005}
1006
Michal Vaskoea5abea2018-09-18 13:10:54 +02001007/**
1008 * @brief Parse extension instance.
1009 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001010 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001011 * @param[in,out] data Data to read from, always moved to currently handled character.
1012 * @param[in] ext_name Extension instance substatement name (keyword).
1013 * @param[in] ext_name_len Extension instance substatement name length.
1014 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1015 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1016 * @param[in,out] exts Extension instances to add to.
1017 *
1018 * @return LY_ERR values.
1019 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001020static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001021parse_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 +02001022 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1023{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001024 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001025 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001026 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001027 struct lysp_ext_instance *e;
1028 enum yang_keyword kw;
1029
Radek Krejci2c4e7172018-10-19 15:56:26 +02001030 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001031
1032 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001033 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001034 e->insubstmt = insubstmt;
1035 e->insubstmt_index = insubstmt_index;
1036
1037 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001038 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001039
Radek Krejci0ae092d2018-09-20 16:43:19 +02001040 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001041 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001042 }
1043
Radek Krejci6d6556c2018-11-08 09:37:45 +01001044 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001045 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001046 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001047 return ret;
1048}
1049
Michal Vaskoea5abea2018-09-18 13:10:54 +02001050/**
1051 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1052 * description, etc...
1053 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001054 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001055 * @param[in,out] data Data to read from, always moved to currently handled character.
1056 * @param[in] substmt Type of this substatement.
1057 * @param[in] substmt_index Index of this substatement.
1058 * @param[in,out] value Place to store the parsed value.
1059 * @param[in] arg Type of the YANG keyword argument (of the value).
1060 * @param[in,out] exts Extension instances to add to.
1061 *
1062 * @return LY_ERR values.
1063 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001064static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001065parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001066 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1067{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001068 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001069 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001070 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001071 enum yang_keyword kw;
1072
1073 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001074 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001075 return LY_EVALID;
1076 }
1077
1078 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001079 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001080
1081 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001082 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001083
Radek Krejci6d6556c2018-11-08 09:37:45 +01001084 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001085 switch (kw) {
1086 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001087 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001088 break;
1089 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001090 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001091 return LY_EVALID;
1092 }
1093 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001094 return ret;
1095}
1096
Michal Vaskoea5abea2018-09-18 13:10:54 +02001097/**
1098 * @brief Parse the yang-version statement.
1099 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001100 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001101 * @param[in,out] data Data to read from, always moved to currently handled character.
1102 * @param[in] mod Module to store the parsed information in.
1103 *
1104 * @return LY_ERR values.
1105 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001106static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001107parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001108{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001109 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001110 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001111 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001112 enum yang_keyword kw;
1113
1114 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001115 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001116 return LY_EVALID;
1117 }
1118
1119 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001120 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001121
1122 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1123 mod->version = LYS_VERSION_1_0;
1124 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1125 mod->version = LYS_VERSION_1_1;
1126 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001127 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001128 free(buf);
1129 return LY_EVALID;
1130 }
1131 free(buf);
1132
Radek Krejci6d6556c2018-11-08 09:37:45 +01001133 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001134 switch (kw) {
1135 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001136 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001137 break;
1138 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001139 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001140 return LY_EVALID;
1141 }
1142 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001143 return ret;
1144}
1145
Michal Vaskoea5abea2018-09-18 13:10:54 +02001146/**
1147 * @brief Parse the belongs-to statement.
1148 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001149 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001150 * @param[in,out] data Data to read from, always moved to currently handled character.
1151 * @param[in,out] belongsto Place to store the parsed value.
1152 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1153 * @param[in,out] exts Extension instances to add to.
1154 *
1155 * @return LY_ERR values.
1156 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001157static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001158parse_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 +02001159{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001160 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001161 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001162 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001163 enum yang_keyword kw;
1164
1165 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001166 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001167 return LY_EVALID;
1168 }
1169
1170 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001171 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001172
Radek Krejci44ceedc2018-10-02 15:54:31 +02001173 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001174 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175 switch (kw) {
1176 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001177 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001178 break;
1179 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001180 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001181 break;
1182 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001183 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184 return LY_EVALID;
1185 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001186 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001187 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001188checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 /* mandatory substatements */
1190 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001191 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001192 return LY_EVALID;
1193 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001194 return ret;
1195}
1196
Michal Vaskoea5abea2018-09-18 13:10:54 +02001197/**
1198 * @brief Parse the revision-date statement.
1199 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001200 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001201 * @param[in,out] data Data to read from, always moved to currently handled character.
1202 * @param[in,out] rev Array to store the parsed value in.
1203 * @param[in,out] exts Extension instances to add to.
1204 *
1205 * @return LY_ERR values.
1206 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001207static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001208parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001209{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001210 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001211 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001212 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001213 enum yang_keyword kw;
1214
1215 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001216 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001217 return LY_EVALID;
1218 }
1219
1220 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001221 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001222
1223 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001224 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001225 free(buf);
1226 return LY_EVALID;
1227 }
1228
1229 /* store value and spend buf if allocated */
1230 strncpy(rev, word, word_len);
1231 free(buf);
1232
Radek Krejci6d6556c2018-11-08 09:37:45 +01001233 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001234 switch (kw) {
1235 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001236 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001237 break;
1238 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001239 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001240 return LY_EVALID;
1241 }
1242 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001243 return ret;
1244}
1245
Michal Vaskoea5abea2018-09-18 13:10:54 +02001246/**
1247 * @brief Parse the include statement.
1248 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001249 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001250 * @param[in,out] data Data to read from, always moved to currently handled character.
1251 * @param[in,out] includes Parsed includes to add to.
1252 *
1253 * @return LY_ERR values.
1254 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001255static LY_ERR
Radek Krejcid33273d2018-10-25 14:55:52 +02001256parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001257{
Radek Krejcid33273d2018-10-25 14:55:52 +02001258 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001259 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001260 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001261 enum yang_keyword kw;
1262 struct lysp_include *inc;
1263
Radek Krejcid33273d2018-10-25 14:55:52 +02001264 LY_ARRAY_NEW_RET(ctx->ctx, mod->includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001265
1266 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001267 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001268
Radek Krejci086c7132018-10-26 15:29:04 +02001269 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1270
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001271 /* submodules share the namespace with the module names, so there must not be
1272 * a module of the same name in the context, no need for revision matching */
1273 if (!strcmp(ctx->mod->name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
1274 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1275 return LY_EVALID;
1276 }
1277
Radek Krejci6d6556c2018-11-08 09:37:45 +01001278 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001279 switch (kw) {
1280 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001281 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 +02001282 break;
1283 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001284 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 +02001285 break;
1286 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001287 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001288 break;
1289 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001290 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001291 break;
1292 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001293 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001294 return LY_EVALID;
1295 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001296 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001297 return ret;
1298}
1299
Michal Vaskoea5abea2018-09-18 13:10:54 +02001300/**
1301 * @brief Parse the import statement.
1302 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001303 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001304 * @param[in,out] data Data to read from, always moved to currently handled character.
1305 * @param[in,out] imports Parsed imports to add to.
1306 *
1307 * @return LY_ERR values.
1308 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001309static LY_ERR
Radek Krejci70853c52018-10-15 14:46:16 +02001310parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *module)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001311{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001312 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001313 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001314 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001315 enum yang_keyword kw;
1316 struct lysp_import *imp;
1317
Radek Krejci2c4e7172018-10-19 15:56:26 +02001318 LY_ARRAY_NEW_RET(ctx->ctx, module->imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001319
1320 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001321 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001322 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001323
Radek Krejci6d6556c2018-11-08 09:37:45 +01001324 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001325 switch (kw) {
1326 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001327 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 +02001328 LY_CHECK_RET(lysp_check_prefix(ctx, module, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001329 break;
1330 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001331 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 +02001332 break;
1333 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001334 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 +02001335 break;
1336 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001337 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001338 break;
1339 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001340 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001341 break;
1342 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001343 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001344 return LY_EVALID;
1345 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001346 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001347 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001348checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001349 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001350 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001351
1352 return ret;
1353}
1354
Michal Vaskoea5abea2018-09-18 13:10:54 +02001355/**
1356 * @brief Parse the revision statement.
1357 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001358 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001359 * @param[in,out] data Data to read from, always moved to currently handled character.
1360 * @param[in,out] revs Parsed revisions to add to.
1361 *
1362 * @return LY_ERR values.
1363 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001364static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001365parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001366{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001367 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001368 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001369 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001370 enum yang_keyword kw;
1371 struct lysp_revision *rev;
1372
Radek Krejci2c4e7172018-10-19 15:56:26 +02001373 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001374
1375 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001376 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001377
1378 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001379 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001380 return LY_EVALID;
1381 }
1382
Radek Krejcib7db73a2018-10-24 14:18:40 +02001383 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001384 free(buf);
1385
Radek Krejci6d6556c2018-11-08 09:37:45 +01001386 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001387 switch (kw) {
1388 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001389 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 +02001390 break;
1391 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001392 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 +02001393 break;
1394 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001395 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001396 break;
1397 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001398 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001399 return LY_EVALID;
1400 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001401 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001402 return ret;
1403}
1404
Michal Vaskoea5abea2018-09-18 13:10:54 +02001405/**
1406 * @brief Parse a generic text field that can have more instances such as base.
1407 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001408 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001409 * @param[in,out] data Data to read from, always moved to currently handled character.
1410 * @param[in] substmt Type of this substatement.
1411 * @param[in,out] texts Parsed values to add to.
1412 * @param[in] arg Type of the expected argument.
1413 * @param[in,out] exts Extension instances to add to.
1414 *
1415 * @return LY_ERR values.
1416 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001417static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001418parse_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 +02001419 struct lysp_ext_instance **exts)
1420{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001421 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001422 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001423 const char **item;
1424 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001425 enum yang_keyword kw;
1426
1427 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001428 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001429
1430 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001431 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001432
Radek Krejci151a5b72018-10-19 14:21:44 +02001433 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001434 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001435 switch (kw) {
1436 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001437 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438 break;
1439 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001440 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001441 return LY_EVALID;
1442 }
1443 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001444 return ret;
1445}
1446
Michal Vaskoea5abea2018-09-18 13:10:54 +02001447/**
1448 * @brief Parse the config statement.
1449 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001450 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001451 * @param[in,out] data Data to read from, always moved to currently handled character.
1452 * @param[in,out] flags Flags to add to.
1453 * @param[in,out] exts Extension instances to add to.
1454 *
1455 * @return LY_ERR values.
1456 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001457static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001458parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001459{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001460 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001461 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001462 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001463 enum yang_keyword kw;
1464
1465 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001466 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001467 return LY_EVALID;
1468 }
1469
1470 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001471 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001472
1473 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1474 *flags |= LYS_CONFIG_W;
1475 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1476 *flags |= LYS_CONFIG_R;
1477 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001478 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001479 free(buf);
1480 return LY_EVALID;
1481 }
1482 free(buf);
1483
Radek Krejci6d6556c2018-11-08 09:37:45 +01001484 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001485 switch (kw) {
1486 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001487 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001488 break;
1489 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001490 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001491 return LY_EVALID;
1492 }
1493 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001494 return ret;
1495}
1496
Michal Vaskoea5abea2018-09-18 13:10:54 +02001497/**
1498 * @brief Parse the mandatory statement.
1499 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001500 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001501 * @param[in,out] data Data to read from, always moved to currently handled character.
1502 * @param[in,out] flags Flags to add to.
1503 * @param[in,out] exts Extension instances to add to.
1504 *
1505 * @return LY_ERR values.
1506 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001507static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001508parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001509{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001510 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001511 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001512 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001513 enum yang_keyword kw;
1514
1515 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001516 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001517 return LY_EVALID;
1518 }
1519
1520 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001521 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001522
1523 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1524 *flags |= LYS_MAND_TRUE;
1525 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1526 *flags |= LYS_MAND_FALSE;
1527 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001528 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001529 free(buf);
1530 return LY_EVALID;
1531 }
1532 free(buf);
1533
Radek Krejci6d6556c2018-11-08 09:37:45 +01001534 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001535 switch (kw) {
1536 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001537 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001538 break;
1539 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001540 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001541 return LY_EVALID;
1542 }
1543 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001544 return ret;
1545}
1546
Michal Vaskoea5abea2018-09-18 13:10:54 +02001547/**
1548 * @brief Parse a restriction such as range or length.
1549 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001550 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001551 * @param[in,out] data Data to read from, always moved to currently handled character.
1552 * @param[in] restr_kw Type of this particular restriction.
1553 * @param[in,out] exts Extension instances to add to.
1554 *
1555 * @return LY_ERR values.
1556 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001557static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001558parse_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 +02001559{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001560 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001561 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001562 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001563 enum yang_keyword kw;
1564
1565 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001566 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001567
Radek Krejci44ceedc2018-10-02 15:54:31 +02001568 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001569 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001570 switch (kw) {
1571 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001572 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 +02001573 break;
1574 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001575 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 +02001576 break;
1577 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001578 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 +02001579 break;
1580 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001581 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 +02001582 break;
1583 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001584 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001585 break;
1586 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001587 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001588 return LY_EVALID;
1589 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001590 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001591 return ret;
1592}
1593
Michal Vaskoea5abea2018-09-18 13:10:54 +02001594/**
1595 * @brief Parse a restriction that can have more instances such as must.
1596 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001597 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001598 * @param[in,out] data Data to read from, always moved to currently handled character.
1599 * @param[in] restr_kw Type of this particular restriction.
1600 * @param[in,out] restrs Restrictions to add to.
1601 *
1602 * @return LY_ERR values.
1603 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001604static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001605parse_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 +02001606{
1607 struct lysp_restr *restr;
1608
Radek Krejci2c4e7172018-10-19 15:56:26 +02001609 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001610 return parse_restr(ctx, data, restr_kw, restr);
1611}
1612
Michal Vaskoea5abea2018-09-18 13:10:54 +02001613/**
1614 * @brief Parse the status statement.
1615 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001616 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001617 * @param[in,out] data Data to read from, always moved to currently handled character.
1618 * @param[in,out] flags Flags to add to.
1619 * @param[in,out] exts Extension instances to add to.
1620 *
1621 * @return LY_ERR values.
1622 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001623static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001624parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001625{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001626 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001627 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001628 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001629 enum yang_keyword kw;
1630
1631 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001632 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001633 return LY_EVALID;
1634 }
1635
1636 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001637 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001638
1639 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1640 *flags |= LYS_STATUS_CURR;
1641 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1642 *flags |= LYS_STATUS_DEPRC;
1643 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1644 *flags |= LYS_STATUS_OBSLT;
1645 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001646 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001647 free(buf);
1648 return LY_EVALID;
1649 }
1650 free(buf);
1651
Radek Krejci6d6556c2018-11-08 09:37:45 +01001652 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001653 switch (kw) {
1654 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001655 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001656 break;
1657 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001658 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001659 return LY_EVALID;
1660 }
1661 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001662 return ret;
1663}
1664
Michal Vaskoea5abea2018-09-18 13:10:54 +02001665/**
1666 * @brief Parse the when statement.
1667 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001668 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001669 * @param[in,out] data Data to read from, always moved to currently handled character.
1670 * @param[in,out] when_p When pointer to parse to.
1671 *
1672 * @return LY_ERR values.
1673 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001674static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001675parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001676{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001677 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001678 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001679 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001680 enum yang_keyword kw;
1681 struct lysp_when *when;
1682
1683 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001684 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001685 return LY_EVALID;
1686 }
1687
1688 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001689 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001690 *when_p = when;
1691
1692 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001693 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001694 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001695
Radek Krejci6d6556c2018-11-08 09:37:45 +01001696 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001697 switch (kw) {
1698 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001699 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 +02001700 break;
1701 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001702 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 +02001703 break;
1704 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001705 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001706 break;
1707 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001708 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001709 return LY_EVALID;
1710 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001711 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001712 return ret;
1713}
1714
Michal Vaskoea5abea2018-09-18 13:10:54 +02001715/**
1716 * @brief Parse the anydata or anyxml statement.
1717 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001718 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001719 * @param[in,out] data Data to read from, always moved to currently handled character.
1720 * @param[in] kw Type of this particular keyword.
1721 * @param[in,out] siblings Siblings to add to.
1722 *
1723 * @return LY_ERR values.
1724 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001725static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001726parse_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 +02001727{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001728 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001729 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001730 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001731 struct lysp_node *iter;
1732 struct lysp_node_anydata *any;
1733
1734 /* create structure */
1735 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001736 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001737 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001738 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001739
1740 /* insert into siblings */
1741 if (!*siblings) {
1742 *siblings = (struct lysp_node *)any;
1743 } else {
1744 for (iter = *siblings; iter->next; iter = iter->next);
1745 iter->next = (struct lysp_node *)any;
1746 }
1747
1748 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001749 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001750 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001751
1752 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001753 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001754 switch (kw) {
1755 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001756 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001757 break;
1758 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001759 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 +02001760 break;
1761 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001762 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 +02001763 break;
1764 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001765 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001766 break;
1767 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001768 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001769 break;
1770 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001771 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 +02001772 break;
1773 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001774 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001775 break;
1776 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001777 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001778 break;
1779 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001780 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001781 break;
1782 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001783 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001784 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001785 return LY_EVALID;
1786 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001787 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001788 return ret;
1789}
1790
Michal Vaskoea5abea2018-09-18 13:10:54 +02001791/**
1792 * @brief Parse the value or position statement. Substatement of type enum statement.
1793 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001794 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001795 * @param[in,out] data Data to read from, always moved to currently handled character.
1796 * @param[in] val_kw Type of this particular keyword.
1797 * @param[in,out] value Value to write to.
1798 * @param[in,out] flags Flags to write to.
1799 * @param[in,out] exts Extension instances to add to.
1800 *
1801 * @return LY_ERR values.
1802 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001803static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001804parse_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 +02001805 struct lysp_ext_instance **exts)
1806{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001807 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001808 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001809 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001810 long int num;
1811 unsigned long int unum;
1812 enum yang_keyword kw;
1813
1814 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001815 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001816 return LY_EVALID;
1817 }
1818 *flags |= LYS_SET_VALUE;
1819
1820 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001821 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001822
1823 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 +02001824 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001825 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001826 }
1827
1828 errno = 0;
1829 if (val_kw == YANG_VALUE) {
1830 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001831 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
1832 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1833 goto error;
1834 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001835 } else {
1836 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001837 if (unum > UINT64_C(4294967295)) {
1838 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1839 goto error;
1840 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001841 }
1842 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001843 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001844 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001845 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001846 }
1847 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001848 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001849 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001850 }
1851 if (val_kw == YANG_VALUE) {
1852 *value = num;
1853 } else {
1854 *value = unum;
1855 }
1856 free(buf);
1857
Radek Krejci6d6556c2018-11-08 09:37:45 +01001858 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001859 switch (kw) {
1860 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001861 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 +02001862 break;
1863 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001864 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001865 return LY_EVALID;
1866 }
1867 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001868 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001869
1870error:
1871 free(buf);
1872 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001873}
1874
Michal Vaskoea5abea2018-09-18 13:10:54 +02001875/**
1876 * @brief Parse the enum or bit statement. Substatement of type statement.
1877 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001878 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001879 * @param[in,out] data Data to read from, always moved to currently handled character.
1880 * @param[in] enum_kw Type of this particular keyword.
1881 * @param[in,out] enums Enums or bits to add to.
1882 *
1883 * @return LY_ERR values.
1884 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001885static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001886parse_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 +02001887{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001888 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001889 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001890 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001891 enum yang_keyword kw;
1892 struct lysp_type_enum *enm;
1893
Radek Krejci2c4e7172018-10-19 15:56:26 +02001894 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001895
1896 /* get value */
Radek Krejci8b764662018-11-14 14:15:13 +01001897 LY_CHECK_RET(get_argument(ctx, data, enum_kw == YANG_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, &word, &buf, &word_len));
1898 if (enum_kw == YANG_ENUM) {
1899 if (!word_len) {
1900 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
1901 free(buf);
1902 return LY_EVALID;
1903 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
1904 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
1905 word_len, word);
1906 free(buf);
1907 return LY_EVALID;
1908 } else {
1909 for (u = 0; u < word_len; ++u) {
1910 if (iscntrl(word[u])) {
1911 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1912 word_len, word, u + 1);
1913 break;
1914 }
1915 }
1916 }
1917 } else { /* YANG_BIT */
1918
1919 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001920 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001921
Radek Krejci8b764662018-11-14 14:15:13 +01001922 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1923
Radek Krejci6d6556c2018-11-08 09:37:45 +01001924 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001925 switch (kw) {
1926 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001927 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 +02001928 break;
1929 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001930 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 +02001931 break;
1932 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001933 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 +02001934 break;
1935 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001936 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001937 break;
1938 case YANG_VALUE:
1939 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001940 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001941 break;
1942 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001943 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001944 break;
1945 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001946 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001947 return LY_EVALID;
1948 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001950 return ret;
1951}
1952
Michal Vaskoea5abea2018-09-18 13:10:54 +02001953/**
1954 * @brief Parse the fraction-digits statement. Substatement of type statement.
1955 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001956 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001957 * @param[in,out] data Data to read from, always moved to currently handled character.
1958 * @param[in,out] fracdig Value to write to.
1959 * @param[in,out] exts Extension instances to add to.
1960 *
1961 * @return LY_ERR values.
1962 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001963static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001964parse_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 +02001965{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001966 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001967 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001968 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001969 unsigned long int num;
1970 enum yang_keyword kw;
1971
1972 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001973 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001974 return LY_EVALID;
1975 }
1976
1977 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001978 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001979
1980 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001981 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001982 free(buf);
1983 return LY_EVALID;
1984 }
1985
1986 errno = 0;
1987 num = strtoul(word, &ptr, 10);
1988 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001989 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001990 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001991 free(buf);
1992 return LY_EVALID;
1993 }
1994 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001995 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001996 free(buf);
1997 return LY_EVALID;
1998 }
1999 *fracdig = num;
2000 free(buf);
2001
Radek Krejci6d6556c2018-11-08 09:37:45 +01002002 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002003 switch (kw) {
2004 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002005 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002006 break;
2007 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002008 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002009 return LY_EVALID;
2010 }
2011 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002012 return ret;
2013}
2014
Michal Vaskoea5abea2018-09-18 13:10:54 +02002015/**
2016 * @brief Parse the require-instance statement. Substatement of type statement.
2017 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002018 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002019 * @param[in,out] data Data to read from, always moved to currently handled character.
2020 * @param[in,out] reqinst Value to write to.
2021 * @param[in,out] flags Flags to write to.
2022 * @param[in,out] exts Extension instances to add to.
2023 *
2024 * @return LY_ERR values.
2025 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002026static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002027parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002028 struct lysp_ext_instance **exts)
2029{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002030 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002031 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002032 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002033 enum yang_keyword kw;
2034
2035 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002036 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002037 return LY_EVALID;
2038 }
2039 *flags |= LYS_SET_REQINST;
2040
2041 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002042 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002043
2044 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2045 *reqinst = 1;
2046 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002047 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002048 free(buf);
2049 return LY_EVALID;
2050 }
2051 free(buf);
2052
Radek Krejci6d6556c2018-11-08 09:37:45 +01002053 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002054 switch (kw) {
2055 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002056 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002057 break;
2058 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002059 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002060 return LY_EVALID;
2061 }
2062 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002063 return ret;
2064}
2065
Michal Vaskoea5abea2018-09-18 13:10:54 +02002066/**
2067 * @brief Parse the modifier statement. Substatement of type pattern statement.
2068 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002069 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002070 * @param[in,out] data Data to read from, always moved to currently handled character.
2071 * @param[in,out] pat Value to write to.
2072 * @param[in,out] exts Extension instances to add to.
2073 *
2074 * @return LY_ERR values.
2075 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002076static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002077parse_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 +02002078{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002079 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002080 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002081 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002082 enum yang_keyword kw;
2083
2084 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002085 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002086 return LY_EVALID;
2087 }
2088
2089 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002090 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002091
2092 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002093 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002094 free(buf);
2095 return LY_EVALID;
2096 }
2097 free(buf);
2098
2099 /* replace the value in the dictionary */
2100 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002101 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002102 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002103 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002104
2105 assert(buf[0] == 0x06);
2106 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002107 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002108
Radek Krejci6d6556c2018-11-08 09:37:45 +01002109 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002110 switch (kw) {
2111 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002112 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002113 break;
2114 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002115 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002116 return LY_EVALID;
2117 }
2118 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002119 return ret;
2120}
2121
Michal Vaskoea5abea2018-09-18 13:10:54 +02002122/**
2123 * @brief Parse the pattern statement. Substatement of type statement.
2124 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002125 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002126 * @param[in,out] data Data to read from, always moved to currently handled character.
2127 * @param[in,out] patterns Restrictions to add to.
2128 *
2129 * @return LY_ERR values.
2130 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002131static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002132parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002133{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002134 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002135 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002136 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002137 enum yang_keyword kw;
2138 struct lysp_restr *restr;
2139
Radek Krejci2c4e7172018-10-19 15:56:26 +02002140 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002141
2142 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002143 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002144
2145 /* add special meaning first byte */
2146 if (buf) {
2147 buf = realloc(buf, word_len + 2);
2148 word = buf;
2149 } else {
2150 buf = malloc(word_len + 2);
2151 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002152 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002153 memmove(buf + 1, word, word_len);
2154 buf[0] = 0x06; /* pattern's default regular-match flag */
2155 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2156 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002157
Radek Krejci6d6556c2018-11-08 09:37:45 +01002158 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002159 switch (kw) {
2160 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002161 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 +02002162 break;
2163 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002164 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 +02002165 break;
2166 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002167 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 +02002168 break;
2169 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002170 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 +02002171 break;
2172 case YANG_MODIFIER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002173 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002174 break;
2175 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002176 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002177 break;
2178 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002179 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002180 return LY_EVALID;
2181 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002182 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002183 return ret;
2184}
2185
Michal Vaskoea5abea2018-09-18 13:10:54 +02002186/**
2187 * @brief Parse the type statement.
2188 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002189 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002190 * @param[in,out] data Data to read from, always moved to currently handled character.
2191 * @param[in,out] type Type to wrote to.
2192 *
2193 * @return LY_ERR values.
2194 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002195static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002196parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002197{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002198 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002199 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002200 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002201 enum yang_keyword kw;
2202 struct lysp_type *nest_type;
2203
2204 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002205 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002206 return LY_EVALID;
2207 }
2208
2209 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002210 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002211 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002212
Radek Krejci6d6556c2018-11-08 09:37:45 +01002213 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002214 switch (kw) {
2215 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002216 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 +01002217 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002218 break;
2219 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002220 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002221 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002222 break;
2223 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002224 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002225 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002226 break;
2227 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002228 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002229 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002230 break;
2231 case YANG_LENGTH:
2232 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002233 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002234 return LY_EVALID;
2235 }
2236 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002237 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002238
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002239 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002240 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002241 break;
2242 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002243 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 +01002244 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002245 break;
2246 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002247 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002248 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002249 break;
2250 case YANG_RANGE:
2251 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002252 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002253 return LY_EVALID;
2254 }
2255 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002256 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002257
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002258 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002259 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002260 break;
2261 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002262 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002263 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002264 break;
2265 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002266 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2267 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002268 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002269 break;
2270 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002271 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002272 break;
2273 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002274 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002275 return LY_EVALID;
2276 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002277 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002278 return ret;
2279}
2280
Michal Vaskoea5abea2018-09-18 13:10:54 +02002281/**
2282 * @brief Parse the leaf statement.
2283 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002284 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002285 * @param[in,out] data Data to read from, always moved to currently handled character.
2286 * @param[in,out] siblings Siblings to add to.
2287 *
2288 * @return LY_ERR values.
2289 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002290static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002291parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002292{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002293 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002294 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002295 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002296 enum yang_keyword kw;
2297 struct lysp_node *iter;
2298 struct lysp_node_leaf *leaf;
2299
2300 /* create structure */
2301 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002302 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002303 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002304 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002305
2306 /* insert into siblings */
2307 if (!*siblings) {
2308 *siblings = (struct lysp_node *)leaf;
2309 } else {
2310 for (iter = *siblings; iter->next; iter = iter->next);
2311 iter->next = (struct lysp_node *)leaf;
2312 }
2313
2314 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002315 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002316 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002317
2318 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002319 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002320 switch (kw) {
2321 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002322 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002323 break;
2324 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002325 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 +02002326 break;
2327 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002328 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 +02002329 break;
2330 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002331 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 +02002332 break;
2333 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002334 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002335 break;
2336 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002337 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002338 break;
2339 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002340 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 +02002341 break;
2342 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002343 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002344 break;
2345 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002346 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002347 break;
2348 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002349 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 +02002350 break;
2351 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002352 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002353 break;
2354 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002355 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002356 break;
2357 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002358 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002359 return LY_EVALID;
2360 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002361 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002362 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002363checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002364 /* mandatory substatements */
2365 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002366 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002367 return LY_EVALID;
2368 }
2369
2370 return ret;
2371}
2372
Michal Vaskoea5abea2018-09-18 13:10:54 +02002373/**
2374 * @brief Parse the max-elements statement.
2375 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002376 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002377 * @param[in,out] data Data to read from, always moved to currently handled character.
2378 * @param[in,out] max Value to write to.
2379 * @param[in,out] flags Flags to write to.
2380 * @param[in,out] exts Extension instances to add to.
2381 *
2382 * @return LY_ERR values.
2383 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002384static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002385parse_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 +02002386{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002387 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002388 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002389 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002390 unsigned long int num;
2391 enum yang_keyword kw;
2392
2393 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002394 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002395 return LY_EVALID;
2396 }
2397 *flags |= LYS_SET_MAX;
2398
2399 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002400 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002401
2402 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002403 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002404 free(buf);
2405 return LY_EVALID;
2406 }
2407
2408 if (strncmp(word, "unbounded", word_len)) {
2409 errno = 0;
2410 num = strtoul(word, &ptr, 10);
2411 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002412 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002413 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002414 free(buf);
2415 return LY_EVALID;
2416 }
2417 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002418 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002419 free(buf);
2420 return LY_EVALID;
2421 }
2422
2423 *max = num;
2424 }
2425 free(buf);
2426
Radek Krejci6d6556c2018-11-08 09:37:45 +01002427 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002428 switch (kw) {
2429 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002430 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002431 break;
2432 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002433 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002434 return LY_EVALID;
2435 }
2436 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002437 return ret;
2438}
2439
Michal Vaskoea5abea2018-09-18 13:10:54 +02002440/**
2441 * @brief Parse the min-elements statement.
2442 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002443 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002444 * @param[in,out] data Data to read from, always moved to currently handled character.
2445 * @param[in,out] min Value to write to.
2446 * @param[in,out] flags Flags to write to.
2447 * @param[in,out] exts Extension instances to add to.
2448 *
2449 * @return LY_ERR values.
2450 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002451static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002452parse_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 +02002453{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002454 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002455 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002456 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002457 unsigned long int num;
2458 enum yang_keyword kw;
2459
2460 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002461 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002462 return LY_EVALID;
2463 }
2464 *flags |= LYS_SET_MIN;
2465
2466 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002467 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002468
2469 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002470 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002471 free(buf);
2472 return LY_EVALID;
2473 }
2474
2475 errno = 0;
2476 num = strtoul(word, &ptr, 10);
2477 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002478 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002479 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002480 free(buf);
2481 return LY_EVALID;
2482 }
2483 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002484 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485 free(buf);
2486 return LY_EVALID;
2487 }
2488 *min = num;
2489 free(buf);
2490
Radek Krejci6d6556c2018-11-08 09:37:45 +01002491 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002492 switch (kw) {
2493 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002494 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002495 break;
2496 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002497 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002498 return LY_EVALID;
2499 }
2500 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002501 return ret;
2502}
2503
Michal Vaskoea5abea2018-09-18 13:10:54 +02002504/**
2505 * @brief Parse the ordered-by statement.
2506 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002507 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002508 * @param[in,out] data Data to read from, always moved to currently handled character.
2509 * @param[in,out] flags Flags to write to.
2510 * @param[in,out] exts Extension instances to add to.
2511 *
2512 * @return LY_ERR values.
2513 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002514static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002515parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002516{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002517 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002518 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002519 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002520 enum yang_keyword kw;
2521
2522 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002523 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002524 return LY_EVALID;
2525 }
2526
2527 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002528 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002529
2530 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2531 *flags |= LYS_ORDBY_SYSTEM;
2532 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2533 *flags |= LYS_ORDBY_USER;
2534 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002535 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002536 free(buf);
2537 return LY_EVALID;
2538 }
2539 free(buf);
2540
Radek Krejci6d6556c2018-11-08 09:37:45 +01002541 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002542 switch (kw) {
2543 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002544 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002545 break;
2546 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002547 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002548 return LY_EVALID;
2549 }
2550 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002551 return ret;
2552}
2553
Michal Vaskoea5abea2018-09-18 13:10:54 +02002554/**
2555 * @brief Parse the leaf-list statement.
2556 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002557 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002558 * @param[in,out] data Data to read from, always moved to currently handled character.
2559 * @param[in,out] siblings Siblings to add to.
2560 *
2561 * @return LY_ERR values.
2562 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002563static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002564parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002565{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002566 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002567 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002568 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002569 enum yang_keyword kw;
2570 struct lysp_node *iter;
2571 struct lysp_node_leaflist *llist;
2572
2573 /* create structure */
2574 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002575 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002576 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002577 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002578
2579 /* insert into siblings */
2580 if (!*siblings) {
2581 *siblings = (struct lysp_node *)llist;
2582 } else {
2583 for (iter = *siblings; iter->next; iter = iter->next);
2584 iter->next = (struct lysp_node *)llist;
2585 }
2586
2587 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002588 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002589 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002590
2591 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002592 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002593 switch (kw) {
2594 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002595 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002596 break;
2597 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002598 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 +02002599 break;
2600 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002601 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 +02002602 break;
2603 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002604 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 +02002605 break;
2606 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002607 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002608 break;
2609 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002610 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002611 break;
2612 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002613 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002614 break;
2615 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002616 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002617 break;
2618 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002619 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 +02002620 break;
2621 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002622 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002623 break;
2624 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002625 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002626 break;
2627 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002628 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 +02002629 break;
2630 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002631 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002632 break;
2633 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002634 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002635 break;
2636 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002637 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002638 return LY_EVALID;
2639 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002640 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002641 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002642checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002643 /* mandatory substatements */
2644 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002645 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002646 return LY_EVALID;
2647 }
2648
2649 return ret;
2650}
2651
Michal Vaskoea5abea2018-09-18 13:10:54 +02002652/**
2653 * @brief Parse the refine statement.
2654 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002655 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002656 * @param[in,out] data Data to read from, always moved to currently handled character.
2657 * @param[in,out] refines Refines to add to.
2658 *
2659 * @return LY_ERR values.
2660 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002661static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002662parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002663{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002664 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002665 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002666 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002667 enum yang_keyword kw;
2668 struct lysp_refine *rf;
2669
Radek Krejci2c4e7172018-10-19 15:56:26 +02002670 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671
2672 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002673 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002674 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002675
Radek Krejci6d6556c2018-11-08 09:37:45 +01002676 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002677 switch (kw) {
2678 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002679 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002680 break;
2681 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002682 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 +02002683 break;
2684 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002685 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 +02002686 break;
2687 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002688 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 +02002689 break;
2690 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002691 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002692 break;
2693 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002694 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695 break;
2696 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002697 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002698 break;
2699 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002700 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002701 break;
2702 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002703 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 +02002704 break;
2705 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002706 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 +02002707 break;
2708 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002709 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002710 break;
2711 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002712 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002713 return LY_EVALID;
2714 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002715 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002716 return ret;
2717}
2718
Michal Vaskoea5abea2018-09-18 13:10:54 +02002719/**
2720 * @brief Parse the typedef statement.
2721 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002722 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002723 * @param[in,out] data Data to read from, always moved to currently handled character.
2724 * @param[in,out] typedefs Typedefs to add to.
2725 *
2726 * @return LY_ERR values.
2727 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002728static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002729parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002730{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002731 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002732 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002733 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002734 enum yang_keyword kw;
2735 struct lysp_tpdf *tpdf;
2736
Radek Krejci2c4e7172018-10-19 15:56:26 +02002737 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002738
2739 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002740 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002741 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002742
2743 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002744 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002745 switch (kw) {
2746 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002747 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 +02002748 break;
2749 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002750 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 +02002751 break;
2752 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002753 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 +02002754 break;
2755 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002756 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002757 break;
2758 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002759 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002760 break;
2761 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002762 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 +02002763 break;
2764 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002765 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002766 break;
2767 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002768 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002769 return LY_EVALID;
2770 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002771 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002772 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002773checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002774 /* mandatory substatements */
2775 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002776 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002777 return LY_EVALID;
2778 }
2779
Radek Krejcibbe09a92018-11-08 09:36:54 +01002780 /* store data for collision check */
2781 if (parent) {
2782 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2783 }
2784
Michal Vasko7fbc8162018-09-17 10:35:16 +02002785 return ret;
2786}
2787
Michal Vaskoea5abea2018-09-18 13:10:54 +02002788/**
2789 * @brief Parse the input or output statement.
2790 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002791 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002792 * @param[in,out] data Data to read from, always moved to currently handled character.
2793 * @param[in] kw Type of this particular keyword
2794 * @param[in,out] inout_p Input/output pointer to write to.
2795 *
2796 * @return LY_ERR values.
2797 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002798static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002799parse_inout(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node *parent, struct lysp_action_inout **inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002800{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002801 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002802 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002803 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002804 struct lysp_action_inout *inout;
2805
2806 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002807 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002808 return LY_EVALID;
2809 }
2810
2811 /* create structure */
2812 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002813 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002814 *inout_p = inout;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002815 inout->nodetype = LYS_INOUT;
2816 inout->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002817
2818 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002819 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002820 switch (kw) {
2821 case YANG_ANYDATA:
2822 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002823 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002824 break;
2825 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002826 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002827 break;
2828 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002829 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002830 break;
2831 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002832 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002833 break;
2834 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002835 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002836 break;
2837 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002838 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002839 break;
2840 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002841 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002842 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002843 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002844 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout, data, &inout->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002845 break;
2846 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002847 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002848 break;
2849 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002850 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout, &inout->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002851 break;
2852 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002853 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002854 break;
2855 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002856 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 return LY_EVALID;
2858 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002859 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 return ret;
2861}
2862
Michal Vaskoea5abea2018-09-18 13:10:54 +02002863/**
2864 * @brief Parse the action statement.
2865 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002866 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002867 * @param[in,out] data Data to read from, always moved to currently handled character.
2868 * @param[in,out] actions Actions to add to.
2869 *
2870 * @return LY_ERR values.
2871 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002872static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002873parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002874{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002875 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002876 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002877 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002878 enum yang_keyword kw;
2879 struct lysp_action *act;
2880
Radek Krejci2c4e7172018-10-19 15:56:26 +02002881 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002882
2883 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002884 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002885 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002886 act->nodetype = LYS_ACTION;
2887 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002888
Radek Krejci6d6556c2018-11-08 09:37:45 +01002889 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002890 switch (kw) {
2891 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002892 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 +02002893 break;
2894 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002895 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 +02002896 break;
2897 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002898 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 +02002899 break;
2900 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002901 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002902 break;
2903
2904 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002905 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002906 break;
2907 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002908 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002909 break;
2910
2911 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002912 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002913 break;
2914 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002915 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002916 break;
2917 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002918 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002919 break;
2920 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002921 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002922 return LY_EVALID;
2923 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002924 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002925 return ret;
2926}
2927
Michal Vaskoea5abea2018-09-18 13:10:54 +02002928/**
2929 * @brief Parse the notification statement.
2930 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002931 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002932 * @param[in,out] data Data to read from, always moved to currently handled character.
2933 * @param[in,out] notifs Notifications to add to.
2934 *
2935 * @return LY_ERR values.
2936 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002937static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002938parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002939{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002940 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002941 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002942 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002943 enum yang_keyword kw;
2944 struct lysp_notif *notif;
2945
Radek Krejci2c4e7172018-10-19 15:56:26 +02002946 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002947
2948 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002949 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002950 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002951 notif->nodetype = LYS_NOTIF;
2952 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002953
Radek Krejci6d6556c2018-11-08 09:37:45 +01002954 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002955 switch (kw) {
2956 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002957 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 +02002958 break;
2959 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002960 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 +02002961 break;
2962 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002963 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 +02002964 break;
2965 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002966 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002967 break;
2968
2969 case YANG_ANYDATA:
2970 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002971 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002972 break;
2973 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002974 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975 break;
2976 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002977 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978 break;
2979 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002980 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002981 break;
2982 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002983 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002984 break;
2985 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002986 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002987 break;
2988 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002989 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002990 break;
2991
2992 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002993 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002994 break;
2995 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002996 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002997 break;
2998 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002999 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003000 break;
3001 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003002 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003003 break;
3004 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003005 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003006 return LY_EVALID;
3007 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003008 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003009 return ret;
3010}
3011
Michal Vaskoea5abea2018-09-18 13:10:54 +02003012/**
3013 * @brief Parse the grouping statement.
3014 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003015 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003016 * @param[in,out] data Data to read from, always moved to currently handled character.
3017 * @param[in,out] groupings Groupings to add to.
3018 *
3019 * @return LY_ERR values.
3020 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003021static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003022parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003023{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003024 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003025 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003026 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003027 enum yang_keyword kw;
3028 struct lysp_grp *grp;
3029
Radek Krejci2c4e7172018-10-19 15:56:26 +02003030 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003031
3032 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003033 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003034 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003035 grp->nodetype = LYS_GROUPING;
3036 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003037
Radek Krejci6d6556c2018-11-08 09:37:45 +01003038 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003039 switch (kw) {
3040 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003041 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 +02003042 break;
3043 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003044 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 +02003045 break;
3046 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003047 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003048 break;
3049
3050 case YANG_ANYDATA:
3051 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003052 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003053 break;
3054 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003055 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003056 break;
3057 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003058 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003059 break;
3060 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003061 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003062 break;
3063 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003064 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003065 break;
3066 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003067 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003068 break;
3069 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003070 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071 break;
3072
3073 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003074 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003075 break;
3076 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003077 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003078 break;
3079 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003080 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003081 break;
3082 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003083 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003084 break;
3085 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003086 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003087 break;
3088 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003089 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003090 return LY_EVALID;
3091 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003092 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003093 return ret;
3094}
3095
Michal Vaskoea5abea2018-09-18 13:10:54 +02003096/**
3097 * @brief Parse the refine statement.
3098 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003099 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003100 * @param[in,out] data Data to read from, always moved to currently handled character.
3101 * @param[in,out] augments Augments to add to.
3102 *
3103 * @return LY_ERR values.
3104 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003105static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003106parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003107{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003108 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003109 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003110 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003111 enum yang_keyword kw;
3112 struct lysp_augment *aug;
3113
Radek Krejci2c4e7172018-10-19 15:56:26 +02003114 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003115
3116 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003117 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003118 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003119 aug->nodetype = LYS_AUGMENT;
3120 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003121
Radek Krejci6d6556c2018-11-08 09:37:45 +01003122 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003123 switch (kw) {
3124 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003125 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 +02003126 break;
3127 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003128 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 +02003129 break;
3130 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003131 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 +02003132 break;
3133 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003134 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 break;
3136 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003137 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003138 break;
3139
3140 case YANG_ANYDATA:
3141 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003142 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003143 break;
3144 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003145 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003146 break;
3147 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003148 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003149 break;
3150 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003151 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003152 break;
3153 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003154 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003155 break;
3156 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003157 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003158 break;
3159 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003160 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003161 break;
3162 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003163 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003164 break;
3165
3166 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003167 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003168 break;
3169 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003170 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003171 break;
3172 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003174 break;
3175 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003176 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003177 return LY_EVALID;
3178 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003179 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003180 return ret;
3181}
3182
Michal Vaskoea5abea2018-09-18 13:10:54 +02003183/**
3184 * @brief Parse the uses statement.
3185 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003186 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003187 * @param[in,out] data Data to read from, always moved to currently handled character.
3188 * @param[in,out] siblings Siblings to add to.
3189 *
3190 * @return LY_ERR values.
3191 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003192static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003193parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003194{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003195 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003196 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003197 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003198 enum yang_keyword kw;
3199 struct lysp_node *iter;
3200 struct lysp_node_uses *uses;
3201
3202 /* create structure */
3203 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003204 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003205 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003206 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003207
3208 /* insert into siblings */
3209 if (!*siblings) {
3210 *siblings = (struct lysp_node *)uses;
3211 } else {
3212 for (iter = *siblings; iter->next; iter = iter->next);
3213 iter->next = (struct lysp_node *)uses;
3214 }
3215
3216 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003217 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003218 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003219
3220 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003221 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003222 switch (kw) {
3223 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003224 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 +02003225 break;
3226 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003227 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 +02003228 break;
3229 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003230 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 +02003231 break;
3232 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003233 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003234 break;
3235 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003236 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003237 break;
3238
3239 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003240 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003241 break;
3242 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003243 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003244 break;
3245 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003246 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003247 break;
3248 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003249 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003250 return LY_EVALID;
3251 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003252 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003253 return ret;
3254}
3255
Michal Vaskoea5abea2018-09-18 13:10:54 +02003256/**
3257 * @brief Parse the case statement.
3258 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003259 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003260 * @param[in,out] data Data to read from, always moved to currently handled character.
3261 * @param[in,out] siblings Siblings to add to.
3262 *
3263 * @return LY_ERR values.
3264 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003265static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003266parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003267{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003268 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003269 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003270 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003271 enum yang_keyword kw;
3272 struct lysp_node *iter;
3273 struct lysp_node_case *cas;
3274
3275 /* create structure */
3276 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003277 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003278 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003279 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003280
3281 /* insert into siblings */
3282 if (!*siblings) {
3283 *siblings = (struct lysp_node *)cas;
3284 } else {
3285 for (iter = *siblings; iter->next; iter = iter->next);
3286 iter->next = (struct lysp_node *)cas;
3287 }
3288
3289 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003290 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003291 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003292
3293 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003294 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003295 switch (kw) {
3296 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003297 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 +02003298 break;
3299 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003300 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 +02003301 break;
3302 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003303 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 +02003304 break;
3305 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003306 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003307 break;
3308 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003309 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003310 break;
3311
3312 case YANG_ANYDATA:
3313 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003314 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003315 break;
3316 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003317 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003318 break;
3319 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003320 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003321 break;
3322 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003323 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003324 break;
3325 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003326 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003327 break;
3328 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003329 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003330 break;
3331 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003332 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003333 break;
3334 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003335 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003336 break;
3337 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003338 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003339 return LY_EVALID;
3340 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003341 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003342 return ret;
3343}
3344
Michal Vaskoea5abea2018-09-18 13:10:54 +02003345/**
3346 * @brief Parse the choice statement.
3347 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003348 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003349 * @param[in,out] data Data to read from, always moved to currently handled character.
3350 * @param[in,out] siblings Siblings to add to.
3351 *
3352 * @return LY_ERR values.
3353 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003354static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003355parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003356{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003357 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003358 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003359 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003360 enum yang_keyword kw;
3361 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003362 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003363
3364 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003365 choice = calloc(1, sizeof *choice);
3366 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3367 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003368 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003369
3370 /* insert into siblings */
3371 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003372 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373 } else {
3374 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003375 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003376 }
3377
3378 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003379 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003380 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003381
3382 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003383 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003384 switch (kw) {
3385 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003386 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003387 break;
3388 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003389 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 +02003390 break;
3391 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003392 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 +02003393 break;
3394 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003395 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003396 break;
3397 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003398 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 +02003399 break;
3400 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003401 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003402 break;
3403 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003404 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003405 break;
3406 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003407 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 +02003408 break;
3409
3410 case YANG_ANYDATA:
3411 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003412 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003413 break;
3414 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003415 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003416 break;
3417 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003418 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003419 break;
3420 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003421 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422 break;
3423 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003424 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003425 break;
3426 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003427 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003428 break;
3429 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003430 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003431 break;
3432 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003433 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003434 break;
3435 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003436 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003437 return LY_EVALID;
3438 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003439 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003440 return ret;
3441}
3442
Michal Vaskoea5abea2018-09-18 13:10:54 +02003443/**
3444 * @brief Parse the container statement.
3445 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003446 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003447 * @param[in,out] data Data to read from, always moved to currently handled character.
3448 * @param[in,out] siblings Siblings to add to.
3449 *
3450 * @return LY_ERR values.
3451 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003452static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003453parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003454{
3455 LY_ERR ret = 0;
3456 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003457 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003458 enum yang_keyword kw;
3459 struct lysp_node *iter;
3460 struct lysp_node_container *cont;
3461
3462 /* create structure */
3463 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003464 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003465 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003466 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003467
3468 /* insert into siblings */
3469 if (!*siblings) {
3470 *siblings = (struct lysp_node *)cont;
3471 } else {
3472 for (iter = *siblings; iter->next; iter = iter->next);
3473 iter->next = (struct lysp_node *)cont;
3474 }
3475
3476 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003477 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003478 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003479
3480 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003481 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003482 switch (kw) {
3483 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003484 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003485 break;
3486 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003487 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 +02003488 break;
3489 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003490 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 +02003491 break;
3492 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003493 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 +02003494 break;
3495 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003496 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003497 break;
3498 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003499 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003500 break;
3501 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003502 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 +02003503 break;
3504
3505 case YANG_ANYDATA:
3506 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003507 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003508 break;
3509 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003510 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003511 break;
3512 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003513 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003514 break;
3515 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003516 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003517 break;
3518 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003519 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003520 break;
3521 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003522 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003523 break;
3524 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003525 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003526 break;
3527
3528 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003529 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530 break;
3531 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003532 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003533 break;
3534 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003535 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536 break;
3537 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003538 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003539 break;
3540 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003541 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003542 break;
3543 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003544 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003545 break;
3546 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003547 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003548 return LY_EVALID;
3549 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003550 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003551 return ret;
3552}
3553
Michal Vaskoea5abea2018-09-18 13:10:54 +02003554/**
3555 * @brief Parse the list statement.
3556 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003557 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003558 * @param[in,out] data Data to read from, always moved to currently handled character.
3559 * @param[in,out] siblings Siblings to add to.
3560 *
3561 * @return LY_ERR values.
3562 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003564parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003565{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003566 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003568 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569 enum yang_keyword kw;
3570 struct lysp_node *iter;
3571 struct lysp_node_list *list;
3572
3573 /* create structure */
3574 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003575 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003576 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003577 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578
3579 /* insert into siblings */
3580 if (!*siblings) {
3581 *siblings = (struct lysp_node *)list;
3582 } else {
3583 for (iter = *siblings; iter->next; iter = iter->next);
3584 iter->next = (struct lysp_node *)list;
3585 }
3586
3587 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003588 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003589 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590
3591 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003592 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003593 switch (kw) {
3594 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003595 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003596 break;
3597 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003598 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 +02003599 break;
3600 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003601 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 +02003602 break;
3603 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003604 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 +02003605 break;
3606 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003607 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003608 break;
3609 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003610 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003611 break;
3612 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003613 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 +02003614 break;
3615 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003616 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003617 break;
3618 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003619 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003620 break;
3621 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003622 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003623 break;
3624 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003625 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 +02003626 break;
3627
3628 case YANG_ANYDATA:
3629 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003630 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003631 break;
3632 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003633 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003634 break;
3635 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003636 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003637 break;
3638 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003639 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003640 break;
3641 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003642 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643 break;
3644 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003645 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003646 break;
3647 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003648 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003649 break;
3650
3651 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003652 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003653 break;
3654 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003655 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003656 break;
3657 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003658 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003659 break;
3660 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003661 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003662 break;
3663 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003664 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003665 break;
3666 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003667 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003668 break;
3669 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003670 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003671 return LY_EVALID;
3672 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003673 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003674
3675 return ret;
3676}
3677
Michal Vaskoea5abea2018-09-18 13:10:54 +02003678/**
3679 * @brief Parse the yin-element statement.
3680 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003681 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003682 * @param[in,out] data Data to read from, always moved to currently handled character.
3683 * @param[in,out] flags Flags to write to.
3684 * @param[in,out] exts Extension instances to add to.
3685 *
3686 * @return LY_ERR values.
3687 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003688static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003689parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003690{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003691 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003692 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003693 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003694 enum yang_keyword kw;
3695
3696 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003697 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003698 return LY_EVALID;
3699 }
3700
3701 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003702 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003703
3704 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3705 *flags |= LYS_YINELEM_TRUE;
3706 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3707 *flags |= LYS_YINELEM_FALSE;
3708 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003709 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003710 free(buf);
3711 return LY_EVALID;
3712 }
3713 free(buf);
3714
Radek Krejci6d6556c2018-11-08 09:37:45 +01003715 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003716 switch (kw) {
3717 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003718 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3719 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003720 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003721 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003722 return LY_EVALID;
3723 }
3724 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725 return ret;
3726}
3727
Michal Vaskoea5abea2018-09-18 13:10:54 +02003728/**
3729 * @brief Parse the yin-element statement.
3730 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003731 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003732 * @param[in,out] data Data to read from, always moved to currently handled character.
3733 * @param[in,out] argument Value to write to.
3734 * @param[in,out] flags Flags to write to.
3735 * @param[in,out] exts Extension instances to add to.
3736 *
3737 * @return LY_ERR values.
3738 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003739static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003740parse_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 +02003741{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003742 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003743 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003744 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003745 enum yang_keyword kw;
3746
3747 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003748 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003749 return LY_EVALID;
3750 }
3751
3752 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003753 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003754 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003755
Radek Krejci6d6556c2018-11-08 09:37:45 +01003756 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003757 switch (kw) {
3758 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003759 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003760 break;
3761 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003762 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003763 break;
3764 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003765 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003766 return LY_EVALID;
3767 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003768 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003769 return ret;
3770}
3771
Michal Vaskoea5abea2018-09-18 13:10:54 +02003772/**
3773 * @brief Parse the extension statement.
3774 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003775 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003776 * @param[in,out] data Data to read from, always moved to currently handled character.
3777 * @param[in,out] extensions Extensions to add to.
3778 *
3779 * @return LY_ERR values.
3780 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003781static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003782parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003783{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003784 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003785 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003786 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003787 enum yang_keyword kw;
3788 struct lysp_ext *ex;
3789
Radek Krejci2c4e7172018-10-19 15:56:26 +02003790 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003791
3792 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003793 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003794 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003795
Radek Krejci6d6556c2018-11-08 09:37:45 +01003796 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003797 switch (kw) {
3798 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003799 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 +02003800 break;
3801 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003802 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 +02003803 break;
3804 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003805 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003806 break;
3807 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003808 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003809 break;
3810 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003811 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003812 break;
3813 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003814 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003815 return LY_EVALID;
3816 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003817 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003818 return ret;
3819}
3820
Michal Vaskoea5abea2018-09-18 13:10:54 +02003821/**
3822 * @brief Parse the deviate statement.
3823 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003824 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003825 * @param[in,out] data Data to read from, always moved to currently handled character.
3826 * @param[in,out] deviates Deviates to add to.
3827 *
3828 * @return LY_ERR values.
3829 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003830static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003831parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003832{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003833 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003834 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003835 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003836 enum yang_keyword kw;
3837 struct lysp_deviate *iter, *d;
3838 struct lysp_deviate_add *d_add = NULL;
3839 struct lysp_deviate_rpl *d_rpl = NULL;
3840 struct lysp_deviate_del *d_del = NULL;
3841 const char **d_units, ***d_uniques, ***d_dflts;
3842 struct lysp_restr **d_musts;
3843 uint16_t *d_flags;
3844 uint32_t *d_min, *d_max;
3845
3846 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003847 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003848
3849 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3850 dev_mod = LYS_DEV_NOT_SUPPORTED;
3851 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3852 dev_mod = LYS_DEV_ADD;
3853 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3854 dev_mod = LYS_DEV_REPLACE;
3855 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3856 dev_mod = LYS_DEV_DELETE;
3857 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003858 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003859 free(buf);
3860 return LY_EVALID;
3861 }
3862 free(buf);
3863
3864 /* create structure */
3865 switch (dev_mod) {
3866 case LYS_DEV_NOT_SUPPORTED:
3867 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003868 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003869 break;
3870 case LYS_DEV_ADD:
3871 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003872 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003873 d = (struct lysp_deviate *)d_add;
3874 d_units = &d_add->units;
3875 d_uniques = &d_add->uniques;
3876 d_dflts = &d_add->dflts;
3877 d_musts = &d_add->musts;
3878 d_flags = &d_add->flags;
3879 d_min = &d_add->min;
3880 d_max = &d_add->max;
3881 break;
3882 case LYS_DEV_REPLACE:
3883 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003884 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003885 d = (struct lysp_deviate *)d_rpl;
3886 d_units = &d_rpl->units;
3887 d_flags = &d_rpl->flags;
3888 d_min = &d_rpl->min;
3889 d_max = &d_rpl->max;
3890 break;
3891 case LYS_DEV_DELETE:
3892 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003893 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003894 d = (struct lysp_deviate *)d_del;
3895 d_units = &d_del->units;
3896 d_uniques = &d_del->uniques;
3897 d_dflts = &d_del->dflts;
3898 d_musts = &d_del->musts;
3899 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003900 break;
3901 default:
3902 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003903 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003904 }
3905 d->mod = dev_mod;
3906
3907 /* insert into siblings */
3908 if (!*deviates) {
3909 *deviates = d;
3910 } else {
3911 for (iter = *deviates; iter->next; iter = iter->next);
3912 iter->next = d;
3913 }
3914
Radek Krejci6d6556c2018-11-08 09:37:45 +01003915 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003916 switch (kw) {
3917 case YANG_CONFIG:
3918 switch (dev_mod) {
3919 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003920 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003921 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 return LY_EVALID;
3923 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003924 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003925 break;
3926 }
3927 break;
3928 case YANG_DEFAULT:
3929 switch (dev_mod) {
3930 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003931 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003932 return LY_EVALID;
3933 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003934 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 +02003935 break;
3936 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003937 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 +02003938 break;
3939 }
3940 break;
3941 case YANG_MANDATORY:
3942 switch (dev_mod) {
3943 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003944 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003945 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003946 return LY_EVALID;
3947 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003948 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003949 break;
3950 }
3951 break;
3952 case YANG_MAX_ELEMENTS:
3953 switch (dev_mod) {
3954 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003955 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003956 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003957 return LY_EVALID;
3958 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003959 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003960 break;
3961 }
3962 break;
3963 case YANG_MIN_ELEMENTS:
3964 switch (dev_mod) {
3965 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003966 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003967 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003968 return LY_EVALID;
3969 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003970 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003971 break;
3972 }
3973 break;
3974 case YANG_MUST:
3975 switch (dev_mod) {
3976 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003977 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003978 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003979 return LY_EVALID;
3980 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003981 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003982 break;
3983 }
3984 break;
3985 case YANG_TYPE:
3986 switch (dev_mod) {
3987 case LYS_DEV_NOT_SUPPORTED:
3988 case LYS_DEV_ADD:
3989 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003990 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003991 return LY_EVALID;
3992 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003993 if (d_rpl->type) {
3994 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
3995 return LY_EVALID;
3996 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003997 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003998 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003999 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004000 break;
4001 }
4002 break;
4003 case YANG_UNIQUE:
4004 switch (dev_mod) {
4005 case LYS_DEV_NOT_SUPPORTED:
4006 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004007 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004008 return LY_EVALID;
4009 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004010 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 +02004011 break;
4012 }
4013 break;
4014 case YANG_UNITS:
4015 switch (dev_mod) {
4016 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004017 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004018 return LY_EVALID;
4019 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004020 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004021 break;
4022 }
4023 break;
4024 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004025 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004026 break;
4027 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004028 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004029 return LY_EVALID;
4030 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004031 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004032 return ret;
4033}
4034
Michal Vaskoea5abea2018-09-18 13:10:54 +02004035/**
4036 * @brief Parse the deviation statement.
4037 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004038 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004039 * @param[in,out] data Data to read from, always moved to currently handled character.
4040 * @param[in,out] deviations Deviations to add to.
4041 *
4042 * @return LY_ERR values.
4043 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004044static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004045parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004046{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004047 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004048 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004049 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004050 enum yang_keyword kw;
4051 struct lysp_deviation *dev;
4052
Radek Krejci2c4e7172018-10-19 15:56:26 +02004053 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004054
4055 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004056 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004057 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004058
Radek Krejci6d6556c2018-11-08 09:37:45 +01004059 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004060 switch (kw) {
4061 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004062 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 +02004063 break;
4064 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004065 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004066 break;
4067 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004068 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 +02004069 break;
4070 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004071 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004072 break;
4073 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004074 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004075 return LY_EVALID;
4076 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004077 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004078 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004079checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004080 /* mandatory substatements */
4081 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004082 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004083 return LY_EVALID;
4084 }
4085
4086 return ret;
4087}
4088
Michal Vaskoea5abea2018-09-18 13:10:54 +02004089/**
4090 * @brief Parse the feature statement.
4091 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004092 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004093 * @param[in,out] data Data to read from, always moved to currently handled character.
4094 * @param[in,out] features Features to add to.
4095 *
4096 * @return LY_ERR values.
4097 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004098static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004099parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004100{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004101 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004102 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004103 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004104 enum yang_keyword kw;
4105 struct lysp_feature *feat;
4106
Radek Krejci2c4e7172018-10-19 15:56:26 +02004107 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004108
4109 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004110 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004111 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004112
4113 CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
4114
Radek Krejci6d6556c2018-11-08 09:37:45 +01004115 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004116 switch (kw) {
4117 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004118 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 +02004119 break;
4120 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004121 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 +02004122 break;
4123 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004124 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 +02004125 break;
4126 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004127 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004128 break;
4129 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004130 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004131 break;
4132 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004133 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004134 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004135 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004136 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004137 return ret;
4138}
4139
Michal Vaskoea5abea2018-09-18 13:10:54 +02004140/**
4141 * @brief Parse the identity statement.
4142 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004143 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004144 * @param[in,out] data Data to read from, always moved to currently handled character.
4145 * @param[in,out] identities Identities to add to.
4146 *
4147 * @return LY_ERR values.
4148 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004149static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004150parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004151{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004152 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004153 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004154 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004155 enum yang_keyword kw;
4156 struct lysp_ident *ident;
4157
Radek Krejci2c4e7172018-10-19 15:56:26 +02004158 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004159
4160 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004161 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004162 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004163
4164 CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
4165
Radek Krejci6d6556c2018-11-08 09:37:45 +01004166 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004167 switch (kw) {
4168 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004169 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 +02004170 break;
4171 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004172 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 +02004173 break;
4174 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004175 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 +02004176 break;
4177 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004178 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179 break;
4180 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004181 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 +02004182 break;
4183 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004184 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004185 break;
4186 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004187 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004188 return LY_EVALID;
4189 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004190 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004191 return ret;
4192}
4193
Michal Vaskoea5abea2018-09-18 13:10:54 +02004194/**
4195 * @brief Parse the module or submodule statement.
4196 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004197 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004198 * @param[in,out] data Data to read from, always moved to currently handled character.
4199 * @param[in,out] mod Module to write to.
4200 *
4201 * @return LY_ERR values.
4202 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004203static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004204parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004205{
4206 LY_ERR ret = 0;
4207 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004208 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004209 enum yang_keyword kw, prev_kw = 0;
4210 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejcie9e987e2018-10-31 12:50:27 +01004211 struct lysp_module *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004212
4213 /* (sub)module name */
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, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004216
Radek Krejci6d6556c2018-11-08 09:37:45 +01004217 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004218
Radek Krejcie3846472018-10-15 15:24:51 +02004219#define CHECK_ORDER(SECTION) \
4220 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4221
Michal Vasko7fbc8162018-09-17 10:35:16 +02004222 switch (kw) {
4223 /* module header */
4224 case YANG_NAMESPACE:
4225 case YANG_PREFIX:
4226 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004227 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004228 return LY_EVALID;
4229 }
Radek Krejcie3846472018-10-15 15:24:51 +02004230 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4231 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004232 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004233 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004234 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004235 return LY_EVALID;
4236 }
Radek Krejcie3846472018-10-15 15:24:51 +02004237 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4238 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004239 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004240 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004241 break;
4242 /* linkage */
4243 case YANG_INCLUDE:
4244 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004245 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004246 break;
4247 /* meta */
4248 case YANG_ORGANIZATION:
4249 case YANG_CONTACT:
4250 case YANG_DESCRIPTION:
4251 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004252 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004253 break;
4254
4255 /* revision */
4256 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004257 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004258 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004259 /* body */
4260 case YANG_ANYDATA:
4261 case YANG_ANYXML:
4262 case YANG_AUGMENT:
4263 case YANG_CHOICE:
4264 case YANG_CONTAINER:
4265 case YANG_DEVIATION:
4266 case YANG_EXTENSION:
4267 case YANG_FEATURE:
4268 case YANG_GROUPING:
4269 case YANG_IDENTITY:
4270 case YANG_LEAF:
4271 case YANG_LEAF_LIST:
4272 case YANG_LIST:
4273 case YANG_NOTIFICATION:
4274 case YANG_RPC:
4275 case YANG_TYPEDEF:
4276 case YANG_USES:
4277 case YANG_CUSTOM:
4278 mod_stmt = Y_MOD_BODY;
4279 break;
4280 default:
4281 /* error handled in the next switch */
4282 break;
4283 }
Radek Krejcie3846472018-10-15 15:24:51 +02004284#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004285
Radek Krejcie3846472018-10-15 15:24:51 +02004286 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004287 switch (kw) {
4288 /* module header */
4289 case YANG_YANG_VERSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004290 LY_CHECK_RET(parse_yangversion(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004291 break;
4292 case YANG_NAMESPACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004293 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 +02004294 break;
4295 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004296 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 +02004297 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004298 break;
4299 case YANG_BELONGS_TO:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004300 LY_CHECK_RET(parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004301 break;
4302
4303 /* linkage */
4304 case YANG_INCLUDE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004305 LY_CHECK_RET(parse_include(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004306 break;
4307 case YANG_IMPORT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004308 LY_CHECK_RET(parse_import(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004309 break;
4310
4311 /* meta */
4312 case YANG_ORGANIZATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004313 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 +02004314 break;
4315 case YANG_CONTACT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004316 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 +02004317 break;
4318 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004319 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 +02004320 break;
4321 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004322 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 +02004323 break;
4324
4325 /* revision */
4326 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004327 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004328 break;
4329
4330 /* body */
4331 case YANG_ANYDATA:
4332 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004333 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004334 break;
4335 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004336 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004337 break;
4338 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004339 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004340 break;
4341 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004342 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004343 break;
4344 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004345 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004346 break;
4347 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004348 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004349 break;
4350 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004351 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004352 break;
4353
4354 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004355 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004356 break;
4357 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004358 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004359 break;
4360 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004361 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004362 break;
4363 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004364 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004365 break;
4366 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004367 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004368 break;
4369 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004370 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004371 break;
4372 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004373 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004374 break;
4375 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004376 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004377 break;
4378 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004379 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004380 break;
4381 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004382 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004383 break;
4384
4385 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004386 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004387 return LY_EVALID;
4388 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004389 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004390 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004391checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004392 /* mandatory substatements */
4393 if (mod->submodule) {
4394 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004395 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004396 return LY_EVALID;
4397 }
4398 } else {
4399 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004400 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004401 return LY_EVALID;
4402 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004403 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004404 return LY_EVALID;
4405 }
4406 }
4407
Radek Krejcie9e987e2018-10-31 12:50:27 +01004408 /* submodules share the namespace with the module names, so there must not be
4409 * a submodule of the same name in the context, no need for revision matching */
4410 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL);
4411 if (dup && (!mod->submodule || strcmp(dup->belongsto, mod->belongsto))) {
4412 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4413 mod->submodule ? "submodules" : "module and submodule", mod->name);
4414 return LY_EVALID;
4415 }
4416
Michal Vasko7fbc8162018-09-17 10:35:16 +02004417 return ret;
4418}
4419
Radek Krejcid4557c62018-09-17 11:42:09 +02004420LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01004421yang_parse(struct ly_parser_ctx *context, const char *data, struct lysp_module **mod_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004423 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004424 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004425 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004426 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004427 struct lysp_module *mod = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428
4429 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004430 ret = get_keyword(context, &data, &kw, &word, &word_len);
4431 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004432
4433 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004434 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004435 ly_stmt2str(kw));
Radek Krejcibbe09a92018-11-08 09:36:54 +01004436 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004437 }
4438
4439 mod = calloc(1, sizeof *mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004440 LY_CHECK_ERR_GOTO(!mod, LOGMEM(context->ctx), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004441 if (kw == YANG_SUBMODULE) {
4442 mod->submodule = 1;
4443 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01004444 mod->parsing = 1;
4445 mod->ctx = context->ctx;
4446 context->mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004447
4448 /* substatements */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004449 ret = parse_sub_module(context, &data, mod);
4450 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004451
4452 /* read some trailing spaces or new lines */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004453 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4454 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004455
4456 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004457 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004458 word_len, word);
4459 free(buf);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004460 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004461 }
4462 assert(!buf);
4463
Radek Krejcibbe09a92018-11-08 09:36:54 +01004464 mod->parsing = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004465 *mod_p = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004466
Radek Krejcibbe09a92018-11-08 09:36:54 +01004467cleanup:
4468 if (ret) {
4469 lysp_module_free(mod);
4470 }
4471
Michal Vasko7fbc8162018-09-17 10:35:16 +02004472 return ret;
4473}