blob: f755d293b8b372651a671c48b2e18435b557a859 [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));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001825 free(buf);
1826 return LY_EVALID;
1827 }
1828
1829 errno = 0;
1830 if (val_kw == YANG_VALUE) {
1831 num = strtol(word, &ptr, 10);
1832 } else {
1833 unum = strtoul(word, &ptr, 10);
1834 }
1835 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001836 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001837 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001838 free(buf);
1839 return LY_EVALID;
1840 }
1841 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001842 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001843 free(buf);
1844 return LY_EVALID;
1845 }
1846 if (val_kw == YANG_VALUE) {
1847 *value = num;
1848 } else {
1849 *value = unum;
1850 }
1851 free(buf);
1852
Radek Krejci6d6556c2018-11-08 09:37:45 +01001853 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001854 switch (kw) {
1855 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001856 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 +02001857 break;
1858 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001859 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001860 return LY_EVALID;
1861 }
1862 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001863 return ret;
1864}
1865
Michal Vaskoea5abea2018-09-18 13:10:54 +02001866/**
1867 * @brief Parse the enum or bit statement. Substatement of type statement.
1868 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001869 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001870 * @param[in,out] data Data to read from, always moved to currently handled character.
1871 * @param[in] enum_kw Type of this particular keyword.
1872 * @param[in,out] enums Enums or bits to add to.
1873 *
1874 * @return LY_ERR values.
1875 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001876static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001877parse_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 +02001878{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001879 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001880 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001881 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001882 enum yang_keyword kw;
1883 struct lysp_type_enum *enm;
1884
Radek Krejci2c4e7172018-10-19 15:56:26 +02001885 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001886
1887 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001888 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001889 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001890
Radek Krejci6d6556c2018-11-08 09:37:45 +01001891 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001892 switch (kw) {
1893 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001894 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 +02001895 break;
1896 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001897 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 +02001898 break;
1899 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001900 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 +02001901 break;
1902 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001903 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001904 break;
1905 case YANG_VALUE:
1906 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001907 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001908 break;
1909 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001910 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001911 break;
1912 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001913 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001914 return LY_EVALID;
1915 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001916 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001917 return ret;
1918}
1919
Michal Vaskoea5abea2018-09-18 13:10:54 +02001920/**
1921 * @brief Parse the fraction-digits statement. Substatement of type statement.
1922 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001923 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001924 * @param[in,out] data Data to read from, always moved to currently handled character.
1925 * @param[in,out] fracdig Value to write to.
1926 * @param[in,out] exts Extension instances to add to.
1927 *
1928 * @return LY_ERR values.
1929 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001930static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001931parse_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 +02001932{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001933 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001934 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001935 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001936 unsigned long int num;
1937 enum yang_keyword kw;
1938
1939 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001940 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001941 return LY_EVALID;
1942 }
1943
1944 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001945 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001946
1947 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001948 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949 free(buf);
1950 return LY_EVALID;
1951 }
1952
1953 errno = 0;
1954 num = strtoul(word, &ptr, 10);
1955 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001956 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001957 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001958 free(buf);
1959 return LY_EVALID;
1960 }
1961 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001962 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001963 free(buf);
1964 return LY_EVALID;
1965 }
1966 *fracdig = num;
1967 free(buf);
1968
Radek Krejci6d6556c2018-11-08 09:37:45 +01001969 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001970 switch (kw) {
1971 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001972 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001973 break;
1974 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001975 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001976 return LY_EVALID;
1977 }
1978 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001979 return ret;
1980}
1981
Michal Vaskoea5abea2018-09-18 13:10:54 +02001982/**
1983 * @brief Parse the require-instance statement. Substatement of type statement.
1984 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001985 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001986 * @param[in,out] data Data to read from, always moved to currently handled character.
1987 * @param[in,out] reqinst Value to write to.
1988 * @param[in,out] flags Flags to write to.
1989 * @param[in,out] exts Extension instances to add to.
1990 *
1991 * @return LY_ERR values.
1992 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001993static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001994parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001995 struct lysp_ext_instance **exts)
1996{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001997 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001998 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001999 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002000 enum yang_keyword kw;
2001
2002 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002003 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002004 return LY_EVALID;
2005 }
2006 *flags |= LYS_SET_REQINST;
2007
2008 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002009 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002010
2011 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2012 *reqinst = 1;
2013 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002014 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002015 free(buf);
2016 return LY_EVALID;
2017 }
2018 free(buf);
2019
Radek Krejci6d6556c2018-11-08 09:37:45 +01002020 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002021 switch (kw) {
2022 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002023 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002024 break;
2025 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002026 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002027 return LY_EVALID;
2028 }
2029 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002030 return ret;
2031}
2032
Michal Vaskoea5abea2018-09-18 13:10:54 +02002033/**
2034 * @brief Parse the modifier statement. Substatement of type pattern statement.
2035 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002036 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002037 * @param[in,out] data Data to read from, always moved to currently handled character.
2038 * @param[in,out] pat Value to write to.
2039 * @param[in,out] exts Extension instances to add to.
2040 *
2041 * @return LY_ERR values.
2042 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002043static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002044parse_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 +02002045{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002046 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002047 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002048 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002049 enum yang_keyword kw;
2050
2051 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002052 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002053 return LY_EVALID;
2054 }
2055
2056 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002057 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002058
2059 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002060 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002061 free(buf);
2062 return LY_EVALID;
2063 }
2064 free(buf);
2065
2066 /* replace the value in the dictionary */
2067 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002068 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002069 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002070 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002071
2072 assert(buf[0] == 0x06);
2073 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002074 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075
Radek Krejci6d6556c2018-11-08 09:37:45 +01002076 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002077 switch (kw) {
2078 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002079 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002080 break;
2081 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002082 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002083 return LY_EVALID;
2084 }
2085 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002086 return ret;
2087}
2088
Michal Vaskoea5abea2018-09-18 13:10:54 +02002089/**
2090 * @brief Parse the pattern statement. Substatement of type statement.
2091 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002092 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002093 * @param[in,out] data Data to read from, always moved to currently handled character.
2094 * @param[in,out] patterns Restrictions to add to.
2095 *
2096 * @return LY_ERR values.
2097 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002098static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002099parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002100{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002101 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002102 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002103 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002104 enum yang_keyword kw;
2105 struct lysp_restr *restr;
2106
Radek Krejci2c4e7172018-10-19 15:56:26 +02002107 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002108
2109 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002110 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002111
2112 /* add special meaning first byte */
2113 if (buf) {
2114 buf = realloc(buf, word_len + 2);
2115 word = buf;
2116 } else {
2117 buf = malloc(word_len + 2);
2118 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002119 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002120 memmove(buf + 1, word, word_len);
2121 buf[0] = 0x06; /* pattern's default regular-match flag */
2122 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2123 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002124
Radek Krejci6d6556c2018-11-08 09:37:45 +01002125 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002126 switch (kw) {
2127 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002128 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 +02002129 break;
2130 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002131 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 +02002132 break;
2133 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002134 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 +02002135 break;
2136 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002137 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 +02002138 break;
2139 case YANG_MODIFIER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002140 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002141 break;
2142 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002143 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002144 break;
2145 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002146 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002147 return LY_EVALID;
2148 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002149 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002150 return ret;
2151}
2152
Michal Vaskoea5abea2018-09-18 13:10:54 +02002153/**
2154 * @brief Parse the type statement.
2155 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002156 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002157 * @param[in,out] data Data to read from, always moved to currently handled character.
2158 * @param[in,out] type Type to wrote to.
2159 *
2160 * @return LY_ERR values.
2161 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002162static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002163parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002164{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002165 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002166 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002167 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002168 enum yang_keyword kw;
2169 struct lysp_type *nest_type;
2170
2171 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002172 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002173 return LY_EVALID;
2174 }
2175
2176 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002177 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002178 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002179
Radek Krejci6d6556c2018-11-08 09:37:45 +01002180 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002181 switch (kw) {
2182 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002183 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002184 break;
2185 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002186 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002187 break;
2188 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002189 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002190 break;
2191 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002192 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002193 break;
2194 case YANG_LENGTH:
2195 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002196 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002197 return LY_EVALID;
2198 }
2199 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002200 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002201
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002202 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002203 break;
2204 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002205 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002206 break;
2207 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002208 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002209 break;
2210 case YANG_RANGE:
2211 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002212 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002213 return LY_EVALID;
2214 }
2215 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002216 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002217
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002218 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002219 break;
2220 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002221 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002222 break;
2223 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002224 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2225 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002226 break;
2227 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002228 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002229 break;
2230 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002231 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002232 return LY_EVALID;
2233 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002234 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002235 return ret;
2236}
2237
Michal Vaskoea5abea2018-09-18 13:10:54 +02002238/**
2239 * @brief Parse the leaf statement.
2240 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002241 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002242 * @param[in,out] data Data to read from, always moved to currently handled character.
2243 * @param[in,out] siblings Siblings to add to.
2244 *
2245 * @return LY_ERR values.
2246 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002247static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002248parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002249{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002250 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002251 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002252 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002253 enum yang_keyword kw;
2254 struct lysp_node *iter;
2255 struct lysp_node_leaf *leaf;
2256
2257 /* create structure */
2258 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002259 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002260 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002261 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002262
2263 /* insert into siblings */
2264 if (!*siblings) {
2265 *siblings = (struct lysp_node *)leaf;
2266 } else {
2267 for (iter = *siblings; iter->next; iter = iter->next);
2268 iter->next = (struct lysp_node *)leaf;
2269 }
2270
2271 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002272 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002273 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002274
2275 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002276 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002277 switch (kw) {
2278 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002279 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002280 break;
2281 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002282 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 +02002283 break;
2284 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002285 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 +02002286 break;
2287 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002288 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 +02002289 break;
2290 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002291 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002292 break;
2293 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002294 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002295 break;
2296 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002297 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 +02002298 break;
2299 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002300 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002301 break;
2302 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002303 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002304 break;
2305 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002306 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 +02002307 break;
2308 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002309 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002310 break;
2311 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002312 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002313 break;
2314 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002315 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002316 return LY_EVALID;
2317 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002318 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002319 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002320checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002321 /* mandatory substatements */
2322 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002323 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002324 return LY_EVALID;
2325 }
2326
2327 return ret;
2328}
2329
Michal Vaskoea5abea2018-09-18 13:10:54 +02002330/**
2331 * @brief Parse the max-elements statement.
2332 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002333 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002334 * @param[in,out] data Data to read from, always moved to currently handled character.
2335 * @param[in,out] max Value to write to.
2336 * @param[in,out] flags Flags to write to.
2337 * @param[in,out] exts Extension instances to add to.
2338 *
2339 * @return LY_ERR values.
2340 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002341static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002342parse_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 +02002343{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002344 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002345 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002346 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002347 unsigned long int num;
2348 enum yang_keyword kw;
2349
2350 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002351 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002352 return LY_EVALID;
2353 }
2354 *flags |= LYS_SET_MAX;
2355
2356 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002357 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002358
2359 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002360 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002361 free(buf);
2362 return LY_EVALID;
2363 }
2364
2365 if (strncmp(word, "unbounded", word_len)) {
2366 errno = 0;
2367 num = strtoul(word, &ptr, 10);
2368 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002369 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002370 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002371 free(buf);
2372 return LY_EVALID;
2373 }
2374 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002375 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002376 free(buf);
2377 return LY_EVALID;
2378 }
2379
2380 *max = num;
2381 }
2382 free(buf);
2383
Radek Krejci6d6556c2018-11-08 09:37:45 +01002384 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002385 switch (kw) {
2386 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002387 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002388 break;
2389 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002390 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002391 return LY_EVALID;
2392 }
2393 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002394 return ret;
2395}
2396
Michal Vaskoea5abea2018-09-18 13:10:54 +02002397/**
2398 * @brief Parse the min-elements statement.
2399 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002400 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002401 * @param[in,out] data Data to read from, always moved to currently handled character.
2402 * @param[in,out] min Value to write to.
2403 * @param[in,out] flags Flags to write to.
2404 * @param[in,out] exts Extension instances to add to.
2405 *
2406 * @return LY_ERR values.
2407 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002408static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002409parse_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 +02002410{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002411 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002412 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002413 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002414 unsigned long int num;
2415 enum yang_keyword kw;
2416
2417 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002418 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002419 return LY_EVALID;
2420 }
2421 *flags |= LYS_SET_MIN;
2422
2423 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002424 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002425
2426 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002427 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002428 free(buf);
2429 return LY_EVALID;
2430 }
2431
2432 errno = 0;
2433 num = strtoul(word, &ptr, 10);
2434 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002435 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002436 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002437 free(buf);
2438 return LY_EVALID;
2439 }
2440 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002441 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002442 free(buf);
2443 return LY_EVALID;
2444 }
2445 *min = num;
2446 free(buf);
2447
Radek Krejci6d6556c2018-11-08 09:37:45 +01002448 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002449 switch (kw) {
2450 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002451 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002452 break;
2453 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002454 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002455 return LY_EVALID;
2456 }
2457 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002458 return ret;
2459}
2460
Michal Vaskoea5abea2018-09-18 13:10:54 +02002461/**
2462 * @brief Parse the ordered-by statement.
2463 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002464 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002465 * @param[in,out] data Data to read from, always moved to currently handled character.
2466 * @param[in,out] flags Flags to write to.
2467 * @param[in,out] exts Extension instances to add to.
2468 *
2469 * @return LY_ERR values.
2470 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002471static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002472parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002473{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002474 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002475 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002476 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002477 enum yang_keyword kw;
2478
2479 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002480 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002481 return LY_EVALID;
2482 }
2483
2484 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002485 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002486
2487 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2488 *flags |= LYS_ORDBY_SYSTEM;
2489 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2490 *flags |= LYS_ORDBY_USER;
2491 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002492 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002493 free(buf);
2494 return LY_EVALID;
2495 }
2496 free(buf);
2497
Radek Krejci6d6556c2018-11-08 09:37:45 +01002498 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002499 switch (kw) {
2500 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002501 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002502 break;
2503 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002504 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002505 return LY_EVALID;
2506 }
2507 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002508 return ret;
2509}
2510
Michal Vaskoea5abea2018-09-18 13:10:54 +02002511/**
2512 * @brief Parse the leaf-list statement.
2513 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002514 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002515 * @param[in,out] data Data to read from, always moved to currently handled character.
2516 * @param[in,out] siblings Siblings to add to.
2517 *
2518 * @return LY_ERR values.
2519 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002520static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002521parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002522{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002523 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002524 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002525 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002526 enum yang_keyword kw;
2527 struct lysp_node *iter;
2528 struct lysp_node_leaflist *llist;
2529
2530 /* create structure */
2531 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002532 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002533 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002534 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002535
2536 /* insert into siblings */
2537 if (!*siblings) {
2538 *siblings = (struct lysp_node *)llist;
2539 } else {
2540 for (iter = *siblings; iter->next; iter = iter->next);
2541 iter->next = (struct lysp_node *)llist;
2542 }
2543
2544 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002545 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002546 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002547
2548 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002549 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002550 switch (kw) {
2551 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002552 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002553 break;
2554 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002555 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 +02002556 break;
2557 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002558 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 +02002559 break;
2560 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002561 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 +02002562 break;
2563 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002564 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002565 break;
2566 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002567 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002568 break;
2569 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002570 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002571 break;
2572 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002573 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002574 break;
2575 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002576 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 +02002577 break;
2578 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002579 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002580 break;
2581 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002582 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002583 break;
2584 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002585 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 +02002586 break;
2587 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002588 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002589 break;
2590 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002591 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002592 break;
2593 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002594 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002595 return LY_EVALID;
2596 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002597 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002598 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002599checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002600 /* mandatory substatements */
2601 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002602 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002603 return LY_EVALID;
2604 }
2605
2606 return ret;
2607}
2608
Michal Vaskoea5abea2018-09-18 13:10:54 +02002609/**
2610 * @brief Parse the refine statement.
2611 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002612 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002613 * @param[in,out] data Data to read from, always moved to currently handled character.
2614 * @param[in,out] refines Refines to add to.
2615 *
2616 * @return LY_ERR values.
2617 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002618static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002619parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002620{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002621 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002622 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002623 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002624 enum yang_keyword kw;
2625 struct lysp_refine *rf;
2626
Radek Krejci2c4e7172018-10-19 15:56:26 +02002627 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628
2629 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002630 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002631 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002632
Radek Krejci6d6556c2018-11-08 09:37:45 +01002633 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002634 switch (kw) {
2635 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002636 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002637 break;
2638 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002639 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 +02002640 break;
2641 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002642 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 +02002643 break;
2644 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002645 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 +02002646 break;
2647 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002648 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002649 break;
2650 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002651 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002652 break;
2653 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002654 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002655 break;
2656 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002657 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002658 break;
2659 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002660 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 +02002661 break;
2662 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002663 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 +02002664 break;
2665 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002666 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002667 break;
2668 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002669 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002670 return LY_EVALID;
2671 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002672 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002673 return ret;
2674}
2675
Michal Vaskoea5abea2018-09-18 13:10:54 +02002676/**
2677 * @brief Parse the typedef statement.
2678 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002679 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002680 * @param[in,out] data Data to read from, always moved to currently handled character.
2681 * @param[in,out] typedefs Typedefs to add to.
2682 *
2683 * @return LY_ERR values.
2684 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002685static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002686parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002687{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002688 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002689 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002690 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002691 enum yang_keyword kw;
2692 struct lysp_tpdf *tpdf;
2693
Radek Krejci2c4e7172018-10-19 15:56:26 +02002694 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695
2696 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002697 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002698 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002699
2700 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002701 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002702 switch (kw) {
2703 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002704 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 +02002705 break;
2706 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002707 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 +02002708 break;
2709 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002710 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 +02002711 break;
2712 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002713 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002714 break;
2715 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002716 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002717 break;
2718 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002719 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 +02002720 break;
2721 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002722 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002723 break;
2724 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002725 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002726 return LY_EVALID;
2727 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002728 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002729 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002730checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002731 /* mandatory substatements */
2732 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002733 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002734 return LY_EVALID;
2735 }
2736
Radek Krejcibbe09a92018-11-08 09:36:54 +01002737 /* store data for collision check */
2738 if (parent) {
2739 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2740 }
2741
Michal Vasko7fbc8162018-09-17 10:35:16 +02002742 return ret;
2743}
2744
Michal Vaskoea5abea2018-09-18 13:10:54 +02002745/**
2746 * @brief Parse the input or output statement.
2747 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002748 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002749 * @param[in,out] data Data to read from, always moved to currently handled character.
2750 * @param[in] kw Type of this particular keyword
2751 * @param[in,out] inout_p Input/output pointer to write to.
2752 *
2753 * @return LY_ERR values.
2754 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002755static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002756parse_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 +02002757{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002758 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002759 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002760 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002761 struct lysp_action_inout *inout;
2762
2763 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002764 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765 return LY_EVALID;
2766 }
2767
2768 /* create structure */
2769 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002770 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002771 *inout_p = inout;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002772 inout->nodetype = LYS_INOUT;
2773 inout->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002774
2775 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002776 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002777 switch (kw) {
2778 case YANG_ANYDATA:
2779 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002780 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002781 break;
2782 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002783 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002784 break;
2785 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002786 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002787 break;
2788 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002789 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790 break;
2791 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002792 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002793 break;
2794 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002795 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 break;
2797 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002798 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002799 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002800 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002801 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout, data, &inout->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002802 break;
2803 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002804 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002805 break;
2806 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002807 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout, &inout->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002808 break;
2809 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002810 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002811 break;
2812 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002813 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002814 return LY_EVALID;
2815 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002816 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002817 return ret;
2818}
2819
Michal Vaskoea5abea2018-09-18 13:10:54 +02002820/**
2821 * @brief Parse the action statement.
2822 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002823 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002824 * @param[in,out] data Data to read from, always moved to currently handled character.
2825 * @param[in,out] actions Actions to add to.
2826 *
2827 * @return LY_ERR values.
2828 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002829static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002830parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002831{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002832 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002833 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002834 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002835 enum yang_keyword kw;
2836 struct lysp_action *act;
2837
Radek Krejci2c4e7172018-10-19 15:56:26 +02002838 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002839
2840 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002841 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002842 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002843 act->nodetype = LYS_ACTION;
2844 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002845
Radek Krejci6d6556c2018-11-08 09:37:45 +01002846 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002847 switch (kw) {
2848 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002849 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 +02002850 break;
2851 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002852 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 +02002853 break;
2854 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002855 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 +02002856 break;
2857 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002858 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002859 break;
2860
2861 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002862 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863 break;
2864 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002865 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002866 break;
2867
2868 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002869 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002870 break;
2871 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002872 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002873 break;
2874 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002875 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002876 break;
2877 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002878 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002879 return LY_EVALID;
2880 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002881 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002882 return ret;
2883}
2884
Michal Vaskoea5abea2018-09-18 13:10:54 +02002885/**
2886 * @brief Parse the notification statement.
2887 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002888 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002889 * @param[in,out] data Data to read from, always moved to currently handled character.
2890 * @param[in,out] notifs Notifications to add to.
2891 *
2892 * @return LY_ERR values.
2893 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002894static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002895parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002896{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002897 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002898 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002899 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002900 enum yang_keyword kw;
2901 struct lysp_notif *notif;
2902
Radek Krejci2c4e7172018-10-19 15:56:26 +02002903 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002904
2905 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002906 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002907 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002908 notif->nodetype = LYS_NOTIF;
2909 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002910
Radek Krejci6d6556c2018-11-08 09:37:45 +01002911 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002912 switch (kw) {
2913 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002914 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 +02002915 break;
2916 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002917 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 +02002918 break;
2919 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002920 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 +02002921 break;
2922 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002923 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002924 break;
2925
2926 case YANG_ANYDATA:
2927 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002928 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002929 break;
2930 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002931 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932 break;
2933 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002934 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002935 break;
2936 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002937 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002938 break;
2939 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002940 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002941 break;
2942 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002943 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002944 break;
2945 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002946 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002947 break;
2948
2949 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002950 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002951 break;
2952 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002953 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002954 break;
2955 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002956 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002957 break;
2958 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002959 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002960 break;
2961 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002962 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002963 return LY_EVALID;
2964 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002965 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002966 return ret;
2967}
2968
Michal Vaskoea5abea2018-09-18 13:10:54 +02002969/**
2970 * @brief Parse the grouping statement.
2971 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002972 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002973 * @param[in,out] data Data to read from, always moved to currently handled character.
2974 * @param[in,out] groupings Groupings to add to.
2975 *
2976 * @return LY_ERR values.
2977 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002979parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002980{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002981 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002982 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002983 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002984 enum yang_keyword kw;
2985 struct lysp_grp *grp;
2986
Radek Krejci2c4e7172018-10-19 15:56:26 +02002987 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002988
2989 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002990 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002991 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002992 grp->nodetype = LYS_GROUPING;
2993 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002994
Radek Krejci6d6556c2018-11-08 09:37:45 +01002995 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002996 switch (kw) {
2997 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002998 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 +02002999 break;
3000 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003001 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 +02003002 break;
3003 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003004 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003005 break;
3006
3007 case YANG_ANYDATA:
3008 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003009 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003010 break;
3011 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003012 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003013 break;
3014 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003015 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003016 break;
3017 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003018 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003019 break;
3020 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003021 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003022 break;
3023 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003024 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003025 break;
3026 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003027 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003028 break;
3029
3030 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003031 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032 break;
3033 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003034 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003035 break;
3036 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003037 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003038 break;
3039 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003040 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003041 break;
3042 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003043 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003044 break;
3045 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003046 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003047 return LY_EVALID;
3048 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003049 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003050 return ret;
3051}
3052
Michal Vaskoea5abea2018-09-18 13:10:54 +02003053/**
3054 * @brief Parse the refine statement.
3055 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003056 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003057 * @param[in,out] data Data to read from, always moved to currently handled character.
3058 * @param[in,out] augments Augments to add to.
3059 *
3060 * @return LY_ERR values.
3061 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003062static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003063parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003064{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003065 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003066 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003067 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003068 enum yang_keyword kw;
3069 struct lysp_augment *aug;
3070
Radek Krejci2c4e7172018-10-19 15:56:26 +02003071 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003072
3073 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003074 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003075 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003076 aug->nodetype = LYS_AUGMENT;
3077 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003078
Radek Krejci6d6556c2018-11-08 09:37:45 +01003079 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003080 switch (kw) {
3081 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003082 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 +02003083 break;
3084 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003085 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 +02003086 break;
3087 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003088 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 +02003089 break;
3090 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003091 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003092 break;
3093 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003094 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003095 break;
3096
3097 case YANG_ANYDATA:
3098 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003099 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003100 break;
3101 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003102 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003103 break;
3104 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003105 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003106 break;
3107 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003108 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003109 break;
3110 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003111 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003112 break;
3113 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003114 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003115 break;
3116 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003117 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003118 break;
3119 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003120 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003121 break;
3122
3123 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003124 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003125 break;
3126 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003127 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003128 break;
3129 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003130 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003131 break;
3132 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003133 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003134 return LY_EVALID;
3135 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003136 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003137 return ret;
3138}
3139
Michal Vaskoea5abea2018-09-18 13:10:54 +02003140/**
3141 * @brief Parse the uses statement.
3142 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003143 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003144 * @param[in,out] data Data to read from, always moved to currently handled character.
3145 * @param[in,out] siblings Siblings to add to.
3146 *
3147 * @return LY_ERR values.
3148 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003149static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003150parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003151{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003152 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003153 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003154 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003155 enum yang_keyword kw;
3156 struct lysp_node *iter;
3157 struct lysp_node_uses *uses;
3158
3159 /* create structure */
3160 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003161 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003162 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003163 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003164
3165 /* insert into siblings */
3166 if (!*siblings) {
3167 *siblings = (struct lysp_node *)uses;
3168 } else {
3169 for (iter = *siblings; iter->next; iter = iter->next);
3170 iter->next = (struct lysp_node *)uses;
3171 }
3172
3173 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003174 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003175 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003176
3177 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003178 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003179 switch (kw) {
3180 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003181 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 +02003182 break;
3183 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003184 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 +02003185 break;
3186 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003187 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 +02003188 break;
3189 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003190 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003191 break;
3192 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003193 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003194 break;
3195
3196 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003197 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003198 break;
3199 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003200 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003201 break;
3202 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003203 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003204 break;
3205 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003206 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003207 return LY_EVALID;
3208 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003209 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003210 return ret;
3211}
3212
Michal Vaskoea5abea2018-09-18 13:10:54 +02003213/**
3214 * @brief Parse the case statement.
3215 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003216 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003217 * @param[in,out] data Data to read from, always moved to currently handled character.
3218 * @param[in,out] siblings Siblings to add to.
3219 *
3220 * @return LY_ERR values.
3221 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003222static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003223parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003225 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003226 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003227 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003228 enum yang_keyword kw;
3229 struct lysp_node *iter;
3230 struct lysp_node_case *cas;
3231
3232 /* create structure */
3233 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003234 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003235 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003236 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003237
3238 /* insert into siblings */
3239 if (!*siblings) {
3240 *siblings = (struct lysp_node *)cas;
3241 } else {
3242 for (iter = *siblings; iter->next; iter = iter->next);
3243 iter->next = (struct lysp_node *)cas;
3244 }
3245
3246 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003247 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003248 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003249
3250 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003251 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003252 switch (kw) {
3253 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003254 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003255 break;
3256 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003257 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003258 break;
3259 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003260 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003261 break;
3262 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003263 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003264 break;
3265 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003266 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003267 break;
3268
3269 case YANG_ANYDATA:
3270 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003271 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003272 break;
3273 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003274 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003275 break;
3276 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003277 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003278 break;
3279 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003280 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003281 break;
3282 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003283 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003284 break;
3285 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003286 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003287 break;
3288 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003289 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003290 break;
3291 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003292 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003293 break;
3294 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003295 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003296 return LY_EVALID;
3297 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003298 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003299 return ret;
3300}
3301
Michal Vaskoea5abea2018-09-18 13:10:54 +02003302/**
3303 * @brief Parse the choice statement.
3304 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003305 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003306 * @param[in,out] data Data to read from, always moved to currently handled character.
3307 * @param[in,out] siblings Siblings to add to.
3308 *
3309 * @return LY_ERR values.
3310 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003311static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003312parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003313{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003314 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003315 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003316 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003317 enum yang_keyword kw;
3318 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003319 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003320
3321 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003322 choice = calloc(1, sizeof *choice);
3323 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3324 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003325 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003326
3327 /* insert into siblings */
3328 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003329 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003330 } else {
3331 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003332 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003333 }
3334
3335 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003336 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003337 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003338
3339 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003340 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003341 switch (kw) {
3342 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003343 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003344 break;
3345 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003346 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 +02003347 break;
3348 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003349 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 +02003350 break;
3351 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003352 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003353 break;
3354 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003355 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 +02003356 break;
3357 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003358 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003359 break;
3360 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003361 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003362 break;
3363 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003364 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 +02003365 break;
3366
3367 case YANG_ANYDATA:
3368 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003369 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003370 break;
3371 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003372 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373 break;
3374 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003375 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003376 break;
3377 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003378 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003379 break;
3380 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003381 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003382 break;
3383 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003384 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003385 break;
3386 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003387 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003388 break;
3389 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003390 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003391 break;
3392 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003393 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003394 return LY_EVALID;
3395 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003396 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003397 return ret;
3398}
3399
Michal Vaskoea5abea2018-09-18 13:10:54 +02003400/**
3401 * @brief Parse the container statement.
3402 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003403 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003404 * @param[in,out] data Data to read from, always moved to currently handled character.
3405 * @param[in,out] siblings Siblings to add to.
3406 *
3407 * @return LY_ERR values.
3408 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003409static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003410parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003411{
3412 LY_ERR ret = 0;
3413 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003414 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003415 enum yang_keyword kw;
3416 struct lysp_node *iter;
3417 struct lysp_node_container *cont;
3418
3419 /* create structure */
3420 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003421 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003423 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003424
3425 /* insert into siblings */
3426 if (!*siblings) {
3427 *siblings = (struct lysp_node *)cont;
3428 } else {
3429 for (iter = *siblings; iter->next; iter = iter->next);
3430 iter->next = (struct lysp_node *)cont;
3431 }
3432
3433 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003434 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003435 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003436
3437 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003438 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003439 switch (kw) {
3440 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003441 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003442 break;
3443 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003444 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 +02003445 break;
3446 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003447 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 +02003448 break;
3449 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003450 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 +02003451 break;
3452 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003453 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003454 break;
3455 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003456 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003457 break;
3458 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003459 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 +02003460 break;
3461
3462 case YANG_ANYDATA:
3463 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003464 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003465 break;
3466 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003467 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003468 break;
3469 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003470 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003471 break;
3472 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003473 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003474 break;
3475 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003476 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003477 break;
3478 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003479 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003480 break;
3481 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003482 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483 break;
3484
3485 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003486 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003487 break;
3488 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003489 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003490 break;
3491 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003492 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003493 break;
3494 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003495 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003496 break;
3497 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003498 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003499 break;
3500 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003501 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003502 break;
3503 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003504 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003505 return LY_EVALID;
3506 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003507 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003508 return ret;
3509}
3510
Michal Vaskoea5abea2018-09-18 13:10:54 +02003511/**
3512 * @brief Parse the list statement.
3513 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003514 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003515 * @param[in,out] data Data to read from, always moved to currently handled character.
3516 * @param[in,out] siblings Siblings to add to.
3517 *
3518 * @return LY_ERR values.
3519 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003520static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003521parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003522{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003523 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003524 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003525 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003526 enum yang_keyword kw;
3527 struct lysp_node *iter;
3528 struct lysp_node_list *list;
3529
3530 /* create structure */
3531 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003532 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003533 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003534 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003535
3536 /* insert into siblings */
3537 if (!*siblings) {
3538 *siblings = (struct lysp_node *)list;
3539 } else {
3540 for (iter = *siblings; iter->next; iter = iter->next);
3541 iter->next = (struct lysp_node *)list;
3542 }
3543
3544 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003545 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003546 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003547
3548 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003549 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003550 switch (kw) {
3551 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003552 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003553 break;
3554 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003555 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 +02003556 break;
3557 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003558 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 +02003559 break;
3560 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003561 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 +02003562 break;
3563 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003564 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003565 break;
3566 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003567 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003568 break;
3569 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003570 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 +02003571 break;
3572 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003573 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003574 break;
3575 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003576 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003577 break;
3578 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003579 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003580 break;
3581 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003582 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 +02003583 break;
3584
3585 case YANG_ANYDATA:
3586 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003587 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003588 break;
3589 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003590 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003591 break;
3592 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003593 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003594 break;
3595 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003596 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003597 break;
3598 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003599 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003600 break;
3601 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003602 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003603 break;
3604 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003605 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003606 break;
3607
3608 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003609 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610 break;
3611 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003612 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613 break;
3614 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003615 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003616 break;
3617 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003618 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003619 break;
3620 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003621 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003622 break;
3623 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003624 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003625 break;
3626 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003627 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003628 return LY_EVALID;
3629 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003630 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003631
3632 return ret;
3633}
3634
Michal Vaskoea5abea2018-09-18 13:10:54 +02003635/**
3636 * @brief Parse the yin-element statement.
3637 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003638 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003639 * @param[in,out] data Data to read from, always moved to currently handled character.
3640 * @param[in,out] flags Flags to write to.
3641 * @param[in,out] exts Extension instances to add to.
3642 *
3643 * @return LY_ERR values.
3644 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003645static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003646parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003647{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003648 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003649 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003650 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003651 enum yang_keyword kw;
3652
3653 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003654 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003655 return LY_EVALID;
3656 }
3657
3658 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003659 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003660
3661 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3662 *flags |= LYS_YINELEM_TRUE;
3663 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3664 *flags |= LYS_YINELEM_FALSE;
3665 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003666 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003667 free(buf);
3668 return LY_EVALID;
3669 }
3670 free(buf);
3671
Radek Krejci6d6556c2018-11-08 09:37:45 +01003672 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003673 switch (kw) {
3674 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003675 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3676 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003677 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003678 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003679 return LY_EVALID;
3680 }
3681 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003682 return ret;
3683}
3684
Michal Vaskoea5abea2018-09-18 13:10:54 +02003685/**
3686 * @brief Parse the yin-element statement.
3687 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003688 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003689 * @param[in,out] data Data to read from, always moved to currently handled character.
3690 * @param[in,out] argument Value to write to.
3691 * @param[in,out] flags Flags to write to.
3692 * @param[in,out] exts Extension instances to add to.
3693 *
3694 * @return LY_ERR values.
3695 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003696static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003697parse_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 +02003698{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003699 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003700 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003701 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003702 enum yang_keyword kw;
3703
3704 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003705 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003706 return LY_EVALID;
3707 }
3708
3709 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003710 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003711 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003712
Radek Krejci6d6556c2018-11-08 09:37:45 +01003713 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003714 switch (kw) {
3715 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003716 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003717 break;
3718 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003719 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003720 break;
3721 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003722 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003723 return LY_EVALID;
3724 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003726 return ret;
3727}
3728
Michal Vaskoea5abea2018-09-18 13:10:54 +02003729/**
3730 * @brief Parse the extension statement.
3731 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003732 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003733 * @param[in,out] data Data to read from, always moved to currently handled character.
3734 * @param[in,out] extensions Extensions to add to.
3735 *
3736 * @return LY_ERR values.
3737 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003738static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003739parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003740{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003741 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003742 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003743 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003744 enum yang_keyword kw;
3745 struct lysp_ext *ex;
3746
Radek Krejci2c4e7172018-10-19 15:56:26 +02003747 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003748
3749 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003750 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003751 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003752
Radek Krejci6d6556c2018-11-08 09:37:45 +01003753 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003754 switch (kw) {
3755 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003756 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 +02003757 break;
3758 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003759 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 +02003760 break;
3761 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003762 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003763 break;
3764 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003765 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003766 break;
3767 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003768 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003769 break;
3770 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003771 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003772 return LY_EVALID;
3773 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003774 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003775 return ret;
3776}
3777
Michal Vaskoea5abea2018-09-18 13:10:54 +02003778/**
3779 * @brief Parse the deviate statement.
3780 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003781 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003782 * @param[in,out] data Data to read from, always moved to currently handled character.
3783 * @param[in,out] deviates Deviates to add to.
3784 *
3785 * @return LY_ERR values.
3786 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003787static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003788parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003789{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003790 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003791 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003792 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003793 enum yang_keyword kw;
3794 struct lysp_deviate *iter, *d;
3795 struct lysp_deviate_add *d_add = NULL;
3796 struct lysp_deviate_rpl *d_rpl = NULL;
3797 struct lysp_deviate_del *d_del = NULL;
3798 const char **d_units, ***d_uniques, ***d_dflts;
3799 struct lysp_restr **d_musts;
3800 uint16_t *d_flags;
3801 uint32_t *d_min, *d_max;
3802
3803 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003804 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003805
3806 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3807 dev_mod = LYS_DEV_NOT_SUPPORTED;
3808 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3809 dev_mod = LYS_DEV_ADD;
3810 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3811 dev_mod = LYS_DEV_REPLACE;
3812 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3813 dev_mod = LYS_DEV_DELETE;
3814 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003815 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003816 free(buf);
3817 return LY_EVALID;
3818 }
3819 free(buf);
3820
3821 /* create structure */
3822 switch (dev_mod) {
3823 case LYS_DEV_NOT_SUPPORTED:
3824 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003825 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003826 break;
3827 case LYS_DEV_ADD:
3828 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003829 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003830 d = (struct lysp_deviate *)d_add;
3831 d_units = &d_add->units;
3832 d_uniques = &d_add->uniques;
3833 d_dflts = &d_add->dflts;
3834 d_musts = &d_add->musts;
3835 d_flags = &d_add->flags;
3836 d_min = &d_add->min;
3837 d_max = &d_add->max;
3838 break;
3839 case LYS_DEV_REPLACE:
3840 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003841 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003842 d = (struct lysp_deviate *)d_rpl;
3843 d_units = &d_rpl->units;
3844 d_flags = &d_rpl->flags;
3845 d_min = &d_rpl->min;
3846 d_max = &d_rpl->max;
3847 break;
3848 case LYS_DEV_DELETE:
3849 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003850 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003851 d = (struct lysp_deviate *)d_del;
3852 d_units = &d_del->units;
3853 d_uniques = &d_del->uniques;
3854 d_dflts = &d_del->dflts;
3855 d_musts = &d_del->musts;
3856 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857 break;
3858 default:
3859 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003860 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003861 }
3862 d->mod = dev_mod;
3863
3864 /* insert into siblings */
3865 if (!*deviates) {
3866 *deviates = d;
3867 } else {
3868 for (iter = *deviates; iter->next; iter = iter->next);
3869 iter->next = d;
3870 }
3871
Radek Krejci6d6556c2018-11-08 09:37:45 +01003872 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003873 switch (kw) {
3874 case YANG_CONFIG:
3875 switch (dev_mod) {
3876 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003877 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003878 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003879 return LY_EVALID;
3880 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003881 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003882 break;
3883 }
3884 break;
3885 case YANG_DEFAULT:
3886 switch (dev_mod) {
3887 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003888 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003889 return LY_EVALID;
3890 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003891 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 +02003892 break;
3893 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003894 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 +02003895 break;
3896 }
3897 break;
3898 case YANG_MANDATORY:
3899 switch (dev_mod) {
3900 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003901 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003902 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003903 return LY_EVALID;
3904 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003905 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003906 break;
3907 }
3908 break;
3909 case YANG_MAX_ELEMENTS:
3910 switch (dev_mod) {
3911 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003912 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003913 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003914 return LY_EVALID;
3915 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003916 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003917 break;
3918 }
3919 break;
3920 case YANG_MIN_ELEMENTS:
3921 switch (dev_mod) {
3922 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003923 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003924 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003925 return LY_EVALID;
3926 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003927 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003928 break;
3929 }
3930 break;
3931 case YANG_MUST:
3932 switch (dev_mod) {
3933 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003934 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003935 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003936 return LY_EVALID;
3937 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003938 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003939 break;
3940 }
3941 break;
3942 case YANG_TYPE:
3943 switch (dev_mod) {
3944 case LYS_DEV_NOT_SUPPORTED:
3945 case LYS_DEV_ADD:
3946 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003947 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003948 return LY_EVALID;
3949 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003950 if (d_rpl->type) {
3951 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
3952 return LY_EVALID;
3953 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003954 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003955 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003956 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003957 break;
3958 }
3959 break;
3960 case YANG_UNIQUE:
3961 switch (dev_mod) {
3962 case LYS_DEV_NOT_SUPPORTED:
3963 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003964 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003965 return LY_EVALID;
3966 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003967 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003968 break;
3969 }
3970 break;
3971 case YANG_UNITS:
3972 switch (dev_mod) {
3973 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003974 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003975 return LY_EVALID;
3976 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003977 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 +02003978 break;
3979 }
3980 break;
3981 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003982 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003983 break;
3984 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003985 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003986 return LY_EVALID;
3987 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003988 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003989 return ret;
3990}
3991
Michal Vaskoea5abea2018-09-18 13:10:54 +02003992/**
3993 * @brief Parse the deviation statement.
3994 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003995 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003996 * @param[in,out] data Data to read from, always moved to currently handled character.
3997 * @param[in,out] deviations Deviations to add to.
3998 *
3999 * @return LY_ERR values.
4000 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004001static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004002parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004003{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004004 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004005 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004006 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004007 enum yang_keyword kw;
4008 struct lysp_deviation *dev;
4009
Radek Krejci2c4e7172018-10-19 15:56:26 +02004010 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004011
4012 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004013 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004014 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004015
Radek Krejci6d6556c2018-11-08 09:37:45 +01004016 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017 switch (kw) {
4018 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004019 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 +02004020 break;
4021 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004022 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004023 break;
4024 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004025 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 +02004026 break;
4027 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004028 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004029 break;
4030 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004031 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004032 return LY_EVALID;
4033 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004034 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004035 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004036checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004037 /* mandatory substatements */
4038 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004039 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004040 return LY_EVALID;
4041 }
4042
4043 return ret;
4044}
4045
Michal Vaskoea5abea2018-09-18 13:10:54 +02004046/**
4047 * @brief Parse the feature statement.
4048 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004049 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004050 * @param[in,out] data Data to read from, always moved to currently handled character.
4051 * @param[in,out] features Features to add to.
4052 *
4053 * @return LY_ERR values.
4054 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004055static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004056parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004057{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004058 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004059 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004060 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004061 enum yang_keyword kw;
4062 struct lysp_feature *feat;
4063
Radek Krejci2c4e7172018-10-19 15:56:26 +02004064 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004065
4066 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004067 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004068 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004069
4070 CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
4071
Radek Krejci6d6556c2018-11-08 09:37:45 +01004072 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004073 switch (kw) {
4074 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004075 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 +02004076 break;
4077 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004078 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 +02004079 break;
4080 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004081 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 +02004082 break;
4083 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004084 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004085 break;
4086 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004087 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004088 break;
4089 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004090 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004091 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004092 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004093 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004094 return ret;
4095}
4096
Michal Vaskoea5abea2018-09-18 13:10:54 +02004097/**
4098 * @brief Parse the identity statement.
4099 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004100 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004101 * @param[in,out] data Data to read from, always moved to currently handled character.
4102 * @param[in,out] identities Identities to add to.
4103 *
4104 * @return LY_ERR values.
4105 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004106static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004107parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004108{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004109 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004110 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004111 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004112 enum yang_keyword kw;
4113 struct lysp_ident *ident;
4114
Radek Krejci2c4e7172018-10-19 15:56:26 +02004115 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004116
4117 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004118 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004119 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004120
4121 CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
4122
Radek Krejci6d6556c2018-11-08 09:37:45 +01004123 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004124 switch (kw) {
4125 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004126 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 +02004127 break;
4128 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004129 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 +02004130 break;
4131 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004132 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 +02004133 break;
4134 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004135 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004136 break;
4137 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004138 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 +02004139 break;
4140 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004141 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004142 break;
4143 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004144 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004145 return LY_EVALID;
4146 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004147 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004148 return ret;
4149}
4150
Michal Vaskoea5abea2018-09-18 13:10:54 +02004151/**
4152 * @brief Parse the module or submodule statement.
4153 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004154 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004155 * @param[in,out] data Data to read from, always moved to currently handled character.
4156 * @param[in,out] mod Module to write to.
4157 *
4158 * @return LY_ERR values.
4159 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004160static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004161parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004162{
4163 LY_ERR ret = 0;
4164 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004165 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004166 enum yang_keyword kw, prev_kw = 0;
4167 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejcie9e987e2018-10-31 12:50:27 +01004168 struct lysp_module *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004169
4170 /* (sub)module name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004171 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004172 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004173
Radek Krejci6d6556c2018-11-08 09:37:45 +01004174 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004175
Radek Krejcie3846472018-10-15 15:24:51 +02004176#define CHECK_ORDER(SECTION) \
4177 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4178
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179 switch (kw) {
4180 /* module header */
4181 case YANG_NAMESPACE:
4182 case YANG_PREFIX:
4183 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004184 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004185 return LY_EVALID;
4186 }
Radek Krejcie3846472018-10-15 15:24:51 +02004187 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4188 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004189 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004190 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004191 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004192 return LY_EVALID;
4193 }
Radek Krejcie3846472018-10-15 15:24:51 +02004194 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4195 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004196 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004197 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004198 break;
4199 /* linkage */
4200 case YANG_INCLUDE:
4201 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004202 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004203 break;
4204 /* meta */
4205 case YANG_ORGANIZATION:
4206 case YANG_CONTACT:
4207 case YANG_DESCRIPTION:
4208 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004209 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004210 break;
4211
4212 /* revision */
4213 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004214 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004215 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004216 /* body */
4217 case YANG_ANYDATA:
4218 case YANG_ANYXML:
4219 case YANG_AUGMENT:
4220 case YANG_CHOICE:
4221 case YANG_CONTAINER:
4222 case YANG_DEVIATION:
4223 case YANG_EXTENSION:
4224 case YANG_FEATURE:
4225 case YANG_GROUPING:
4226 case YANG_IDENTITY:
4227 case YANG_LEAF:
4228 case YANG_LEAF_LIST:
4229 case YANG_LIST:
4230 case YANG_NOTIFICATION:
4231 case YANG_RPC:
4232 case YANG_TYPEDEF:
4233 case YANG_USES:
4234 case YANG_CUSTOM:
4235 mod_stmt = Y_MOD_BODY;
4236 break;
4237 default:
4238 /* error handled in the next switch */
4239 break;
4240 }
Radek Krejcie3846472018-10-15 15:24:51 +02004241#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004242
Radek Krejcie3846472018-10-15 15:24:51 +02004243 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004244 switch (kw) {
4245 /* module header */
4246 case YANG_YANG_VERSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004247 LY_CHECK_RET(parse_yangversion(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004248 break;
4249 case YANG_NAMESPACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004250 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 +02004251 break;
4252 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004253 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 +02004254 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004255 break;
4256 case YANG_BELONGS_TO:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004257 LY_CHECK_RET(parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004258 break;
4259
4260 /* linkage */
4261 case YANG_INCLUDE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004262 LY_CHECK_RET(parse_include(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004263 break;
4264 case YANG_IMPORT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004265 LY_CHECK_RET(parse_import(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004266 break;
4267
4268 /* meta */
4269 case YANG_ORGANIZATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004270 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 +02004271 break;
4272 case YANG_CONTACT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004273 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 +02004274 break;
4275 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004276 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 +02004277 break;
4278 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004279 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 +02004280 break;
4281
4282 /* revision */
4283 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004284 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004285 break;
4286
4287 /* body */
4288 case YANG_ANYDATA:
4289 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004290 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004291 break;
4292 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004293 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004294 break;
4295 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004296 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004297 break;
4298 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004299 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004300 break;
4301 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004302 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004303 break;
4304 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004305 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004306 break;
4307 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004308 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004309 break;
4310
4311 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004312 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004313 break;
4314 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004315 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316 break;
4317 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004318 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004319 break;
4320 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004321 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004322 break;
4323 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004324 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004325 break;
4326 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004327 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004328 break;
4329 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004330 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004331 break;
4332 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004333 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004334 break;
4335 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004336 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004337 break;
4338 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004339 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004340 break;
4341
4342 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004343 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004344 return LY_EVALID;
4345 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004346 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004347 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004348checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004349 /* mandatory substatements */
4350 if (mod->submodule) {
4351 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004352 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004353 return LY_EVALID;
4354 }
4355 } else {
4356 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004357 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004358 return LY_EVALID;
4359 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004360 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004361 return LY_EVALID;
4362 }
4363 }
4364
Radek Krejcie9e987e2018-10-31 12:50:27 +01004365 /* submodules share the namespace with the module names, so there must not be
4366 * a submodule of the same name in the context, no need for revision matching */
4367 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL);
4368 if (dup && (!mod->submodule || strcmp(dup->belongsto, mod->belongsto))) {
4369 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4370 mod->submodule ? "submodules" : "module and submodule", mod->name);
4371 return LY_EVALID;
4372 }
4373
Michal Vasko7fbc8162018-09-17 10:35:16 +02004374 return ret;
4375}
4376
Radek Krejcid4557c62018-09-17 11:42:09 +02004377LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01004378yang_parse(struct ly_parser_ctx *context, const char *data, struct lysp_module **mod_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004379{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004380 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004381 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004382 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004383 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004384 struct lysp_module *mod = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004385
4386 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004387 ret = get_keyword(context, &data, &kw, &word, &word_len);
4388 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004389
4390 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004391 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004392 ly_stmt2str(kw));
Radek Krejcibbe09a92018-11-08 09:36:54 +01004393 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004394 }
4395
4396 mod = calloc(1, sizeof *mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004397 LY_CHECK_ERR_GOTO(!mod, LOGMEM(context->ctx), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004398 if (kw == YANG_SUBMODULE) {
4399 mod->submodule = 1;
4400 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01004401 mod->parsing = 1;
4402 mod->ctx = context->ctx;
4403 context->mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004404
4405 /* substatements */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004406 ret = parse_sub_module(context, &data, mod);
4407 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004408
4409 /* read some trailing spaces or new lines */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004410 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4411 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004412
4413 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004414 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004415 word_len, word);
4416 free(buf);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004417 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004418 }
4419 assert(!buf);
4420
Radek Krejcibbe09a92018-11-08 09:36:54 +01004421 mod->parsing = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422 *mod_p = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004423
Radek Krejcibbe09a92018-11-08 09:36:54 +01004424cleanup:
4425 if (ret) {
4426 lysp_module_free(mod);
4427 }
4428
Michal Vasko7fbc8162018-09-17 10:35:16 +02004429 return ret;
4430}