blob: 2f3d9db51b4ee1d07e70f7f91cf39a41dec808cb [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 */
Michal Vasko7fbc8162018-09-17 10:35:16 +020077#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR) \
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 Krejci6d9b9b52018-11-02 12:43:39 +010080 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +020081 } \
82 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020083 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020084 return LY_EVALID; \
85 } \
86 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
87 !ERR && (KW != YANG_RIGHT_BRACE); \
88 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
89
Radek Krejci6d9b9b52018-11-02 12:43:39 +010090static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
91static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
92static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
93static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
94static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
95static 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 +020096
Michal Vaskoea5abea2018-09-18 13:10:54 +020097/**
98 * @brief Add another character to dynamic buffer, a low-level function.
99 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200100 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200101 *
Radek Krejci404251e2018-10-09 12:06:44 +0200102 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200103 * @param[in, out] input Input string to process.
104 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200105 * @param[in,out] buf Buffer to use, can be moved by realloc().
106 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200107 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200108 *
109 * @return LY_ERR values.
110 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200111static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200112buf_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 +0200113{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200114 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200115 *buf_len += 16;
116 *buf = ly_realloc(*buf, *buf_len);
117 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
118 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200119 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200120
Radek Krejci44ceedc2018-10-02 15:54:31 +0200121 (*buf_used) += len;
122 (*input) += len;
123
Michal Vasko7fbc8162018-09-17 10:35:16 +0200124 return LY_SUCCESS;
125}
126
Michal Vaskoea5abea2018-09-18 13:10:54 +0200127/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200128 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200129 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200130 * @param[in] ctx yang parser context for logging.
131 * @param[in] c UTF8 code point of a character to check.
132 * @return LY_ERR values.
133 */
134static LY_ERR
135check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
136{
137 if (!is_yangutf8char(c)) {
138 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
139 return LY_EVALID;
140 }
141 return LY_SUCCESS;
142}
143
144/**
145 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
146 *
147 * @param[in] ctx yang parser context for logging.
148 * @param[in] c UTF8 code point of a character to check.
149 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200150 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
151 * 0 - colon not yet found (no prefix)
152 * 1 - \p c is the colon character
153 * 2 - prefix already processed, now processing the identifier
154 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200155 * If the identifier cannot be prefixed, NULL is expected.
156 * @return LY_ERR values.
157 */
158static LY_ERR
159check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
160{
161 if (first || (prefix && (*prefix) == 1)) {
162 if (!is_yangidentstartchar(c)) {
163 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
164 return LY_EVALID;
165 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200166 if (prefix) {
167 if (first) {
168 (*prefix) = 0;
169 } else {
170 (*prefix) = 2;
171 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200172 }
173 } else if (c == ':' && prefix && (*prefix) == 0) {
174 (*prefix) = 1;
175 } else if (!is_yangidentchar(c)) {
176 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
177 return LY_EVALID;
178 }
179
180 return LY_SUCCESS;
181}
182
183/**
184 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
185 *
186 * @param[in] ctx yang parser context for logging.
187 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
188 * when function returns.
189 * @param[in] arg Type of the input string to select method of checking character validity.
190 * @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 +0200191 * 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 +0200192 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
193 * @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 +0200194 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200195 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200196 *
197 * @return LY_ERR values.
198 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200199static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200200buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
201 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200202{
Radek Krejci404251e2018-10-09 12:06:44 +0200203 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200204 unsigned int c;
205 size_t len;
206
207 /* get UTF8 code point (and number of bytes coding the character) */
208 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
209 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
210 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200211 if (c == '\n') {
212 ctx->indent = 0;
213 } else {
214 /* note - even the multibyte character is count as 1 */
215 ++ctx->indent;
216 }
217
Radek Krejci44ceedc2018-10-02 15:54:31 +0200218 /* check character validity */
219 switch (arg) {
220 case Y_IDENTIF_ARG:
221 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
222 break;
223 case Y_PREF_IDENTIF_ARG:
224 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
225 break;
226 case Y_STR_ARG:
227 case Y_MAYBE_STR_ARG:
228 LY_CHECK_RET(check_stringchar(ctx, c));
229 break;
230 }
231
Michal Vasko7fbc8162018-09-17 10:35:16 +0200232 if (word_b && *word_b) {
233 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200234 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200235 return LY_EMEM;
236 }
237
238 /* in case of realloc */
239 *word_p = *word_b;
240 } else if (need_buf) {
241 /* first time we need a buffer, copy everything read up to now */
242 if (*word_len) {
243 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200244 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200245 *buf_len = *word_len;
246 memcpy(*word_b, *word_p, *word_len);
247 }
248
249 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200250 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200251 return LY_EMEM;
252 }
253
254 /* in case of realloc */
255 *word_p = *word_b;
256 } else {
257 /* just remember the first character pointer */
258 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200259 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200260 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200261 /* ... and update the word's length */
262 (*word_len) += len;
263 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200264 }
265
266 return LY_SUCCESS;
267}
268
Michal Vaskoea5abea2018-09-18 13:10:54 +0200269/**
270 * @brief Skip YANG comment in data.
271 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200272 * @param[in] ctx yang parser context for logging.
273 * @param[in,out] data Data to read from, automatically moved after the comment.
274 * @param[in] comment Type of the comment to process:
275 * 1 for a one-line comment,
276 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200277 *
278 * @return LY_ERR values.
279 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200280static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200281skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200282{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200283 /* internal statuses: 0 - comment ended,
284 * 1 - in line comment,
285 * 2 - in block comment,
286 * 3 - in block comment with last read character '*'
287 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200288 while (**data && comment) {
289 switch (comment) {
290 case 1:
291 if (**data == '\n') {
292 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200293 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200294 }
295 break;
296 case 2:
297 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200298 comment = 3;
299 } else if (**data == '\n') {
300 ++ctx->line;
301 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200302 break;
303 case 3:
304 if (**data == '/') {
305 comment = 0;
306 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200307 if (**data == '\n') {
308 ++ctx->line;
309 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200310 comment = 2;
311 }
312 break;
313 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200314 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200315 }
316
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200317 if (**data == '\n') {
318 ctx->indent = 0;
319 } else {
320 ++ctx->indent;
321 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200322 ++(*data);
323 }
324
325 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200326 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200327 return LY_EVALID;
328 }
329
330 return LY_SUCCESS;
331}
332
Michal Vaskoea5abea2018-09-18 13:10:54 +0200333/**
334 * @brief Read a quoted string from data.
335 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200336 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200337 * @param[in,out] data Data to read from, always moved to currently handled character.
338 * @param[in] arg Type of YANG keyword argument expected.
339 * @param[out] word_p Pointer to the read quoted string.
340 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
341 * set to NULL. Otherwise equal to \p word_p.
342 * @param[out] word_len Length of the read quoted string.
343 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
344 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
345 * indenation in the final quoted string.
346 *
347 * @return LY_ERR values.
348 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200349static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200350read_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 +0200351 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200352{
353 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
354 * 4 - string finished, now skipping whitespaces looking for +,
355 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200356 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200357 const char *c;
358
359 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200360 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200361 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200362 } else {
363 assert(**data == '\'');
364 string = 1;
365 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200366 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200367
368 while (**data && string) {
369 switch (string) {
370 case 1:
371 switch (**data) {
372 case '\'':
373 /* string may be finished, but check for + */
374 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200375 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200376 break;
377 default:
378 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200379 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 +0200380 break;
381 }
382 break;
383 case 2:
384 switch (**data) {
385 case '\"':
386 /* string may be finished, but check for + */
387 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200388 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200389 break;
390 case '\\':
391 /* special character following */
392 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200393 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200394 break;
395 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200396 if (current_indent < block_indent) {
397 ++current_indent;
398 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200399 } else {
400 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200401 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 +0200402 }
403 break;
404 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200405 if (current_indent < block_indent) {
406 assert(need_buf);
407 current_indent += 8;
408 ctx->indent += 8;
409 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
410 /* store leftover spaces from the tab */
411 c = " ";
412 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 +0200413 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200414 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200415 } else {
416 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200417 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 +0200418 /* additional characters for indentation - only 1 was count in buf_store_char */
419 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200420 }
421 break;
422 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200423 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200424 /* we will be removing the indents so we need our own buffer */
425 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200426
427 /* remove trailing tabs and spaces */
428 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
429 --(*word_len);
430 }
431
432 /* start indentation */
433 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200434 }
435
436 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200437 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
438
439 /* maintain line number */
440 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200441
442 /* reset context indentation counter for possible string after this one */
443 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200444 break;
445 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200446 /* first non-whitespace character, stop eating indentation */
447 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200448
449 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200450 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 +0200451 break;
452 }
453 break;
454 case 3:
455 /* string encoded characters */
456 switch (**data) {
457 case 'n':
458 c = "\n";
459 break;
460 case 't':
461 c = "\t";
462 break;
463 case '\"':
464 c = *data;
465 break;
466 case '\\':
467 c = *data;
468 break;
469 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200470 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200471 return LY_EVALID;
472 }
473
474 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200475 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 +0200476
477 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200478 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200479 break;
480 case 4:
481 switch (**data) {
482 case '+':
483 /* string continues */
484 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200485 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200486 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200487 case '\n':
488 ++ctx->line;
489 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200490 case ' ':
491 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200492 /* just skip */
493 break;
494 default:
495 /* string is finished */
496 goto string_end;
497 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200498 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200499 break;
500 case 5:
501 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200502 case '\n':
503 ++ctx->line;
504 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200505 case ' ':
506 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200507 /* skip */
508 break;
509 case '\'':
510 string = 1;
511 break;
512 case '\"':
513 string = 2;
514 break;
515 default:
516 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200517 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200518 return LY_EVALID;
519 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200520 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200521 break;
522 default:
523 return LY_EINT;
524 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200525 }
526
527string_end:
528 return LY_SUCCESS;
529}
530
Michal Vaskoea5abea2018-09-18 13:10:54 +0200531/**
532 * @brief Get another YANG string from the raw data.
533 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200534 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200535 * @param[in,out] data Data to read from, always moved to currently handled character.
536 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200537 * @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 +0200538 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
539 * set to NULL. Otherwise equal to \p word_p.
540 * @param[out] word_len Length of the read string.
541 *
542 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200543 */
544static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200545get_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 +0200546{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200547 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200548
549 /* word buffer - dynamically allocated */
550 *word_b = NULL;
551
552 /* word pointer - just a pointer to data */
553 *word_p = NULL;
554
555 *word_len = 0;
556 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200557 switch (**data) {
558 case '\'':
559 case '\"':
560 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200561 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
562 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
563 "unquoted string character, optsep, semicolon or opening brace");
564 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200565 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100566 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200567 goto str_end;
568 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200569 if ((*data)[1] == '/') {
570 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200571 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100572 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200573 } else if ((*data)[1] == '*') {
574 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200575 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100576 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200577 } else {
578 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100579 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 +0200580 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200581 break;
582 case ' ':
583 if (*word_len) {
584 /* word is finished */
585 goto str_end;
586 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200587 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200588 break;
589 case '\t':
590 if (*word_len) {
591 /* word is finished */
592 goto str_end;
593 }
594 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200595 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200596
597 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200598 break;
599 case '\n':
600 if (*word_len) {
601 /* word is finished */
602 goto str_end;
603 }
604 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200605 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200606
607 /* track line numbers */
608 ++ctx->line;
609
610 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200611 break;
612 case ';':
613 case '{':
614 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
615 /* word is finished */
616 goto str_end;
617 }
618
Radek Krejci44ceedc2018-10-02 15:54:31 +0200619 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200620 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200621 case '}':
622 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
623 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
624 "unquoted string character, optsep, semicolon or opening brace");
625 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200626 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200627 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 +0200628 break;
629 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200630 }
631
632str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200633 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200634 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200635 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
636 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
637 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200638 *word_p = *word_b;
639 }
640
641 return LY_SUCCESS;
642}
643
Michal Vaskoea5abea2018-09-18 13:10:54 +0200644/**
645 * @brief Get another YANG keyword from the raw data.
646 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200647 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200648 * @param[in,out] data Data to read from, always moved to currently handled character.
649 * @param[out] kw YANG keyword read.
650 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
651 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
652 *
653 * @return LY_ERR values.
654 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200655static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200656get_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 +0200657{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200658 int prefix;
659 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200660 unsigned int c;
661 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200662
663 if (word_p) {
664 *word_p = NULL;
665 *word_len = 0;
666 }
667
668 /* first skip "optsep", comments */
669 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200670 switch (**data) {
671 case '/':
672 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200673 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200674 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100675 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200676 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200677 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200678 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100679 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200680 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200681 /* error - not a comment after all, keyword cannot start with slash */
682 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
683 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200684 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200685 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200686 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200687 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200688 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200689 ctx->indent = 0;
690 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200691 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200692 /* skip whitespaces (optsep) */
693 ++ctx->indent;
694 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200695 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200696 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200697 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200698 break;
699 default:
700 /* either a keyword start or an invalid character */
701 goto keyword_start;
702 }
703
704 ++(*data);
705 }
706
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200707#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
708#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
709#define IF_KW_PREFIX_END }
710
Michal Vasko7fbc8162018-09-17 10:35:16 +0200711keyword_start:
712 word_start = *data;
713 *kw = YANG_NONE;
714
715 /* read the keyword itself */
716 switch (**data) {
717 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200718 MOVE_INPUT(ctx, data, 1);
719 IF_KW("rgument", 7, YANG_ARGUMENT)
720 else IF_KW("ugment", 6, YANG_AUGMENT)
721 else IF_KW("ction", 5, YANG_ACTION)
722 else IF_KW_PREFIX("ny", 2)
723 IF_KW("data", 4, YANG_ANYDATA)
724 else IF_KW("xml", 3, YANG_ANYXML)
725 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200726 break;
727 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200728 MOVE_INPUT(ctx, data, 1);
729 IF_KW("ase", 3, YANG_BASE)
730 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
731 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200732 break;
733 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200734 MOVE_INPUT(ctx, data, 1);
735 IF_KW("ase", 3, YANG_CASE)
736 else IF_KW("hoice", 5, YANG_CHOICE)
737 else IF_KW_PREFIX("on", 2)
738 IF_KW("fig", 3, YANG_CONFIG)
739 else IF_KW_PREFIX("ta", 2)
740 IF_KW("ct", 2, YANG_CONTACT)
741 else IF_KW("iner", 4, YANG_CONTAINER)
742 IF_KW_PREFIX_END
743 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200744 break;
745 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200746 MOVE_INPUT(ctx, data, 1);
747 IF_KW_PREFIX("e", 1)
748 IF_KW("fault", 5, YANG_DEFAULT)
749 else IF_KW("scription", 9, YANG_DESCRIPTION)
750 else IF_KW_PREFIX("viat", 4)
751 IF_KW("e", 1, YANG_DEVIATE)
752 else IF_KW("ion", 3, YANG_DEVIATION)
753 IF_KW_PREFIX_END
754 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200755 break;
756 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200757 MOVE_INPUT(ctx, data, 1);
758 IF_KW("num", 3, YANG_ENUM)
759 else IF_KW_PREFIX("rror-", 5)
760 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
761 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
762 IF_KW_PREFIX_END
763 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200764 break;
765 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200766 MOVE_INPUT(ctx, data, 1);
767 IF_KW("eature", 6, YANG_FEATURE)
768 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200769 break;
770 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200771 MOVE_INPUT(ctx, data, 1);
772 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200773 break;
774 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200775 MOVE_INPUT(ctx, data, 1);
776 IF_KW("dentity", 7, YANG_IDENTITY)
777 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
778 else IF_KW("mport", 5, YANG_IMPORT)
779 else IF_KW_PREFIX("n", 1)
780 IF_KW("clude", 5, YANG_INCLUDE)
781 else IF_KW("put", 3, YANG_INPUT)
782 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200783 break;
784 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200785 MOVE_INPUT(ctx, data, 1);
786 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200787 break;
788 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200789 MOVE_INPUT(ctx, data, 1);
790 IF_KW_PREFIX("e", 1)
791 IF_KW("af-list", 7, YANG_LEAF_LIST)
792 else IF_KW("af", 2, YANG_LEAF)
793 else IF_KW("ngth", 4, YANG_LENGTH)
794 IF_KW_PREFIX_END
795 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200796 break;
797 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200798 MOVE_INPUT(ctx, data, 1);
799 IF_KW_PREFIX("a", 1)
800 IF_KW("ndatory", 7, YANG_MANDATORY)
801 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
802 IF_KW_PREFIX_END
803 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
804 else IF_KW("ust", 3, YANG_MUST)
805 else IF_KW_PREFIX("od", 2)
806 IF_KW("ule", 3, YANG_MODULE)
807 else IF_KW("ifier", 5, YANG_MODIFIER)
808 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200809 break;
810 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200811 MOVE_INPUT(ctx, data, 1);
812 IF_KW("amespace", 8, YANG_NAMESPACE)
813 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200814 break;
815 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200816 MOVE_INPUT(ctx, data, 1);
817 IF_KW_PREFIX("r", 1)
818 IF_KW("dered-by", 8, YANG_ORDERED_BY)
819 else IF_KW("ganization", 10, YANG_ORGANIZATION)
820 IF_KW_PREFIX_END
821 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200822 break;
823 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200824 MOVE_INPUT(ctx, data, 1);
825 IF_KW("ath", 3, YANG_PATH)
826 else IF_KW("attern", 6, YANG_PATTERN)
827 else IF_KW("osition", 7, YANG_POSITION)
828 else IF_KW_PREFIX("re", 2)
829 IF_KW("fix", 3, YANG_PREFIX)
830 else IF_KW("sence", 5, YANG_PRESENCE)
831 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200832 break;
833 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200834 MOVE_INPUT(ctx, data, 1);
835 IF_KW("ange", 4, YANG_RANGE)
836 else IF_KW_PREFIX("e", 1)
837 IF_KW_PREFIX("f", 1)
838 IF_KW("erence", 6, YANG_REFERENCE)
839 else IF_KW("ine", 3, YANG_REFINE)
840 IF_KW_PREFIX_END
841 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
842 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
843 else IF_KW("vision", 6, YANG_REVISION)
844 IF_KW_PREFIX_END
845 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200846 break;
847 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200848 MOVE_INPUT(ctx, data, 1);
849 IF_KW("tatus", 5, YANG_STATUS)
850 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200851 break;
852 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200853 MOVE_INPUT(ctx, data, 1);
854 IF_KW("ypedef", 6, YANG_TYPEDEF)
855 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200856 break;
857 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200858 MOVE_INPUT(ctx, data, 1);
859 IF_KW_PREFIX("ni", 2)
860 IF_KW("que", 3, YANG_UNIQUE)
861 else IF_KW("ts", 2, YANG_UNITS)
862 IF_KW_PREFIX_END
863 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200864 break;
865 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200866 MOVE_INPUT(ctx, data, 1);
867 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200868 break;
869 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200870 MOVE_INPUT(ctx, data, 1);
871 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200872 break;
873 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200874 MOVE_INPUT(ctx, data, 1);
875 IF_KW("ang-version", 11, YANG_YANG_VERSION)
876 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200877 break;
878 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200879 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200880 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200881 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200882 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200883 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200884 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200885 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200886 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200887 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200888 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200889 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200890 default:
891 break;
892 }
893
894 if (*kw != YANG_NONE) {
895 /* make sure we have the whole keyword */
896 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200897 case '\n':
898 ++ctx->line;
899 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200900 case ' ':
901 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200902 /* mandatory "sep" */
903 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200904 case ':':
905 /* keyword is not actually a keyword, but prefix of an extension.
906 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
907 * and we will be checking the keyword (extension instance) itself */
908 prefix = 1;
909 MOVE_INPUT(ctx, data, 1);
910 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200911 case '{':
912 /* allowed only for input and output statements which can be without arguments */
913 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
914 break;
915 }
916 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200917 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200918 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200919 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
920 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200921 return LY_EVALID;
922 }
923 } else {
924 /* still can be an extension */
925 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200926extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200927 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200928 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
929 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200930 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200931 /* check character validity */
932 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200933 }
934 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200935 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200936 return LY_EVALID;
937 }
938
939 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200940 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200941 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200942 return LY_EVALID;
943 }
944
945 *kw = YANG_CUSTOM;
946 }
Radek Krejci626df482018-10-11 15:06:31 +0200947success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200948 if (word_p) {
949 *word_p = (char *)word_start;
950 *word_len = *data - word_start;
951 }
952
953 return LY_SUCCESS;
954}
955
Michal Vaskoea5abea2018-09-18 13:10:54 +0200956/**
957 * @brief Parse extension instance substatements.
958 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200959 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200960 * @param[in,out] data Data to read from, always moved to currently handled character.
961 * @param[in] word Extension instance substatement name (keyword).
962 * @param[in] word_len Extension instance substatement name length.
963 * @param[in,out] child Children of this extension instance to add to.
964 *
965 * @return LY_ERR values.
966 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200967static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200968parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200969 struct lysp_stmt **child)
970{
971 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100972 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200973 enum yang_keyword kw;
974 struct lysp_stmt *stmt, *par_child;
975
976 stmt = calloc(1, sizeof *stmt);
977 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
978
Radek Krejci44ceedc2018-10-02 15:54:31 +0200979 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200980
981 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100982 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200983
Radek Krejci0ae092d2018-09-20 16:43:19 +0200984 if (word) {
985 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200986 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200987 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200988 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200989 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200990 }
991
992 /* insert into parent statements */
993 if (!*child) {
994 *child = stmt;
995 } else {
996 for (par_child = *child; par_child->next; par_child = par_child->next);
997 par_child->next = stmt;
998 }
999
1000 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001001 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001002 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001003 return ret;
1004}
1005
Michal Vaskoea5abea2018-09-18 13:10:54 +02001006/**
1007 * @brief Parse extension instance.
1008 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001009 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001010 * @param[in,out] data Data to read from, always moved to currently handled character.
1011 * @param[in] ext_name Extension instance substatement name (keyword).
1012 * @param[in] ext_name_len Extension instance substatement name length.
1013 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1014 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1015 * @param[in,out] exts Extension instances to add to.
1016 *
1017 * @return LY_ERR values.
1018 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001019static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001020parse_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 +02001021 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1022{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001023 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001024 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001025 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001026 struct lysp_ext_instance *e;
1027 enum yang_keyword kw;
1028
Radek Krejci2c4e7172018-10-19 15:56:26 +02001029 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001030
1031 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001032 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001033 e->insubstmt = insubstmt;
1034 e->insubstmt_index = insubstmt_index;
1035
1036 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001037 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001038
Radek Krejci0ae092d2018-09-20 16:43:19 +02001039 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001040 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001041 }
1042
1043 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001044 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001045 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001046 return ret;
1047}
1048
Michal Vaskoea5abea2018-09-18 13:10:54 +02001049/**
1050 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1051 * description, etc...
1052 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001053 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001054 * @param[in,out] data Data to read from, always moved to currently handled character.
1055 * @param[in] substmt Type of this substatement.
1056 * @param[in] substmt_index Index of this substatement.
1057 * @param[in,out] value Place to store the parsed value.
1058 * @param[in] arg Type of the YANG keyword argument (of the value).
1059 * @param[in,out] exts Extension instances to add to.
1060 *
1061 * @return LY_ERR values.
1062 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001063static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001064parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001065 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1066{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001067 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001068 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001069 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001070 enum yang_keyword kw;
1071
1072 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001073 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001074 return LY_EVALID;
1075 }
1076
1077 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001078 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001079
1080 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001081 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001082
1083 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001084 switch (kw) {
1085 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001086 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001087 break;
1088 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001089 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001090 return LY_EVALID;
1091 }
1092 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001093 return ret;
1094}
1095
Michal Vaskoea5abea2018-09-18 13:10:54 +02001096/**
1097 * @brief Parse the yang-version statement.
1098 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001099 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001100 * @param[in,out] data Data to read from, always moved to currently handled character.
1101 * @param[in] mod Module to store the parsed information in.
1102 *
1103 * @return LY_ERR values.
1104 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001105static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001106parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001107{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001108 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001109 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001110 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001111 enum yang_keyword kw;
1112
1113 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001114 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001115 return LY_EVALID;
1116 }
1117
1118 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001119 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001120
1121 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1122 mod->version = LYS_VERSION_1_0;
1123 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1124 mod->version = LYS_VERSION_1_1;
1125 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001126 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001127 free(buf);
1128 return LY_EVALID;
1129 }
1130 free(buf);
1131
1132 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001133 switch (kw) {
1134 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001135 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001136 break;
1137 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001138 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001139 return LY_EVALID;
1140 }
1141 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001142 return ret;
1143}
1144
Michal Vaskoea5abea2018-09-18 13:10:54 +02001145/**
1146 * @brief Parse the belongs-to statement.
1147 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001148 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001149 * @param[in,out] data Data to read from, always moved to currently handled character.
1150 * @param[in,out] belongsto Place to store the parsed value.
1151 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1152 * @param[in,out] exts Extension instances to add to.
1153 *
1154 * @return LY_ERR values.
1155 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001156static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001157parse_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 +02001158{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001159 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001160 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001161 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001162 enum yang_keyword kw;
1163
1164 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001165 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001166 return LY_EVALID;
1167 }
1168
1169 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001170 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001171
Radek Krejci44ceedc2018-10-02 15:54:31 +02001172 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001173 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001174 switch (kw) {
1175 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001176 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001177 break;
1178 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001179 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001180 break;
1181 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001182 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001183 return LY_EVALID;
1184 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001185 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001186 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001187
1188 /* mandatory substatements */
1189 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001190 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001191 return LY_EVALID;
1192 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001193 return ret;
1194}
1195
Michal Vaskoea5abea2018-09-18 13:10:54 +02001196/**
1197 * @brief Parse the revision-date statement.
1198 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001199 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001200 * @param[in,out] data Data to read from, always moved to currently handled character.
1201 * @param[in,out] rev Array to store the parsed value in.
1202 * @param[in,out] exts Extension instances to add to.
1203 *
1204 * @return LY_ERR values.
1205 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001206static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001207parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001208{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001209 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001210 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001211 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001212 enum yang_keyword kw;
1213
1214 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001215 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001216 return LY_EVALID;
1217 }
1218
1219 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001220 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001221
1222 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001223 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001224 free(buf);
1225 return LY_EVALID;
1226 }
1227
1228 /* store value and spend buf if allocated */
1229 strncpy(rev, word, word_len);
1230 free(buf);
1231
1232 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001233 switch (kw) {
1234 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001235 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001236 break;
1237 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001238 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001239 return LY_EVALID;
1240 }
1241 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001242 return ret;
1243}
1244
Michal Vaskoea5abea2018-09-18 13:10:54 +02001245/**
1246 * @brief Parse the include statement.
1247 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001248 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001249 * @param[in,out] data Data to read from, always moved to currently handled character.
1250 * @param[in,out] includes Parsed includes to add to.
1251 *
1252 * @return LY_ERR values.
1253 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001254static LY_ERR
Radek Krejcid33273d2018-10-25 14:55:52 +02001255parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001256{
Radek Krejcid33273d2018-10-25 14:55:52 +02001257 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001258 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001259 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001260 enum yang_keyword kw;
1261 struct lysp_include *inc;
1262
Radek Krejcid33273d2018-10-25 14:55:52 +02001263 LY_ARRAY_NEW_RET(ctx->ctx, mod->includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001264
1265 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001266 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001267
Radek Krejci086c7132018-10-26 15:29:04 +02001268 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1269
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001270 /* submodules share the namespace with the module names, so there must not be
1271 * a module of the same name in the context, no need for revision matching */
1272 if (!strcmp(ctx->mod->name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
1273 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1274 return LY_EVALID;
1275 }
1276
Radek Krejci086c7132018-10-26 15:29:04 +02001277 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001278 switch (kw) {
1279 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001280 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 +02001281 break;
1282 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001283 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 +02001284 break;
1285 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001286 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001287 break;
1288 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001289 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001290 break;
1291 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001292 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001293 return LY_EVALID;
1294 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001295 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001296 return ret;
1297}
1298
Michal Vaskoea5abea2018-09-18 13:10:54 +02001299/**
1300 * @brief Parse the import statement.
1301 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001302 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001303 * @param[in,out] data Data to read from, always moved to currently handled character.
1304 * @param[in,out] imports Parsed imports to add to.
1305 *
1306 * @return LY_ERR values.
1307 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001308static LY_ERR
Radek Krejci70853c52018-10-15 14:46:16 +02001309parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *module)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001310{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001311 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001312 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001313 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001314 enum yang_keyword kw;
1315 struct lysp_import *imp;
1316
Radek Krejci2c4e7172018-10-19 15:56:26 +02001317 LY_ARRAY_NEW_RET(ctx->ctx, module->imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001318
1319 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001320 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001321 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001322
Radek Krejci086c7132018-10-26 15:29:04 +02001323 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001324 switch (kw) {
1325 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001326 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 +02001327 LY_CHECK_RET(lysp_check_prefix(ctx, module, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001328 break;
1329 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001330 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 +02001331 break;
1332 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001333 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 +02001334 break;
1335 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001336 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001337 break;
1338 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001339 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001340 break;
1341 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001342 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001343 return LY_EVALID;
1344 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001345 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001346 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001347
1348 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001349 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001350
1351 return ret;
1352}
1353
Michal Vaskoea5abea2018-09-18 13:10:54 +02001354/**
1355 * @brief Parse the revision statement.
1356 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001357 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001358 * @param[in,out] data Data to read from, always moved to currently handled character.
1359 * @param[in,out] revs Parsed revisions to add to.
1360 *
1361 * @return LY_ERR values.
1362 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001363static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001364parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001365{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001366 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001367 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001368 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001369 enum yang_keyword kw;
1370 struct lysp_revision *rev;
1371
Radek Krejci2c4e7172018-10-19 15:56:26 +02001372 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001373
1374 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001375 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001376
1377 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001378 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001379 return LY_EVALID;
1380 }
1381
Radek Krejcib7db73a2018-10-24 14:18:40 +02001382 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001383 free(buf);
1384
1385 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001386 switch (kw) {
1387 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001388 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 +02001389 break;
1390 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001391 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 +02001392 break;
1393 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001394 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001395 break;
1396 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001397 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001398 return LY_EVALID;
1399 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001400 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001401 return ret;
1402}
1403
Michal Vaskoea5abea2018-09-18 13:10:54 +02001404/**
1405 * @brief Parse a generic text field that can have more instances such as base.
1406 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001407 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001408 * @param[in,out] data Data to read from, always moved to currently handled character.
1409 * @param[in] substmt Type of this substatement.
1410 * @param[in,out] texts Parsed values to add to.
1411 * @param[in] arg Type of the expected argument.
1412 * @param[in,out] exts Extension instances to add to.
1413 *
1414 * @return LY_ERR values.
1415 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001416static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001417parse_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 +02001418 struct lysp_ext_instance **exts)
1419{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001420 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001421 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001422 const char **item;
1423 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001424 enum yang_keyword kw;
1425
1426 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001427 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001428
1429 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001430 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001431
Radek Krejci151a5b72018-10-19 14:21:44 +02001432 INSERT_WORD(ctx, buf, *item, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001433 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001434 switch (kw) {
1435 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001436 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001437 break;
1438 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001439 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001440 return LY_EVALID;
1441 }
1442 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001443 return ret;
1444}
1445
Michal Vaskoea5abea2018-09-18 13:10:54 +02001446/**
1447 * @brief Parse the config statement.
1448 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001449 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001450 * @param[in,out] data Data to read from, always moved to currently handled character.
1451 * @param[in,out] flags Flags to add to.
1452 * @param[in,out] exts Extension instances to add to.
1453 *
1454 * @return LY_ERR values.
1455 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001456static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001457parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001458{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001459 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001460 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001461 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001462 enum yang_keyword kw;
1463
1464 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001465 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001466 return LY_EVALID;
1467 }
1468
1469 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001470 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001471
1472 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1473 *flags |= LYS_CONFIG_W;
1474 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1475 *flags |= LYS_CONFIG_R;
1476 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001477 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001478 free(buf);
1479 return LY_EVALID;
1480 }
1481 free(buf);
1482
1483 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001484 switch (kw) {
1485 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001486 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001487 break;
1488 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001489 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001490 return LY_EVALID;
1491 }
1492 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001493 return ret;
1494}
1495
Michal Vaskoea5abea2018-09-18 13:10:54 +02001496/**
1497 * @brief Parse the mandatory statement.
1498 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001499 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001500 * @param[in,out] data Data to read from, always moved to currently handled character.
1501 * @param[in,out] flags Flags to add to.
1502 * @param[in,out] exts Extension instances to add to.
1503 *
1504 * @return LY_ERR values.
1505 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001506static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001507parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001508{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001509 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001510 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001511 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001512 enum yang_keyword kw;
1513
1514 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001515 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001516 return LY_EVALID;
1517 }
1518
1519 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001520 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001521
1522 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1523 *flags |= LYS_MAND_TRUE;
1524 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1525 *flags |= LYS_MAND_FALSE;
1526 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001527 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001528 free(buf);
1529 return LY_EVALID;
1530 }
1531 free(buf);
1532
1533 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001534 switch (kw) {
1535 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001536 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001537 break;
1538 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001539 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001540 return LY_EVALID;
1541 }
1542 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001543 return ret;
1544}
1545
Michal Vaskoea5abea2018-09-18 13:10:54 +02001546/**
1547 * @brief Parse a restriction such as range or length.
1548 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001549 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001550 * @param[in,out] data Data to read from, always moved to currently handled character.
1551 * @param[in] restr_kw Type of this particular restriction.
1552 * @param[in,out] exts Extension instances to add to.
1553 *
1554 * @return LY_ERR values.
1555 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001556static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001557parse_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 +02001558{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001559 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001560 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001561 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001562 enum yang_keyword kw;
1563
1564 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001565 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001566
Radek Krejci44ceedc2018-10-02 15:54:31 +02001567 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001568 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001569 switch (kw) {
1570 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001571 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 +02001572 break;
1573 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001574 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 +02001575 break;
1576 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001577 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 +02001578 break;
1579 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001580 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 +02001581 break;
1582 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001583 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001584 break;
1585 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001586 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001587 return LY_EVALID;
1588 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001589 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001590 return ret;
1591}
1592
Michal Vaskoea5abea2018-09-18 13:10:54 +02001593/**
1594 * @brief Parse a restriction that can have more instances such as must.
1595 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001596 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001597 * @param[in,out] data Data to read from, always moved to currently handled character.
1598 * @param[in] restr_kw Type of this particular restriction.
1599 * @param[in,out] restrs Restrictions to add to.
1600 *
1601 * @return LY_ERR values.
1602 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001603static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001604parse_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 +02001605{
1606 struct lysp_restr *restr;
1607
Radek Krejci2c4e7172018-10-19 15:56:26 +02001608 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001609 return parse_restr(ctx, data, restr_kw, restr);
1610}
1611
Michal Vaskoea5abea2018-09-18 13:10:54 +02001612/**
1613 * @brief Parse the status statement.
1614 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001615 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001616 * @param[in,out] data Data to read from, always moved to currently handled character.
1617 * @param[in,out] flags Flags to add to.
1618 * @param[in,out] exts Extension instances to add to.
1619 *
1620 * @return LY_ERR values.
1621 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001622static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001623parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001624{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001625 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001626 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001627 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001628 enum yang_keyword kw;
1629
1630 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001631 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001632 return LY_EVALID;
1633 }
1634
1635 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001636 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001637
1638 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1639 *flags |= LYS_STATUS_CURR;
1640 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1641 *flags |= LYS_STATUS_DEPRC;
1642 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1643 *flags |= LYS_STATUS_OBSLT;
1644 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001645 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001646 free(buf);
1647 return LY_EVALID;
1648 }
1649 free(buf);
1650
1651 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001652 switch (kw) {
1653 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001654 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001655 break;
1656 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001657 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001658 return LY_EVALID;
1659 }
1660 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001661 return ret;
1662}
1663
Michal Vaskoea5abea2018-09-18 13:10:54 +02001664/**
1665 * @brief Parse the when statement.
1666 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001667 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001668 * @param[in,out] data Data to read from, always moved to currently handled character.
1669 * @param[in,out] when_p When pointer to parse to.
1670 *
1671 * @return LY_ERR values.
1672 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001673static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001674parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001675{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001676 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001677 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001678 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001679 enum yang_keyword kw;
1680 struct lysp_when *when;
1681
1682 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001683 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001684 return LY_EVALID;
1685 }
1686
1687 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001688 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001689 *when_p = when;
1690
1691 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001692 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001693 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001694
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001695 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001696 switch (kw) {
1697 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001698 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 +02001699 break;
1700 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001701 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 +02001702 break;
1703 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001704 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001705 break;
1706 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001707 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001708 return LY_EVALID;
1709 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001710 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001711 return ret;
1712}
1713
Michal Vaskoea5abea2018-09-18 13:10:54 +02001714/**
1715 * @brief Parse the anydata or anyxml statement.
1716 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001717 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001718 * @param[in,out] data Data to read from, always moved to currently handled character.
1719 * @param[in] kw Type of this particular keyword.
1720 * @param[in,out] siblings Siblings to add to.
1721 *
1722 * @return LY_ERR values.
1723 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001724static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001725parse_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 +02001726{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001727 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001728 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001729 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001730 struct lysp_node *iter;
1731 struct lysp_node_anydata *any;
1732
1733 /* create structure */
1734 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001735 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001736 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001737 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001738
1739 /* insert into siblings */
1740 if (!*siblings) {
1741 *siblings = (struct lysp_node *)any;
1742 } else {
1743 for (iter = *siblings; iter->next; iter = iter->next);
1744 iter->next = (struct lysp_node *)any;
1745 }
1746
1747 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001748 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001749 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001750
1751 /* parse substatements */
1752 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001753 switch (kw) {
1754 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001755 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001756 break;
1757 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001758 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 +02001759 break;
1760 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001761 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 +02001762 break;
1763 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001764 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001765 break;
1766 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001767 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001768 break;
1769 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001770 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 +02001771 break;
1772 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001773 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001774 break;
1775 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001776 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001777 break;
1778 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001779 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001780 break;
1781 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001782 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001783 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001784 return LY_EVALID;
1785 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001786 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001787 return ret;
1788}
1789
Michal Vaskoea5abea2018-09-18 13:10:54 +02001790/**
1791 * @brief Parse the value or position statement. Substatement of type enum statement.
1792 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001793 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001794 * @param[in,out] data Data to read from, always moved to currently handled character.
1795 * @param[in] val_kw Type of this particular keyword.
1796 * @param[in,out] value Value to write to.
1797 * @param[in,out] flags Flags to write to.
1798 * @param[in,out] exts Extension instances to add to.
1799 *
1800 * @return LY_ERR values.
1801 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001802static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001803parse_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 +02001804 struct lysp_ext_instance **exts)
1805{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001806 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001807 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001808 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001809 long int num;
1810 unsigned long int unum;
1811 enum yang_keyword kw;
1812
1813 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001814 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001815 return LY_EVALID;
1816 }
1817 *flags |= LYS_SET_VALUE;
1818
1819 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001820 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001821
1822 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 +02001823 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001824 free(buf);
1825 return LY_EVALID;
1826 }
1827
1828 errno = 0;
1829 if (val_kw == YANG_VALUE) {
1830 num = strtol(word, &ptr, 10);
1831 } else {
1832 unum = strtoul(word, &ptr, 10);
1833 }
1834 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001835 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001836 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001837 free(buf);
1838 return LY_EVALID;
1839 }
1840 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001841 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001842 free(buf);
1843 return LY_EVALID;
1844 }
1845 if (val_kw == YANG_VALUE) {
1846 *value = num;
1847 } else {
1848 *value = unum;
1849 }
1850 free(buf);
1851
1852 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001853 switch (kw) {
1854 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001855 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 +02001856 break;
1857 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001858 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001859 return LY_EVALID;
1860 }
1861 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001862 return ret;
1863}
1864
Michal Vaskoea5abea2018-09-18 13:10:54 +02001865/**
1866 * @brief Parse the enum or bit statement. Substatement of type statement.
1867 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001868 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001869 * @param[in,out] data Data to read from, always moved to currently handled character.
1870 * @param[in] enum_kw Type of this particular keyword.
1871 * @param[in,out] enums Enums or bits to add to.
1872 *
1873 * @return LY_ERR values.
1874 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001875static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001876parse_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 +02001877{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001878 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001879 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001880 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001881 enum yang_keyword kw;
1882 struct lysp_type_enum *enm;
1883
Radek Krejci2c4e7172018-10-19 15:56:26 +02001884 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001885
1886 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001887 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001888 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001889
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001890 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001891 switch (kw) {
1892 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001893 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 +02001894 break;
1895 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001896 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 +02001897 break;
1898 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001899 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 +02001900 break;
1901 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001902 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001903 break;
1904 case YANG_VALUE:
1905 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001906 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001907 break;
1908 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001909 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001910 break;
1911 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001912 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001913 return LY_EVALID;
1914 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001915 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001916 return ret;
1917}
1918
Michal Vaskoea5abea2018-09-18 13:10:54 +02001919/**
1920 * @brief Parse the fraction-digits statement. Substatement of type statement.
1921 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001922 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001923 * @param[in,out] data Data to read from, always moved to currently handled character.
1924 * @param[in,out] fracdig Value to write to.
1925 * @param[in,out] exts Extension instances to add to.
1926 *
1927 * @return LY_ERR values.
1928 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001929static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001930parse_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 +02001931{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001932 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001933 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001934 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001935 unsigned long int num;
1936 enum yang_keyword kw;
1937
1938 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001939 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001940 return LY_EVALID;
1941 }
1942
1943 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001944 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001945
1946 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001947 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001948 free(buf);
1949 return LY_EVALID;
1950 }
1951
1952 errno = 0;
1953 num = strtoul(word, &ptr, 10);
1954 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001955 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001956 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001957 free(buf);
1958 return LY_EVALID;
1959 }
1960 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001961 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001962 free(buf);
1963 return LY_EVALID;
1964 }
1965 *fracdig = num;
1966 free(buf);
1967
1968 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001969 switch (kw) {
1970 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001971 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001972 break;
1973 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001974 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001975 return LY_EVALID;
1976 }
1977 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001978 return ret;
1979}
1980
Michal Vaskoea5abea2018-09-18 13:10:54 +02001981/**
1982 * @brief Parse the require-instance statement. Substatement of type statement.
1983 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001984 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001985 * @param[in,out] data Data to read from, always moved to currently handled character.
1986 * @param[in,out] reqinst Value to write to.
1987 * @param[in,out] flags Flags to write to.
1988 * @param[in,out] exts Extension instances to add to.
1989 *
1990 * @return LY_ERR values.
1991 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001992static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001993parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001994 struct lysp_ext_instance **exts)
1995{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001996 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001997 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001998 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001999 enum yang_keyword kw;
2000
2001 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002002 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002003 return LY_EVALID;
2004 }
2005 *flags |= LYS_SET_REQINST;
2006
2007 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002008 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002009
2010 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2011 *reqinst = 1;
2012 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002013 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002014 free(buf);
2015 return LY_EVALID;
2016 }
2017 free(buf);
2018
2019 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002020 switch (kw) {
2021 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002022 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002023 break;
2024 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002025 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002026 return LY_EVALID;
2027 }
2028 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002029 return ret;
2030}
2031
Michal Vaskoea5abea2018-09-18 13:10:54 +02002032/**
2033 * @brief Parse the modifier statement. Substatement of type pattern statement.
2034 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002035 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002036 * @param[in,out] data Data to read from, always moved to currently handled character.
2037 * @param[in,out] pat Value to write to.
2038 * @param[in,out] exts Extension instances to add to.
2039 *
2040 * @return LY_ERR values.
2041 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002042static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002043parse_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 +02002044{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002045 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002046 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002047 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002048 enum yang_keyword kw;
2049
2050 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002051 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002052 return LY_EVALID;
2053 }
2054
2055 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002056 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002057
2058 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002059 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002060 free(buf);
2061 return LY_EVALID;
2062 }
2063 free(buf);
2064
2065 /* replace the value in the dictionary */
2066 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002067 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002068 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002069 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002070
2071 assert(buf[0] == 0x06);
2072 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002073 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002074
2075 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002076 switch (kw) {
2077 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002078 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002079 break;
2080 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002081 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002082 return LY_EVALID;
2083 }
2084 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002085 return ret;
2086}
2087
Michal Vaskoea5abea2018-09-18 13:10:54 +02002088/**
2089 * @brief Parse the pattern statement. Substatement of type statement.
2090 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002091 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002092 * @param[in,out] data Data to read from, always moved to currently handled character.
2093 * @param[in,out] patterns Restrictions to add to.
2094 *
2095 * @return LY_ERR values.
2096 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002097static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002098parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002099{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002100 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002101 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002102 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002103 enum yang_keyword kw;
2104 struct lysp_restr *restr;
2105
Radek Krejci2c4e7172018-10-19 15:56:26 +02002106 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002107
2108 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002109 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002110
2111 /* add special meaning first byte */
2112 if (buf) {
2113 buf = realloc(buf, word_len + 2);
2114 word = buf;
2115 } else {
2116 buf = malloc(word_len + 2);
2117 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002118 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002119 memmove(buf + 1, word, word_len);
2120 buf[0] = 0x06; /* pattern's default regular-match flag */
2121 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2122 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002123
2124 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002125 switch (kw) {
2126 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002127 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 +02002128 break;
2129 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002130 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 +02002131 break;
2132 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002133 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 +02002134 break;
2135 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002136 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 +02002137 break;
2138 case YANG_MODIFIER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002139 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002140 break;
2141 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002142 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002143 break;
2144 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002145 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002146 return LY_EVALID;
2147 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002148 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002149 return ret;
2150}
2151
Michal Vaskoea5abea2018-09-18 13:10:54 +02002152/**
2153 * @brief Parse the type statement.
2154 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002155 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002156 * @param[in,out] data Data to read from, always moved to currently handled character.
2157 * @param[in,out] type Type to wrote to.
2158 *
2159 * @return LY_ERR values.
2160 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002161static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002162parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002163{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002164 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002165 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002166 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002167 enum yang_keyword kw;
2168 struct lysp_type *nest_type;
2169
2170 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002171 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002172 return LY_EVALID;
2173 }
2174
2175 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002176 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002177 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002178
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002179 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002180 switch (kw) {
2181 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002182 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 +02002183 break;
2184 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002185 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002186 break;
2187 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002188 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189 break;
2190 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002191 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002192 break;
2193 case YANG_LENGTH:
2194 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002195 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002196 return LY_EVALID;
2197 }
2198 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002199 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002200
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002201 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002202 break;
2203 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002204 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 +02002205 break;
2206 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002207 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002208 break;
2209 case YANG_RANGE:
2210 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002211 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002212 return LY_EVALID;
2213 }
2214 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002215 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002216
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002217 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002218 break;
2219 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002220 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002221 break;
2222 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002223 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2224 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002225 break;
2226 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002227 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002228 break;
2229 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002230 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002231 return LY_EVALID;
2232 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002233 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002234 return ret;
2235}
2236
Michal Vaskoea5abea2018-09-18 13:10:54 +02002237/**
2238 * @brief Parse the leaf statement.
2239 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002240 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002241 * @param[in,out] data Data to read from, always moved to currently handled character.
2242 * @param[in,out] siblings Siblings to add to.
2243 *
2244 * @return LY_ERR values.
2245 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002246static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002247parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002248{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002249 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002250 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002251 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002252 enum yang_keyword kw;
2253 struct lysp_node *iter;
2254 struct lysp_node_leaf *leaf;
2255
2256 /* create structure */
2257 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002258 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002259 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002260 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002261
2262 /* insert into siblings */
2263 if (!*siblings) {
2264 *siblings = (struct lysp_node *)leaf;
2265 } else {
2266 for (iter = *siblings; iter->next; iter = iter->next);
2267 iter->next = (struct lysp_node *)leaf;
2268 }
2269
2270 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002271 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002272 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002273
2274 /* parse substatements */
2275 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002276 switch (kw) {
2277 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002278 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002279 break;
2280 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002281 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 +02002282 break;
2283 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002284 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 +02002285 break;
2286 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002287 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 +02002288 break;
2289 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002290 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002291 break;
2292 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002293 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002294 break;
2295 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002296 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 +02002297 break;
2298 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002299 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002300 break;
2301 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002302 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002303 break;
2304 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002305 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 +02002306 break;
2307 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002308 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002309 break;
2310 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002311 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002312 break;
2313 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002314 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002315 return LY_EVALID;
2316 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002317 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002318 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002319
2320 /* mandatory substatements */
2321 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002322 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002323 return LY_EVALID;
2324 }
2325
2326 return ret;
2327}
2328
Michal Vaskoea5abea2018-09-18 13:10:54 +02002329/**
2330 * @brief Parse the max-elements statement.
2331 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002332 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002333 * @param[in,out] data Data to read from, always moved to currently handled character.
2334 * @param[in,out] max Value to write to.
2335 * @param[in,out] flags Flags to write to.
2336 * @param[in,out] exts Extension instances to add to.
2337 *
2338 * @return LY_ERR values.
2339 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002340static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002341parse_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 +02002342{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002343 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002344 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002345 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002346 unsigned long int num;
2347 enum yang_keyword kw;
2348
2349 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002350 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002351 return LY_EVALID;
2352 }
2353 *flags |= LYS_SET_MAX;
2354
2355 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002356 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002357
2358 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002359 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002360 free(buf);
2361 return LY_EVALID;
2362 }
2363
2364 if (strncmp(word, "unbounded", word_len)) {
2365 errno = 0;
2366 num = strtoul(word, &ptr, 10);
2367 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002368 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002369 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002370 free(buf);
2371 return LY_EVALID;
2372 }
2373 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002374 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002375 free(buf);
2376 return LY_EVALID;
2377 }
2378
2379 *max = num;
2380 }
2381 free(buf);
2382
2383 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002384 switch (kw) {
2385 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002386 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002387 break;
2388 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002389 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002390 return LY_EVALID;
2391 }
2392 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002393 return ret;
2394}
2395
Michal Vaskoea5abea2018-09-18 13:10:54 +02002396/**
2397 * @brief Parse the min-elements statement.
2398 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002399 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002400 * @param[in,out] data Data to read from, always moved to currently handled character.
2401 * @param[in,out] min Value to write to.
2402 * @param[in,out] flags Flags to write to.
2403 * @param[in,out] exts Extension instances to add to.
2404 *
2405 * @return LY_ERR values.
2406 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002407static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002408parse_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 +02002409{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002410 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002411 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002412 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002413 unsigned long int num;
2414 enum yang_keyword kw;
2415
2416 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002417 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002418 return LY_EVALID;
2419 }
2420 *flags |= LYS_SET_MIN;
2421
2422 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002423 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002424
2425 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002426 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002427 free(buf);
2428 return LY_EVALID;
2429 }
2430
2431 errno = 0;
2432 num = strtoul(word, &ptr, 10);
2433 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002434 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002435 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002436 free(buf);
2437 return LY_EVALID;
2438 }
2439 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002440 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002441 free(buf);
2442 return LY_EVALID;
2443 }
2444 *min = num;
2445 free(buf);
2446
2447 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002448 switch (kw) {
2449 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002450 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002451 break;
2452 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002453 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002454 return LY_EVALID;
2455 }
2456 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002457 return ret;
2458}
2459
Michal Vaskoea5abea2018-09-18 13:10:54 +02002460/**
2461 * @brief Parse the ordered-by statement.
2462 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002463 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002464 * @param[in,out] data Data to read from, always moved to currently handled character.
2465 * @param[in,out] flags Flags to write to.
2466 * @param[in,out] exts Extension instances to add to.
2467 *
2468 * @return LY_ERR values.
2469 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002470static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002471parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002472{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002473 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002474 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002475 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002476 enum yang_keyword kw;
2477
2478 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002479 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002480 return LY_EVALID;
2481 }
2482
2483 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002484 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485
2486 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2487 *flags |= LYS_ORDBY_SYSTEM;
2488 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2489 *flags |= LYS_ORDBY_USER;
2490 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002491 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002492 free(buf);
2493 return LY_EVALID;
2494 }
2495 free(buf);
2496
2497 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002498 switch (kw) {
2499 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002500 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002501 break;
2502 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002503 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002504 return LY_EVALID;
2505 }
2506 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002507 return ret;
2508}
2509
Michal Vaskoea5abea2018-09-18 13:10:54 +02002510/**
2511 * @brief Parse the leaf-list statement.
2512 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002513 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002514 * @param[in,out] data Data to read from, always moved to currently handled character.
2515 * @param[in,out] siblings Siblings to add to.
2516 *
2517 * @return LY_ERR values.
2518 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002519static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002520parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002521{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002522 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002523 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002524 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002525 enum yang_keyword kw;
2526 struct lysp_node *iter;
2527 struct lysp_node_leaflist *llist;
2528
2529 /* create structure */
2530 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002531 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002532 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002533 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002534
2535 /* insert into siblings */
2536 if (!*siblings) {
2537 *siblings = (struct lysp_node *)llist;
2538 } else {
2539 for (iter = *siblings; iter->next; iter = iter->next);
2540 iter->next = (struct lysp_node *)llist;
2541 }
2542
2543 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002544 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002545 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002546
2547 /* parse substatements */
2548 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002549 switch (kw) {
2550 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002551 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002552 break;
2553 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002554 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 +02002555 break;
2556 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002557 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 +02002558 break;
2559 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002560 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 +02002561 break;
2562 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002563 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002564 break;
2565 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002566 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002567 break;
2568 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002569 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002570 break;
2571 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002572 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002573 break;
2574 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002575 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 +02002576 break;
2577 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002578 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002579 break;
2580 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002581 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002582 break;
2583 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002584 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 +02002585 break;
2586 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002587 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002588 break;
2589 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002590 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002591 break;
2592 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002593 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002594 return LY_EVALID;
2595 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002596 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002597 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002598
2599 /* mandatory substatements */
2600 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002601 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002602 return LY_EVALID;
2603 }
2604
2605 return ret;
2606}
2607
Michal Vaskoea5abea2018-09-18 13:10:54 +02002608/**
2609 * @brief Parse the refine statement.
2610 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002611 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002612 * @param[in,out] data Data to read from, always moved to currently handled character.
2613 * @param[in,out] refines Refines to add to.
2614 *
2615 * @return LY_ERR values.
2616 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002617static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002618parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002620 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002621 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002622 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002623 enum yang_keyword kw;
2624 struct lysp_refine *rf;
2625
Radek Krejci2c4e7172018-10-19 15:56:26 +02002626 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002627
2628 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002629 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002630 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002631
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002632 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002633 switch (kw) {
2634 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002635 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636 break;
2637 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002638 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 +02002639 break;
2640 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002641 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 +02002642 break;
2643 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002644 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 +02002645 break;
2646 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002647 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002648 break;
2649 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002650 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002651 break;
2652 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002653 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002654 break;
2655 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002656 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002657 break;
2658 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002659 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 +02002660 break;
2661 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002662 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 +02002663 break;
2664 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002665 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002666 break;
2667 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002668 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002669 return LY_EVALID;
2670 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002672 return ret;
2673}
2674
Michal Vaskoea5abea2018-09-18 13:10:54 +02002675/**
2676 * @brief Parse the typedef statement.
2677 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002678 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002679 * @param[in,out] data Data to read from, always moved to currently handled character.
2680 * @param[in,out] typedefs Typedefs to add to.
2681 *
2682 * @return LY_ERR values.
2683 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002684static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002685parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002686{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002687 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002688 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002689 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002690 enum yang_keyword kw;
2691 struct lysp_tpdf *tpdf;
2692
Radek Krejci2c4e7172018-10-19 15:56:26 +02002693 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002694
2695 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002696 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002697 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002698
2699 /* parse substatements */
2700 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002701 switch (kw) {
2702 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002703 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 +02002704 break;
2705 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002706 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 +02002707 break;
2708 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002709 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 +02002710 break;
2711 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002712 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002713 break;
2714 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002715 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002716 break;
2717 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002718 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 +02002719 break;
2720 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002721 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002722 break;
2723 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002724 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002725 return LY_EVALID;
2726 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002727 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002728 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002729checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002730 /* mandatory substatements */
2731 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002732 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002733 return LY_EVALID;
2734 }
2735
Radek Krejcibbe09a92018-11-08 09:36:54 +01002736 /* store data for collision check */
2737 if (parent) {
2738 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2739 }
2740
Michal Vasko7fbc8162018-09-17 10:35:16 +02002741 return ret;
2742}
2743
Michal Vaskoea5abea2018-09-18 13:10:54 +02002744/**
2745 * @brief Parse the input or output statement.
2746 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002747 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002748 * @param[in,out] data Data to read from, always moved to currently handled character.
2749 * @param[in] kw Type of this particular keyword
2750 * @param[in,out] inout_p Input/output pointer to write to.
2751 *
2752 * @return LY_ERR values.
2753 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002754static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002755parse_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 +02002756{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002757 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002758 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002759 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002760 struct lysp_action_inout *inout;
2761
2762 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002763 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002764 return LY_EVALID;
2765 }
2766
2767 /* create structure */
2768 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002769 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002770 *inout_p = inout;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002771 inout->nodetype = LYS_INOUT;
2772 inout->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002773
2774 /* parse substatements */
2775 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002776 switch (kw) {
2777 case YANG_ANYDATA:
2778 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002779 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002780 break;
2781 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002782 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002783 break;
2784 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002785 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002786 break;
2787 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002788 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002789 break;
2790 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002791 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002792 break;
2793 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002794 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002795 break;
2796 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002797 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002798 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002799 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002800 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout, data, &inout->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002801 break;
2802 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002803 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002804 break;
2805 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002806 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout, &inout->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002807 break;
2808 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002809 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002810 break;
2811 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002812 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002813 return LY_EVALID;
2814 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002815 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002816 return ret;
2817}
2818
Michal Vaskoea5abea2018-09-18 13:10:54 +02002819/**
2820 * @brief Parse the action statement.
2821 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002822 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002823 * @param[in,out] data Data to read from, always moved to currently handled character.
2824 * @param[in,out] actions Actions to add to.
2825 *
2826 * @return LY_ERR values.
2827 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002828static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002829parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002830{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002831 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002832 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002833 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002834 enum yang_keyword kw;
2835 struct lysp_action *act;
2836
Radek Krejci2c4e7172018-10-19 15:56:26 +02002837 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002838
2839 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002840 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002841 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002842 act->nodetype = LYS_ACTION;
2843 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002844
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002845 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846 switch (kw) {
2847 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002848 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 +02002849 break;
2850 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002851 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 +02002852 break;
2853 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002854 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 +02002855 break;
2856 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002857 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002858 break;
2859
2860 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002861 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002862 break;
2863 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002864 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002865 break;
2866
2867 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002868 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002869 break;
2870 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002871 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002872 break;
2873 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002874 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002875 break;
2876 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002877 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002878 return LY_EVALID;
2879 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002880 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002881 return ret;
2882}
2883
Michal Vaskoea5abea2018-09-18 13:10:54 +02002884/**
2885 * @brief Parse the notification statement.
2886 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002887 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002888 * @param[in,out] data Data to read from, always moved to currently handled character.
2889 * @param[in,out] notifs Notifications to add to.
2890 *
2891 * @return LY_ERR values.
2892 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002893static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002894parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002895{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002896 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002897 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002898 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002899 enum yang_keyword kw;
2900 struct lysp_notif *notif;
2901
Radek Krejci2c4e7172018-10-19 15:56:26 +02002902 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002903
2904 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002905 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002906 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002907 notif->nodetype = LYS_NOTIF;
2908 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002909
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002910 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002911 switch (kw) {
2912 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002913 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 +02002914 break;
2915 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002916 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 +02002917 break;
2918 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002919 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 +02002920 break;
2921 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002922 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002923 break;
2924
2925 case YANG_ANYDATA:
2926 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002927 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002928 break;
2929 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002930 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002931 break;
2932 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002933 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002934 break;
2935 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002936 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002937 break;
2938 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002939 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002940 break;
2941 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002942 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002943 break;
2944 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002945 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002946 break;
2947
2948 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002949 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002950 break;
2951 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002952 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002953 break;
2954 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002955 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002956 break;
2957 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002958 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002959 break;
2960 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002961 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002962 return LY_EVALID;
2963 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002964 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002965 return ret;
2966}
2967
Michal Vaskoea5abea2018-09-18 13:10:54 +02002968/**
2969 * @brief Parse the grouping statement.
2970 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002971 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002972 * @param[in,out] data Data to read from, always moved to currently handled character.
2973 * @param[in,out] groupings Groupings to add to.
2974 *
2975 * @return LY_ERR values.
2976 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002977static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002978parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002979{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002980 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002981 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002982 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002983 enum yang_keyword kw;
2984 struct lysp_grp *grp;
2985
Radek Krejci2c4e7172018-10-19 15:56:26 +02002986 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002987
2988 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002989 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002990 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002991 grp->nodetype = LYS_GROUPING;
2992 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002993
2994 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002995 switch (kw) {
2996 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002997 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 +02002998 break;
2999 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003000 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 +02003001 break;
3002 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003003 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003004 break;
3005
3006 case YANG_ANYDATA:
3007 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003008 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003009 break;
3010 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003011 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003012 break;
3013 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003014 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003015 break;
3016 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003017 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003018 break;
3019 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003020 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003021 break;
3022 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003023 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003024 break;
3025 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003026 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003027 break;
3028
3029 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003030 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003031 break;
3032 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003033 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003034 break;
3035 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003036 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003037 break;
3038 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003039 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003040 break;
3041 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003042 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003043 break;
3044 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003045 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003046 return LY_EVALID;
3047 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003048 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003049 return ret;
3050}
3051
Michal Vaskoea5abea2018-09-18 13:10:54 +02003052/**
3053 * @brief Parse the refine statement.
3054 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003055 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003056 * @param[in,out] data Data to read from, always moved to currently handled character.
3057 * @param[in,out] augments Augments to add to.
3058 *
3059 * @return LY_ERR values.
3060 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003061static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003062parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003063{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003064 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003065 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003066 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003067 enum yang_keyword kw;
3068 struct lysp_augment *aug;
3069
Radek Krejci2c4e7172018-10-19 15:56:26 +02003070 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071
3072 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003073 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003074 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003075 aug->nodetype = LYS_AUGMENT;
3076 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003077
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003078 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079 switch (kw) {
3080 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003081 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 +02003082 break;
3083 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003084 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 +02003085 break;
3086 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003087 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 +02003088 break;
3089 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003090 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003091 break;
3092 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003093 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003094 break;
3095
3096 case YANG_ANYDATA:
3097 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003098 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003099 break;
3100 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003101 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003102 break;
3103 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003104 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003105 break;
3106 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003107 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003108 break;
3109 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003110 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003111 break;
3112 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003113 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003114 break;
3115 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003116 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003117 break;
3118 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003119 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003120 break;
3121
3122 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003123 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003124 break;
3125 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003126 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003127 break;
3128 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003129 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003130 break;
3131 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003132 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003133 return LY_EVALID;
3134 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003136 return ret;
3137}
3138
Michal Vaskoea5abea2018-09-18 13:10:54 +02003139/**
3140 * @brief Parse the uses statement.
3141 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003142 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003143 * @param[in,out] data Data to read from, always moved to currently handled character.
3144 * @param[in,out] siblings Siblings to add to.
3145 *
3146 * @return LY_ERR values.
3147 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003148static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003149parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003150{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003151 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003152 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003153 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003154 enum yang_keyword kw;
3155 struct lysp_node *iter;
3156 struct lysp_node_uses *uses;
3157
3158 /* create structure */
3159 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003160 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003161 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003162 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003163
3164 /* insert into siblings */
3165 if (!*siblings) {
3166 *siblings = (struct lysp_node *)uses;
3167 } else {
3168 for (iter = *siblings; iter->next; iter = iter->next);
3169 iter->next = (struct lysp_node *)uses;
3170 }
3171
3172 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003174 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003175
3176 /* parse substatements */
3177 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003178 switch (kw) {
3179 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003180 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 +02003181 break;
3182 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003183 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 +02003184 break;
3185 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003186 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 +02003187 break;
3188 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003189 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003190 break;
3191 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003192 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003193 break;
3194
3195 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003196 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003197 break;
3198 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003199 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003200 break;
3201 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003202 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003203 break;
3204 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003205 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003206 return LY_EVALID;
3207 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003208 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003209 return ret;
3210}
3211
Michal Vaskoea5abea2018-09-18 13:10:54 +02003212/**
3213 * @brief Parse the case statement.
3214 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003215 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003216 * @param[in,out] data Data to read from, always moved to currently handled character.
3217 * @param[in,out] siblings Siblings to add to.
3218 *
3219 * @return LY_ERR values.
3220 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003221static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003222parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003223{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003224 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003225 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003226 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003227 enum yang_keyword kw;
3228 struct lysp_node *iter;
3229 struct lysp_node_case *cas;
3230
3231 /* create structure */
3232 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003233 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003234 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003235 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003236
3237 /* insert into siblings */
3238 if (!*siblings) {
3239 *siblings = (struct lysp_node *)cas;
3240 } else {
3241 for (iter = *siblings; iter->next; iter = iter->next);
3242 iter->next = (struct lysp_node *)cas;
3243 }
3244
3245 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003246 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003247 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003248
3249 /* parse substatements */
3250 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003251 switch (kw) {
3252 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003253 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 +02003254 break;
3255 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003256 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 +02003257 break;
3258 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003259 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 +02003260 break;
3261 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003262 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003263 break;
3264 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003265 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003266 break;
3267
3268 case YANG_ANYDATA:
3269 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003270 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003271 break;
3272 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003273 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003274 break;
3275 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003276 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003277 break;
3278 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003279 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003280 break;
3281 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003282 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003283 break;
3284 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003285 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003286 break;
3287 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003288 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003289 break;
3290 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003291 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003292 break;
3293 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003294 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003295 return LY_EVALID;
3296 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003298 return ret;
3299}
3300
Michal Vaskoea5abea2018-09-18 13:10:54 +02003301/**
3302 * @brief Parse the choice statement.
3303 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003304 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003305 * @param[in,out] data Data to read from, always moved to currently handled character.
3306 * @param[in,out] siblings Siblings to add to.
3307 *
3308 * @return LY_ERR values.
3309 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003310static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003311parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003312{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003313 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003314 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003315 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003316 enum yang_keyword kw;
3317 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003318 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003319
3320 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003321 choice = calloc(1, sizeof *choice);
3322 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3323 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003324 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003325
3326 /* insert into siblings */
3327 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003328 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003329 } else {
3330 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003331 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003332 }
3333
3334 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003335 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003336 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003337
3338 /* parse substatements */
3339 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003340 switch (kw) {
3341 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003342 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003343 break;
3344 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003345 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 +02003346 break;
3347 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003348 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 +02003349 break;
3350 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003351 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003352 break;
3353 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003354 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 +02003355 break;
3356 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003357 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003358 break;
3359 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003360 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003361 break;
3362 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003363 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 +02003364 break;
3365
3366 case YANG_ANYDATA:
3367 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003368 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003369 break;
3370 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003371 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003372 break;
3373 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003374 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003375 break;
3376 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003377 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003378 break;
3379 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003380 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003381 break;
3382 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003383 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003384 break;
3385 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003386 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003387 break;
3388 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003389 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003390 break;
3391 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003392 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003393 return LY_EVALID;
3394 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003395 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003396 return ret;
3397}
3398
Michal Vaskoea5abea2018-09-18 13:10:54 +02003399/**
3400 * @brief Parse the container statement.
3401 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003402 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003403 * @param[in,out] data Data to read from, always moved to currently handled character.
3404 * @param[in,out] siblings Siblings to add to.
3405 *
3406 * @return LY_ERR values.
3407 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003408static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003409parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003410{
3411 LY_ERR ret = 0;
3412 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003413 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003414 enum yang_keyword kw;
3415 struct lysp_node *iter;
3416 struct lysp_node_container *cont;
3417
3418 /* create structure */
3419 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003420 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003421 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003422 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003423
3424 /* insert into siblings */
3425 if (!*siblings) {
3426 *siblings = (struct lysp_node *)cont;
3427 } else {
3428 for (iter = *siblings; iter->next; iter = iter->next);
3429 iter->next = (struct lysp_node *)cont;
3430 }
3431
3432 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003433 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003434 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003435
3436 /* parse substatements */
3437 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003438 switch (kw) {
3439 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003440 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003441 break;
3442 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003443 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 +02003444 break;
3445 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003446 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 +02003447 break;
3448 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003449 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 +02003450 break;
3451 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003452 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003453 break;
3454 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003455 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003456 break;
3457 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003458 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 +02003459 break;
3460
3461 case YANG_ANYDATA:
3462 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003463 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003464 break;
3465 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003466 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003467 break;
3468 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003469 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003470 break;
3471 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003472 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003473 break;
3474 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003475 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003476 break;
3477 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003478 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003479 break;
3480 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003481 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003482 break;
3483
3484 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003485 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003486 break;
3487 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003488 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003489 break;
3490 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003491 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003492 break;
3493 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003494 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003495 break;
3496 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003497 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003498 break;
3499 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003500 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003501 break;
3502 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003503 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003504 return LY_EVALID;
3505 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003506 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003507 return ret;
3508}
3509
Michal Vaskoea5abea2018-09-18 13:10:54 +02003510/**
3511 * @brief Parse the list statement.
3512 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003513 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003514 * @param[in,out] data Data to read from, always moved to currently handled character.
3515 * @param[in,out] siblings Siblings to add to.
3516 *
3517 * @return LY_ERR values.
3518 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003519static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003520parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003521{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003522 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003523 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003524 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003525 enum yang_keyword kw;
3526 struct lysp_node *iter;
3527 struct lysp_node_list *list;
3528
3529 /* create structure */
3530 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003531 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003532 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003533 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003534
3535 /* insert into siblings */
3536 if (!*siblings) {
3537 *siblings = (struct lysp_node *)list;
3538 } else {
3539 for (iter = *siblings; iter->next; iter = iter->next);
3540 iter->next = (struct lysp_node *)list;
3541 }
3542
3543 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003544 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003545 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003546
3547 /* parse substatements */
3548 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003549 switch (kw) {
3550 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003551 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003552 break;
3553 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003554 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 +02003555 break;
3556 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003557 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 +02003558 break;
3559 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003560 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 +02003561 break;
3562 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003563 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003564 break;
3565 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003566 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567 break;
3568 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003569 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 +02003570 break;
3571 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003572 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003573 break;
3574 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003575 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003576 break;
3577 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003578 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003579 break;
3580 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003581 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 +02003582 break;
3583
3584 case YANG_ANYDATA:
3585 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003586 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003587 break;
3588 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003589 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590 break;
3591 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003592 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003593 break;
3594 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003595 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003596 break;
3597 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003598 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003599 break;
3600 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003601 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003602 break;
3603 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003604 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003605 break;
3606
3607 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003608 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003609 break;
3610 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003611 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003612 break;
3613 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003614 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003615 break;
3616 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003617 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003618 break;
3619 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003620 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003621 break;
3622 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003623 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003624 break;
3625 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003626 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003627 return LY_EVALID;
3628 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003629 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003630
3631 return ret;
3632}
3633
Michal Vaskoea5abea2018-09-18 13:10:54 +02003634/**
3635 * @brief Parse the yin-element statement.
3636 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003637 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003638 * @param[in,out] data Data to read from, always moved to currently handled character.
3639 * @param[in,out] flags Flags to write to.
3640 * @param[in,out] exts Extension instances to add to.
3641 *
3642 * @return LY_ERR values.
3643 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003644static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003645parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003646{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003647 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003648 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003649 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003650 enum yang_keyword kw;
3651
3652 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003653 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003654 return LY_EVALID;
3655 }
3656
3657 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003658 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003659
3660 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3661 *flags |= LYS_YINELEM_TRUE;
3662 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3663 *flags |= LYS_YINELEM_FALSE;
3664 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003665 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003666 free(buf);
3667 return LY_EVALID;
3668 }
3669 free(buf);
3670
3671 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003672 switch (kw) {
3673 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003674 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3675 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003676 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003677 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003678 return LY_EVALID;
3679 }
3680 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003681 return ret;
3682}
3683
Michal Vaskoea5abea2018-09-18 13:10:54 +02003684/**
3685 * @brief Parse the yin-element statement.
3686 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003687 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003688 * @param[in,out] data Data to read from, always moved to currently handled character.
3689 * @param[in,out] argument Value to write to.
3690 * @param[in,out] flags Flags to write to.
3691 * @param[in,out] exts Extension instances to add to.
3692 *
3693 * @return LY_ERR values.
3694 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003695static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003696parse_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 +02003697{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003698 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003699 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003700 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003701 enum yang_keyword kw;
3702
3703 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003704 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003705 return LY_EVALID;
3706 }
3707
3708 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003709 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003710 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003711
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003712 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003713 switch (kw) {
3714 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003715 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003716 break;
3717 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003718 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003719 break;
3720 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003721 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003722 return LY_EVALID;
3723 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003724 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725 return ret;
3726}
3727
Michal Vaskoea5abea2018-09-18 13:10:54 +02003728/**
3729 * @brief Parse the extension statement.
3730 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003731 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003732 * @param[in,out] data Data to read from, always moved to currently handled character.
3733 * @param[in,out] extensions Extensions to add to.
3734 *
3735 * @return LY_ERR values.
3736 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003737static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003738parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003739{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003740 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003741 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003742 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003743 enum yang_keyword kw;
3744 struct lysp_ext *ex;
3745
Radek Krejci2c4e7172018-10-19 15:56:26 +02003746 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003747
3748 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003749 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003750 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003751
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003752 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003753 switch (kw) {
3754 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003755 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 +02003756 break;
3757 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003758 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 +02003759 break;
3760 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003761 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003762 break;
3763 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003764 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003765 break;
3766 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003767 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003768 break;
3769 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003770 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003771 return LY_EVALID;
3772 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003773 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003774 return ret;
3775}
3776
Michal Vaskoea5abea2018-09-18 13:10:54 +02003777/**
3778 * @brief Parse the deviate statement.
3779 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003780 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003781 * @param[in,out] data Data to read from, always moved to currently handled character.
3782 * @param[in,out] deviates Deviates to add to.
3783 *
3784 * @return LY_ERR values.
3785 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003786static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003787parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003788{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003789 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003790 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003791 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003792 enum yang_keyword kw;
3793 struct lysp_deviate *iter, *d;
3794 struct lysp_deviate_add *d_add = NULL;
3795 struct lysp_deviate_rpl *d_rpl = NULL;
3796 struct lysp_deviate_del *d_del = NULL;
3797 const char **d_units, ***d_uniques, ***d_dflts;
3798 struct lysp_restr **d_musts;
3799 uint16_t *d_flags;
3800 uint32_t *d_min, *d_max;
3801
3802 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003803 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003804
3805 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3806 dev_mod = LYS_DEV_NOT_SUPPORTED;
3807 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3808 dev_mod = LYS_DEV_ADD;
3809 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3810 dev_mod = LYS_DEV_REPLACE;
3811 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3812 dev_mod = LYS_DEV_DELETE;
3813 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003814 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003815 free(buf);
3816 return LY_EVALID;
3817 }
3818 free(buf);
3819
3820 /* create structure */
3821 switch (dev_mod) {
3822 case LYS_DEV_NOT_SUPPORTED:
3823 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003824 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003825 break;
3826 case LYS_DEV_ADD:
3827 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003828 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003829 d = (struct lysp_deviate *)d_add;
3830 d_units = &d_add->units;
3831 d_uniques = &d_add->uniques;
3832 d_dflts = &d_add->dflts;
3833 d_musts = &d_add->musts;
3834 d_flags = &d_add->flags;
3835 d_min = &d_add->min;
3836 d_max = &d_add->max;
3837 break;
3838 case LYS_DEV_REPLACE:
3839 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003840 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003841 d = (struct lysp_deviate *)d_rpl;
3842 d_units = &d_rpl->units;
3843 d_flags = &d_rpl->flags;
3844 d_min = &d_rpl->min;
3845 d_max = &d_rpl->max;
3846 break;
3847 case LYS_DEV_DELETE:
3848 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003849 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003850 d = (struct lysp_deviate *)d_del;
3851 d_units = &d_del->units;
3852 d_uniques = &d_del->uniques;
3853 d_dflts = &d_del->dflts;
3854 d_musts = &d_del->musts;
3855 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003856 break;
3857 default:
3858 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003859 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003860 }
3861 d->mod = dev_mod;
3862
3863 /* insert into siblings */
3864 if (!*deviates) {
3865 *deviates = d;
3866 } else {
3867 for (iter = *deviates; iter->next; iter = iter->next);
3868 iter->next = d;
3869 }
3870
3871 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003872 switch (kw) {
3873 case YANG_CONFIG:
3874 switch (dev_mod) {
3875 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003876 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003877 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003878 return LY_EVALID;
3879 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003880 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003881 break;
3882 }
3883 break;
3884 case YANG_DEFAULT:
3885 switch (dev_mod) {
3886 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003887 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003888 return LY_EVALID;
3889 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003890 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 +02003891 break;
3892 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003893 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 +02003894 break;
3895 }
3896 break;
3897 case YANG_MANDATORY:
3898 switch (dev_mod) {
3899 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003900 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003901 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003902 return LY_EVALID;
3903 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003904 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003905 break;
3906 }
3907 break;
3908 case YANG_MAX_ELEMENTS:
3909 switch (dev_mod) {
3910 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003911 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003912 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003913 return LY_EVALID;
3914 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003915 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003916 break;
3917 }
3918 break;
3919 case YANG_MIN_ELEMENTS:
3920 switch (dev_mod) {
3921 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003922 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003923 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003924 return LY_EVALID;
3925 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003926 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003927 break;
3928 }
3929 break;
3930 case YANG_MUST:
3931 switch (dev_mod) {
3932 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003933 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003934 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003935 return LY_EVALID;
3936 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003937 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003938 break;
3939 }
3940 break;
3941 case YANG_TYPE:
3942 switch (dev_mod) {
3943 case LYS_DEV_NOT_SUPPORTED:
3944 case LYS_DEV_ADD:
3945 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003946 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003947 return LY_EVALID;
3948 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003949 if (d_rpl->type) {
3950 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
3951 return LY_EVALID;
3952 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003953 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003954 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003955 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003956 break;
3957 }
3958 break;
3959 case YANG_UNIQUE:
3960 switch (dev_mod) {
3961 case LYS_DEV_NOT_SUPPORTED:
3962 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003963 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003964 return LY_EVALID;
3965 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003966 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 +02003967 break;
3968 }
3969 break;
3970 case YANG_UNITS:
3971 switch (dev_mod) {
3972 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003973 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003974 return LY_EVALID;
3975 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003976 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 +02003977 break;
3978 }
3979 break;
3980 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003981 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003982 break;
3983 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003984 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003985 return LY_EVALID;
3986 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003987 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003988 return ret;
3989}
3990
Michal Vaskoea5abea2018-09-18 13:10:54 +02003991/**
3992 * @brief Parse the deviation statement.
3993 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003994 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003995 * @param[in,out] data Data to read from, always moved to currently handled character.
3996 * @param[in,out] deviations Deviations to add to.
3997 *
3998 * @return LY_ERR values.
3999 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004000static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004001parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004002{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004003 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004004 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004005 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004006 enum yang_keyword kw;
4007 struct lysp_deviation *dev;
4008
Radek Krejci2c4e7172018-10-19 15:56:26 +02004009 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004010
4011 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004012 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004013 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004014
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004015 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004016 switch (kw) {
4017 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004018 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 +02004019 break;
4020 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004021 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004022 break;
4023 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004024 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 +02004025 break;
4026 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004027 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004028 break;
4029 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004030 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004031 return LY_EVALID;
4032 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004033 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004034 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004035
4036 /* mandatory substatements */
4037 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004038 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004039 return LY_EVALID;
4040 }
4041
4042 return ret;
4043}
4044
Michal Vaskoea5abea2018-09-18 13:10:54 +02004045/**
4046 * @brief Parse the feature statement.
4047 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004048 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004049 * @param[in,out] data Data to read from, always moved to currently handled character.
4050 * @param[in,out] features Features to add to.
4051 *
4052 * @return LY_ERR values.
4053 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004054static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004055parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004056{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004057 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004058 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004059 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004060 enum yang_keyword kw;
4061 struct lysp_feature *feat;
4062
Radek Krejci2c4e7172018-10-19 15:56:26 +02004063 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004064
4065 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004066 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004067 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004068
4069 CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
4070
Michal Vasko7fbc8162018-09-17 10:35:16 +02004071 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004072 switch (kw) {
4073 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004074 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 +02004075 break;
4076 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004077 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 +02004078 break;
4079 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004080 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 +02004081 break;
4082 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004083 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004084 break;
4085 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004086 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004087 break;
4088 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004089 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004090 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004091 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004092 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004093 return ret;
4094}
4095
Michal Vaskoea5abea2018-09-18 13:10:54 +02004096/**
4097 * @brief Parse the identity statement.
4098 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004099 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004100 * @param[in,out] data Data to read from, always moved to currently handled character.
4101 * @param[in,out] identities Identities to add to.
4102 *
4103 * @return LY_ERR values.
4104 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004105static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004106parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004107{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004108 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004109 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004110 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004111 enum yang_keyword kw;
4112 struct lysp_ident *ident;
4113
Radek Krejci2c4e7172018-10-19 15:56:26 +02004114 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004115
4116 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004117 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004118 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004119
4120 CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
4121
Michal Vasko7fbc8162018-09-17 10:35:16 +02004122 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004123 switch (kw) {
4124 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004125 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 +02004126 break;
4127 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004128 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 +02004129 break;
4130 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004131 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 +02004132 break;
4133 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004134 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004135 break;
4136 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004137 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 +02004138 break;
4139 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004140 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004141 break;
4142 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004143 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004144 return LY_EVALID;
4145 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004146 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004147 return ret;
4148}
4149
Michal Vaskoea5abea2018-09-18 13:10:54 +02004150/**
4151 * @brief Parse the module or submodule statement.
4152 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004153 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004154 * @param[in,out] data Data to read from, always moved to currently handled character.
4155 * @param[in,out] mod Module to write to.
4156 *
4157 * @return LY_ERR values.
4158 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004159static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004160parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004161{
4162 LY_ERR ret = 0;
4163 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004164 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004165 enum yang_keyword kw, prev_kw = 0;
4166 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejcie9e987e2018-10-31 12:50:27 +01004167 struct lysp_module *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004168
4169 /* (sub)module name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004170 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004171 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004172
Michal Vasko7fbc8162018-09-17 10:35:16 +02004173 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004174
Radek Krejcie3846472018-10-15 15:24:51 +02004175#define CHECK_ORDER(SECTION) \
4176 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4177
Michal Vasko7fbc8162018-09-17 10:35:16 +02004178 switch (kw) {
4179 /* module header */
4180 case YANG_NAMESPACE:
4181 case YANG_PREFIX:
4182 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004183 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004184 return LY_EVALID;
4185 }
Radek Krejcie3846472018-10-15 15:24:51 +02004186 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4187 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004188 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004189 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004190 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004191 return LY_EVALID;
4192 }
Radek Krejcie3846472018-10-15 15:24:51 +02004193 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4194 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004195 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004196 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004197 break;
4198 /* linkage */
4199 case YANG_INCLUDE:
4200 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004201 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004202 break;
4203 /* meta */
4204 case YANG_ORGANIZATION:
4205 case YANG_CONTACT:
4206 case YANG_DESCRIPTION:
4207 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004208 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004209 break;
4210
4211 /* revision */
4212 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004213 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004214 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004215 /* body */
4216 case YANG_ANYDATA:
4217 case YANG_ANYXML:
4218 case YANG_AUGMENT:
4219 case YANG_CHOICE:
4220 case YANG_CONTAINER:
4221 case YANG_DEVIATION:
4222 case YANG_EXTENSION:
4223 case YANG_FEATURE:
4224 case YANG_GROUPING:
4225 case YANG_IDENTITY:
4226 case YANG_LEAF:
4227 case YANG_LEAF_LIST:
4228 case YANG_LIST:
4229 case YANG_NOTIFICATION:
4230 case YANG_RPC:
4231 case YANG_TYPEDEF:
4232 case YANG_USES:
4233 case YANG_CUSTOM:
4234 mod_stmt = Y_MOD_BODY;
4235 break;
4236 default:
4237 /* error handled in the next switch */
4238 break;
4239 }
Radek Krejcie3846472018-10-15 15:24:51 +02004240#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004241
Radek Krejcie3846472018-10-15 15:24:51 +02004242 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004243 switch (kw) {
4244 /* module header */
4245 case YANG_YANG_VERSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004246 LY_CHECK_RET(parse_yangversion(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004247 break;
4248 case YANG_NAMESPACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004249 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 +02004250 break;
4251 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004252 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 +02004253 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004254 break;
4255 case YANG_BELONGS_TO:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004256 LY_CHECK_RET(parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004257 break;
4258
4259 /* linkage */
4260 case YANG_INCLUDE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004261 LY_CHECK_RET(parse_include(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004262 break;
4263 case YANG_IMPORT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004264 LY_CHECK_RET(parse_import(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004265 break;
4266
4267 /* meta */
4268 case YANG_ORGANIZATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004269 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 +02004270 break;
4271 case YANG_CONTACT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004272 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 +02004273 break;
4274 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004275 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 +02004276 break;
4277 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004278 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 +02004279 break;
4280
4281 /* revision */
4282 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004283 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004284 break;
4285
4286 /* body */
4287 case YANG_ANYDATA:
4288 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004289 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004290 break;
4291 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004292 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004293 break;
4294 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004295 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004296 break;
4297 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004298 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004299 break;
4300 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004301 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004302 break;
4303 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004304 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004305 break;
4306 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004307 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004308 break;
4309
4310 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004311 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004312 break;
4313 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004314 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004315 break;
4316 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004317 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004318 break;
4319 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004320 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004321 break;
4322 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004323 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004324 break;
4325 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004326 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004327 break;
4328 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004329 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004330 break;
4331 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004332 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004333 break;
4334 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004335 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004336 break;
4337 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004338 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004339 break;
4340
4341 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004342 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004343 return LY_EVALID;
4344 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004345 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004346 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004347
4348 /* mandatory substatements */
4349 if (mod->submodule) {
4350 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004351 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004352 return LY_EVALID;
4353 }
4354 } else {
4355 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004356 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004357 return LY_EVALID;
4358 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004359 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004360 return LY_EVALID;
4361 }
4362 }
4363
Radek Krejcie9e987e2018-10-31 12:50:27 +01004364 /* submodules share the namespace with the module names, so there must not be
4365 * a submodule of the same name in the context, no need for revision matching */
4366 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL);
4367 if (dup && (!mod->submodule || strcmp(dup->belongsto, mod->belongsto))) {
4368 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4369 mod->submodule ? "submodules" : "module and submodule", mod->name);
4370 return LY_EVALID;
4371 }
4372
Michal Vasko7fbc8162018-09-17 10:35:16 +02004373 return ret;
4374}
4375
Radek Krejcid4557c62018-09-17 11:42:09 +02004376LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01004377yang_parse(struct ly_parser_ctx *context, const char *data, struct lysp_module **mod_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004378{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004379 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004380 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004381 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004382 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004383 struct lysp_module *mod = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004384
4385 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004386 ret = get_keyword(context, &data, &kw, &word, &word_len);
4387 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004388
4389 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004390 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004391 ly_stmt2str(kw));
Radek Krejcibbe09a92018-11-08 09:36:54 +01004392 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004393 }
4394
4395 mod = calloc(1, sizeof *mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004396 LY_CHECK_ERR_GOTO(!mod, LOGMEM(context->ctx), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004397 if (kw == YANG_SUBMODULE) {
4398 mod->submodule = 1;
4399 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01004400 mod->parsing = 1;
4401 mod->ctx = context->ctx;
4402 context->mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004403
4404 /* substatements */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004405 ret = parse_sub_module(context, &data, mod);
4406 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004407
4408 /* read some trailing spaces or new lines */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004409 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4410 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004411
4412 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004413 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004414 word_len, word);
4415 free(buf);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004416 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004417 }
4418 assert(!buf);
4419
Radek Krejcibbe09a92018-11-08 09:36:54 +01004420 mod->parsing = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004421 *mod_p = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422
Radek Krejcibbe09a92018-11-08 09:36:54 +01004423cleanup:
4424 if (ret) {
4425 lysp_module_free(mod);
4426 }
4427
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428 return ret;
4429}