blob: 47819a1a1d274c845d4c56c4b8ba73a4ece4c3e6 [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 Krejci44ceedc2018-10-02 15:54:31 +02001223 if (lysp_check_date(ctx->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 Krejci44ceedc2018-10-02 15:54:31 +02001378 if (lysp_check_date(ctx->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 Krejci44ceedc2018-10-02 15:54:31 +02002685parse_typedef(struct ly_parser_ctx *ctx, 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);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002729
2730 /* 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
2736 return ret;
2737}
2738
Michal Vaskoea5abea2018-09-18 13:10:54 +02002739/**
2740 * @brief Parse the input or output statement.
2741 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002742 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002743 * @param[in,out] data Data to read from, always moved to currently handled character.
2744 * @param[in] kw Type of this particular keyword
2745 * @param[in,out] inout_p Input/output pointer to write to.
2746 *
2747 * @return LY_ERR values.
2748 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002749static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002750parse_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 +02002751{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002752 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002753 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002754 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002755 struct lysp_action_inout *inout;
2756
2757 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002758 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002759 return LY_EVALID;
2760 }
2761
2762 /* create structure */
2763 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002764 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765 *inout_p = inout;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002766 inout->nodetype = LYS_INOUT;
2767 inout->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002768
2769 /* parse substatements */
2770 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002771 switch (kw) {
2772 case YANG_ANYDATA:
2773 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002774 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002775 break;
2776 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002777 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002778 break;
2779 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002780 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002781 break;
2782 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002783 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002784 break;
2785 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002786 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002787 break;
2788 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002789 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790 break;
2791 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002792 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002793 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002794 case YANG_TYPEDEF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002795 LY_CHECK_RET(parse_typedef(ctx, data, &inout->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 break;
2797 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002798 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002799 break;
2800 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002801 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout, &inout->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002802 break;
2803 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002804 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002805 break;
2806 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002807 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002808 return LY_EVALID;
2809 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002810 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002811 return ret;
2812}
2813
Michal Vaskoea5abea2018-09-18 13:10:54 +02002814/**
2815 * @brief Parse the action statement.
2816 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002817 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002818 * @param[in,out] data Data to read from, always moved to currently handled character.
2819 * @param[in,out] actions Actions to add to.
2820 *
2821 * @return LY_ERR values.
2822 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002823static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002824parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002825{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002826 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002827 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002828 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002829 enum yang_keyword kw;
2830 struct lysp_action *act;
2831
Radek Krejci2c4e7172018-10-19 15:56:26 +02002832 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002833
2834 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002835 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002836 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002837 act->nodetype = LYS_ACTION;
2838 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002839
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002840 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002841 switch (kw) {
2842 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002843 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 +02002844 break;
2845 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002846 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 +02002847 break;
2848 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002849 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 +02002850 break;
2851 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002852 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002853 break;
2854
2855 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002856 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 break;
2858 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002859 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 break;
2861
2862 case YANG_TYPEDEF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002863 LY_CHECK_RET(parse_typedef(ctx, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002864 break;
2865 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002866 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002867 break;
2868 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002869 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002870 break;
2871 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002872 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002873 return LY_EVALID;
2874 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002875 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002876 return ret;
2877}
2878
Michal Vaskoea5abea2018-09-18 13:10:54 +02002879/**
2880 * @brief Parse the notification statement.
2881 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002882 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002883 * @param[in,out] data Data to read from, always moved to currently handled character.
2884 * @param[in,out] notifs Notifications to add to.
2885 *
2886 * @return LY_ERR values.
2887 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002888static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002889parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002890{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002891 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002892 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002893 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002894 enum yang_keyword kw;
2895 struct lysp_notif *notif;
2896
Radek Krejci2c4e7172018-10-19 15:56:26 +02002897 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002898
2899 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002900 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002901 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002902 notif->nodetype = LYS_NOTIF;
2903 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002904
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002905 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002906 switch (kw) {
2907 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002908 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 +02002909 break;
2910 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002911 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 +02002912 break;
2913 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002914 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 +02002915 break;
2916 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002917 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918 break;
2919
2920 case YANG_ANYDATA:
2921 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002922 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002923 break;
2924 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002925 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002926 break;
2927 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002928 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002929 break;
2930 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002931 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932 break;
2933 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002934 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002935 break;
2936 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002937 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002938 break;
2939 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002940 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002941 break;
2942
2943 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002944 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002945 break;
2946 case YANG_TYPEDEF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002947 LY_CHECK_RET(parse_typedef(ctx, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002948 break;
2949 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002950 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002951 break;
2952 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002953 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002954 break;
2955 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002956 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002957 return LY_EVALID;
2958 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002959 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002960 return ret;
2961}
2962
Michal Vaskoea5abea2018-09-18 13:10:54 +02002963/**
2964 * @brief Parse the grouping statement.
2965 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002966 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002967 * @param[in,out] data Data to read from, always moved to currently handled character.
2968 * @param[in,out] groupings Groupings to add to.
2969 *
2970 * @return LY_ERR values.
2971 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002972static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002973parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002974{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002975 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002976 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002977 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978 enum yang_keyword kw;
2979 struct lysp_grp *grp;
2980
Radek Krejci2c4e7172018-10-19 15:56:26 +02002981 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002982
2983 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002984 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002985 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002986 grp->nodetype = LYS_GROUPING;
2987 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002988
2989 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002990 switch (kw) {
2991 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002992 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 +02002993 break;
2994 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002995 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 +02002996 break;
2997 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002998 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002999 break;
3000
3001 case YANG_ANYDATA:
3002 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003003 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003004 break;
3005 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003006 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003007 break;
3008 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003009 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003010 break;
3011 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003012 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003013 break;
3014 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003015 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003016 break;
3017 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003018 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003019 break;
3020 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003021 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003022 break;
3023
3024 case YANG_TYPEDEF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003025 LY_CHECK_RET(parse_typedef(ctx, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003026 break;
3027 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003028 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003029 break;
3030 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003031 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032 break;
3033 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003034 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003035 break;
3036 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003037 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003038 break;
3039 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003040 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003041 return LY_EVALID;
3042 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003043 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003044 return ret;
3045}
3046
Michal Vaskoea5abea2018-09-18 13:10:54 +02003047/**
3048 * @brief Parse the refine statement.
3049 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003050 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003051 * @param[in,out] data Data to read from, always moved to currently handled character.
3052 * @param[in,out] augments Augments to add to.
3053 *
3054 * @return LY_ERR values.
3055 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003056static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003057parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003058{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003059 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003060 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003061 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003062 enum yang_keyword kw;
3063 struct lysp_augment *aug;
3064
Radek Krejci2c4e7172018-10-19 15:56:26 +02003065 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003066
3067 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003068 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003069 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003070 aug->nodetype = LYS_AUGMENT;
3071 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003072
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003073 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003074 switch (kw) {
3075 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003076 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 +02003077 break;
3078 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003079 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 +02003080 break;
3081 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003082 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 +02003083 break;
3084 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003085 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003086 break;
3087 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003088 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003089 break;
3090
3091 case YANG_ANYDATA:
3092 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003093 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003094 break;
3095 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003096 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003097 break;
3098 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003099 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003100 break;
3101 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003102 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003103 break;
3104 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003105 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003106 break;
3107 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003108 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003109 break;
3110 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003111 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003112 break;
3113 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003114 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003115 break;
3116
3117 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003118 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003119 break;
3120 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003121 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003122 break;
3123 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003124 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003125 break;
3126 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003127 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003128 return LY_EVALID;
3129 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003130 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003131 return ret;
3132}
3133
Michal Vaskoea5abea2018-09-18 13:10:54 +02003134/**
3135 * @brief Parse the uses statement.
3136 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003137 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003138 * @param[in,out] data Data to read from, always moved to currently handled character.
3139 * @param[in,out] siblings Siblings to add to.
3140 *
3141 * @return LY_ERR values.
3142 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003143static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003144parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003145{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003146 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003147 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003148 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003149 enum yang_keyword kw;
3150 struct lysp_node *iter;
3151 struct lysp_node_uses *uses;
3152
3153 /* create structure */
3154 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003155 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003156 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003157 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003158
3159 /* insert into siblings */
3160 if (!*siblings) {
3161 *siblings = (struct lysp_node *)uses;
3162 } else {
3163 for (iter = *siblings; iter->next; iter = iter->next);
3164 iter->next = (struct lysp_node *)uses;
3165 }
3166
3167 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003168 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003169 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003170
3171 /* parse substatements */
3172 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003173 switch (kw) {
3174 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003175 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 +02003176 break;
3177 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003178 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 +02003179 break;
3180 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003181 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 +02003182 break;
3183 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003184 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003185 break;
3186 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003187 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003188 break;
3189
3190 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003191 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003192 break;
3193 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003194 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003195 break;
3196 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003197 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003198 break;
3199 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003200 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003201 return LY_EVALID;
3202 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003203 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003204 return ret;
3205}
3206
Michal Vaskoea5abea2018-09-18 13:10:54 +02003207/**
3208 * @brief Parse the case statement.
3209 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003210 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003211 * @param[in,out] data Data to read from, always moved to currently handled character.
3212 * @param[in,out] siblings Siblings to add to.
3213 *
3214 * @return LY_ERR values.
3215 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003216static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003217parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003218{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003219 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003220 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003221 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003222 enum yang_keyword kw;
3223 struct lysp_node *iter;
3224 struct lysp_node_case *cas;
3225
3226 /* create structure */
3227 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003228 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003229 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003230 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003231
3232 /* insert into siblings */
3233 if (!*siblings) {
3234 *siblings = (struct lysp_node *)cas;
3235 } else {
3236 for (iter = *siblings; iter->next; iter = iter->next);
3237 iter->next = (struct lysp_node *)cas;
3238 }
3239
3240 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003241 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003242 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003243
3244 /* parse substatements */
3245 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003246 switch (kw) {
3247 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003248 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 +02003249 break;
3250 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003251 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 +02003252 break;
3253 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003254 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 +02003255 break;
3256 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003257 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003258 break;
3259 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003260 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003261 break;
3262
3263 case YANG_ANYDATA:
3264 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003265 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003266 break;
3267 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003268 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003269 break;
3270 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003271 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003272 break;
3273 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003274 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003275 break;
3276 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003277 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003278 break;
3279 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003280 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003281 break;
3282 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003283 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003284 break;
3285 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003286 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003287 break;
3288 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003289 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003290 return LY_EVALID;
3291 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003292 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003293 return ret;
3294}
3295
Michal Vaskoea5abea2018-09-18 13:10:54 +02003296/**
3297 * @brief Parse the choice statement.
3298 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003299 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003300 * @param[in,out] data Data to read from, always moved to currently handled character.
3301 * @param[in,out] siblings Siblings to add to.
3302 *
3303 * @return LY_ERR values.
3304 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003305static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003306parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003307{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003308 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003309 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003310 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003311 enum yang_keyword kw;
3312 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003313 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003314
3315 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003316 choice = calloc(1, sizeof *choice);
3317 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3318 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003319 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003320
3321 /* insert into siblings */
3322 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003323 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003324 } else {
3325 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003326 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003327 }
3328
3329 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003330 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003331 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003332
3333 /* parse substatements */
3334 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003335 switch (kw) {
3336 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003337 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003338 break;
3339 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003340 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 +02003341 break;
3342 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003343 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 +02003344 break;
3345 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003346 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003347 break;
3348 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003349 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 +02003350 break;
3351 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003352 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003353 break;
3354 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003355 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003356 break;
3357 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003358 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 +02003359 break;
3360
3361 case YANG_ANYDATA:
3362 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003363 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003364 break;
3365 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003366 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003367 break;
3368 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003369 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003370 break;
3371 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003372 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373 break;
3374 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003375 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003376 break;
3377 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003378 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003379 break;
3380 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003381 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003382 break;
3383 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003384 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003385 break;
3386 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003387 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003388 return LY_EVALID;
3389 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003390 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003391 return ret;
3392}
3393
Michal Vaskoea5abea2018-09-18 13:10:54 +02003394/**
3395 * @brief Parse the container statement.
3396 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003397 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003398 * @param[in,out] data Data to read from, always moved to currently handled character.
3399 * @param[in,out] siblings Siblings to add to.
3400 *
3401 * @return LY_ERR values.
3402 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003403static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003404parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003405{
3406 LY_ERR ret = 0;
3407 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003408 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003409 enum yang_keyword kw;
3410 struct lysp_node *iter;
3411 struct lysp_node_container *cont;
3412
3413 /* create structure */
3414 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003415 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003416 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003417 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003418
3419 /* insert into siblings */
3420 if (!*siblings) {
3421 *siblings = (struct lysp_node *)cont;
3422 } else {
3423 for (iter = *siblings; iter->next; iter = iter->next);
3424 iter->next = (struct lysp_node *)cont;
3425 }
3426
3427 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003428 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003429 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003430
3431 /* parse substatements */
3432 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003433 switch (kw) {
3434 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003435 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003436 break;
3437 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003438 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 +02003439 break;
3440 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003441 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 +02003442 break;
3443 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003444 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 +02003445 break;
3446 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003447 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003448 break;
3449 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003450 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003451 break;
3452 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003453 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 +02003454 break;
3455
3456 case YANG_ANYDATA:
3457 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003458 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003459 break;
3460 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003461 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003462 break;
3463 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003464 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003465 break;
3466 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003467 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003468 break;
3469 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003470 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003471 break;
3472 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003473 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003474 break;
3475 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003476 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003477 break;
3478
3479 case YANG_TYPEDEF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003480 LY_CHECK_RET(parse_typedef(ctx, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003481 break;
3482 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003483 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003484 break;
3485 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003486 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003487 break;
3488 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003489 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003490 break;
3491 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003492 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003493 break;
3494 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003495 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003496 break;
3497 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003498 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003499 return LY_EVALID;
3500 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003501 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003502 return ret;
3503}
3504
Michal Vaskoea5abea2018-09-18 13:10:54 +02003505/**
3506 * @brief Parse the list statement.
3507 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003508 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003509 * @param[in,out] data Data to read from, always moved to currently handled character.
3510 * @param[in,out] siblings Siblings to add to.
3511 *
3512 * @return LY_ERR values.
3513 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003514static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003515parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003516{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003517 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003518 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003519 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003520 enum yang_keyword kw;
3521 struct lysp_node *iter;
3522 struct lysp_node_list *list;
3523
3524 /* create structure */
3525 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003526 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003527 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003528 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003529
3530 /* insert into siblings */
3531 if (!*siblings) {
3532 *siblings = (struct lysp_node *)list;
3533 } else {
3534 for (iter = *siblings; iter->next; iter = iter->next);
3535 iter->next = (struct lysp_node *)list;
3536 }
3537
3538 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003539 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003540 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003541
3542 /* parse substatements */
3543 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003544 switch (kw) {
3545 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003546 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003547 break;
3548 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003549 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 +02003550 break;
3551 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003552 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 +02003553 break;
3554 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003555 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 +02003556 break;
3557 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003558 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003559 break;
3560 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003561 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003562 break;
3563 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003564 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 +02003565 break;
3566 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003567 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003568 break;
3569 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003570 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003571 break;
3572 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003573 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003574 break;
3575 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003576 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 +02003577 break;
3578
3579 case YANG_ANYDATA:
3580 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003581 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003582 break;
3583 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003584 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003585 break;
3586 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003587 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003588 break;
3589 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003590 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003591 break;
3592 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003593 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003594 break;
3595 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003596 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003597 break;
3598 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003599 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003600 break;
3601
3602 case YANG_TYPEDEF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003603 LY_CHECK_RET(parse_typedef(ctx, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604 break;
3605 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003606 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003607 break;
3608 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003609 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610 break;
3611 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003612 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613 break;
3614 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003615 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003616 break;
3617 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003618 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003619 break;
3620 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003621 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003622 return LY_EVALID;
3623 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003624 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003625
3626 return ret;
3627}
3628
Michal Vaskoea5abea2018-09-18 13:10:54 +02003629/**
3630 * @brief Parse the yin-element statement.
3631 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003632 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003633 * @param[in,out] data Data to read from, always moved to currently handled character.
3634 * @param[in,out] flags Flags to write to.
3635 * @param[in,out] exts Extension instances to add to.
3636 *
3637 * @return LY_ERR values.
3638 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003639static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003640parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003641{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003642 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003644 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003645 enum yang_keyword kw;
3646
3647 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003648 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003649 return LY_EVALID;
3650 }
3651
3652 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003653 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003654
3655 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3656 *flags |= LYS_YINELEM_TRUE;
3657 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3658 *flags |= LYS_YINELEM_FALSE;
3659 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003660 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003661 free(buf);
3662 return LY_EVALID;
3663 }
3664 free(buf);
3665
3666 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003667 switch (kw) {
3668 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003669 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3670 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003671 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003672 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003673 return LY_EVALID;
3674 }
3675 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003676 return ret;
3677}
3678
Michal Vaskoea5abea2018-09-18 13:10:54 +02003679/**
3680 * @brief Parse the yin-element statement.
3681 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003682 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003683 * @param[in,out] data Data to read from, always moved to currently handled character.
3684 * @param[in,out] argument Value to write to.
3685 * @param[in,out] flags Flags to write to.
3686 * @param[in,out] exts Extension instances to add to.
3687 *
3688 * @return LY_ERR values.
3689 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003690static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003691parse_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 +02003692{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003693 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003694 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003695 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003696 enum yang_keyword kw;
3697
3698 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003699 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003700 return LY_EVALID;
3701 }
3702
3703 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003704 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003705 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003706
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003707 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003708 switch (kw) {
3709 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003710 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003711 break;
3712 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003713 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003714 break;
3715 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003716 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003717 return LY_EVALID;
3718 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003719 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003720 return ret;
3721}
3722
Michal Vaskoea5abea2018-09-18 13:10:54 +02003723/**
3724 * @brief Parse the extension statement.
3725 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003726 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003727 * @param[in,out] data Data to read from, always moved to currently handled character.
3728 * @param[in,out] extensions Extensions to add to.
3729 *
3730 * @return LY_ERR values.
3731 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003732static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003733parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003734{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003735 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003736 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003737 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003738 enum yang_keyword kw;
3739 struct lysp_ext *ex;
3740
Radek Krejci2c4e7172018-10-19 15:56:26 +02003741 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003742
3743 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003744 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003745 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003747 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003748 switch (kw) {
3749 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003750 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 +02003751 break;
3752 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003753 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 +02003754 break;
3755 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003756 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003757 break;
3758 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003759 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003760 break;
3761 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003762 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003763 break;
3764 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003765 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003766 return LY_EVALID;
3767 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003768 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003769 return ret;
3770}
3771
Michal Vaskoea5abea2018-09-18 13:10:54 +02003772/**
3773 * @brief Parse the deviate statement.
3774 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003775 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003776 * @param[in,out] data Data to read from, always moved to currently handled character.
3777 * @param[in,out] deviates Deviates to add to.
3778 *
3779 * @return LY_ERR values.
3780 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003781static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003782parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003783{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003784 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003785 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003786 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003787 enum yang_keyword kw;
3788 struct lysp_deviate *iter, *d;
3789 struct lysp_deviate_add *d_add = NULL;
3790 struct lysp_deviate_rpl *d_rpl = NULL;
3791 struct lysp_deviate_del *d_del = NULL;
3792 const char **d_units, ***d_uniques, ***d_dflts;
3793 struct lysp_restr **d_musts;
3794 uint16_t *d_flags;
3795 uint32_t *d_min, *d_max;
3796
3797 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003798 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003799
3800 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3801 dev_mod = LYS_DEV_NOT_SUPPORTED;
3802 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3803 dev_mod = LYS_DEV_ADD;
3804 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3805 dev_mod = LYS_DEV_REPLACE;
3806 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3807 dev_mod = LYS_DEV_DELETE;
3808 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003809 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003810 free(buf);
3811 return LY_EVALID;
3812 }
3813 free(buf);
3814
3815 /* create structure */
3816 switch (dev_mod) {
3817 case LYS_DEV_NOT_SUPPORTED:
3818 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003819 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003820 break;
3821 case LYS_DEV_ADD:
3822 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003823 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003824 d = (struct lysp_deviate *)d_add;
3825 d_units = &d_add->units;
3826 d_uniques = &d_add->uniques;
3827 d_dflts = &d_add->dflts;
3828 d_musts = &d_add->musts;
3829 d_flags = &d_add->flags;
3830 d_min = &d_add->min;
3831 d_max = &d_add->max;
3832 break;
3833 case LYS_DEV_REPLACE:
3834 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003835 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003836 d = (struct lysp_deviate *)d_rpl;
3837 d_units = &d_rpl->units;
3838 d_flags = &d_rpl->flags;
3839 d_min = &d_rpl->min;
3840 d_max = &d_rpl->max;
3841 break;
3842 case LYS_DEV_DELETE:
3843 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003844 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003845 d = (struct lysp_deviate *)d_del;
3846 d_units = &d_del->units;
3847 d_uniques = &d_del->uniques;
3848 d_dflts = &d_del->dflts;
3849 d_musts = &d_del->musts;
3850 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003851 break;
3852 default:
3853 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003854 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003855 }
3856 d->mod = dev_mod;
3857
3858 /* insert into siblings */
3859 if (!*deviates) {
3860 *deviates = d;
3861 } else {
3862 for (iter = *deviates; iter->next; iter = iter->next);
3863 iter->next = d;
3864 }
3865
3866 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003867 switch (kw) {
3868 case YANG_CONFIG:
3869 switch (dev_mod) {
3870 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003871 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003872 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003873 return LY_EVALID;
3874 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003875 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003876 break;
3877 }
3878 break;
3879 case YANG_DEFAULT:
3880 switch (dev_mod) {
3881 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003882 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003883 return LY_EVALID;
3884 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003885 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 +02003886 break;
3887 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003888 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 +02003889 break;
3890 }
3891 break;
3892 case YANG_MANDATORY:
3893 switch (dev_mod) {
3894 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003895 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003896 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003897 return LY_EVALID;
3898 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003899 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003900 break;
3901 }
3902 break;
3903 case YANG_MAX_ELEMENTS:
3904 switch (dev_mod) {
3905 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003906 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003907 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908 return LY_EVALID;
3909 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003910 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003911 break;
3912 }
3913 break;
3914 case YANG_MIN_ELEMENTS:
3915 switch (dev_mod) {
3916 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003917 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003918 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003919 return LY_EVALID;
3920 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003921 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 break;
3923 }
3924 break;
3925 case YANG_MUST:
3926 switch (dev_mod) {
3927 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003928 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003929 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003930 return LY_EVALID;
3931 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003932 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003933 break;
3934 }
3935 break;
3936 case YANG_TYPE:
3937 switch (dev_mod) {
3938 case LYS_DEV_NOT_SUPPORTED:
3939 case LYS_DEV_ADD:
3940 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003941 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003942 return LY_EVALID;
3943 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003944 if (d_rpl->type) {
3945 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
3946 return LY_EVALID;
3947 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003948 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003949 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003950 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003951 break;
3952 }
3953 break;
3954 case YANG_UNIQUE:
3955 switch (dev_mod) {
3956 case LYS_DEV_NOT_SUPPORTED:
3957 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003958 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003959 return LY_EVALID;
3960 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003961 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 +02003962 break;
3963 }
3964 break;
3965 case YANG_UNITS:
3966 switch (dev_mod) {
3967 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003968 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003969 return LY_EVALID;
3970 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003971 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 +02003972 break;
3973 }
3974 break;
3975 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003976 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003977 break;
3978 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003979 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003980 return LY_EVALID;
3981 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003982 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003983 return ret;
3984}
3985
Michal Vaskoea5abea2018-09-18 13:10:54 +02003986/**
3987 * @brief Parse the deviation statement.
3988 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003989 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003990 * @param[in,out] data Data to read from, always moved to currently handled character.
3991 * @param[in,out] deviations Deviations to add to.
3992 *
3993 * @return LY_ERR values.
3994 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003995static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003996parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003997{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003998 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003999 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004000 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004001 enum yang_keyword kw;
4002 struct lysp_deviation *dev;
4003
Radek Krejci2c4e7172018-10-19 15:56:26 +02004004 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004005
4006 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004007 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004008 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004009
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004010 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004011 switch (kw) {
4012 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004013 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 +02004014 break;
4015 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004016 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017 break;
4018 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004019 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 +02004020 break;
4021 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004022 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004023 break;
4024 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004025 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004026 return LY_EVALID;
4027 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004028 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004029 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004030
4031 /* mandatory substatements */
4032 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004033 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004034 return LY_EVALID;
4035 }
4036
4037 return ret;
4038}
4039
Michal Vaskoea5abea2018-09-18 13:10:54 +02004040/**
4041 * @brief Parse the feature statement.
4042 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004043 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004044 * @param[in,out] data Data to read from, always moved to currently handled character.
4045 * @param[in,out] features Features to add to.
4046 *
4047 * @return LY_ERR values.
4048 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004049static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004050parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004051{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004052 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004053 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004054 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004055 enum yang_keyword kw;
4056 struct lysp_feature *feat;
4057
Radek Krejci2c4e7172018-10-19 15:56:26 +02004058 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004059
4060 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004061 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004062 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004063
4064 CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
4065
Michal Vasko7fbc8162018-09-17 10:35:16 +02004066 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004067 switch (kw) {
4068 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004069 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 +02004070 break;
4071 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004072 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 +02004073 break;
4074 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004075 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 +02004076 break;
4077 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004078 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004079 break;
4080 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004081 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004082 break;
4083 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004084 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004085 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004086 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004087 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004088 return ret;
4089}
4090
Michal Vaskoea5abea2018-09-18 13:10:54 +02004091/**
4092 * @brief Parse the identity statement.
4093 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004094 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004095 * @param[in,out] data Data to read from, always moved to currently handled character.
4096 * @param[in,out] identities Identities to add to.
4097 *
4098 * @return LY_ERR values.
4099 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004100static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004101parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004102{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004103 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004104 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004105 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004106 enum yang_keyword kw;
4107 struct lysp_ident *ident;
4108
Radek Krejci2c4e7172018-10-19 15:56:26 +02004109 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004110
4111 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004112 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004113 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004114
4115 CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
4116
Michal Vasko7fbc8162018-09-17 10:35:16 +02004117 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004118 switch (kw) {
4119 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004120 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 +02004121 break;
4122 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004123 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 +02004124 break;
4125 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004126 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 +02004127 break;
4128 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004129 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004130 break;
4131 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004132 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 +02004133 break;
4134 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004135 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004136 break;
4137 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004138 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004139 return LY_EVALID;
4140 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004141 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004142 return ret;
4143}
4144
Michal Vaskoea5abea2018-09-18 13:10:54 +02004145/**
4146 * @brief Parse the module or submodule statement.
4147 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004148 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004149 * @param[in,out] data Data to read from, always moved to currently handled character.
4150 * @param[in,out] mod Module to write to.
4151 *
4152 * @return LY_ERR values.
4153 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004154static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004155parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004156{
4157 LY_ERR ret = 0;
4158 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004159 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004160 enum yang_keyword kw, prev_kw = 0;
4161 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejcie9e987e2018-10-31 12:50:27 +01004162 struct lysp_module *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004163
4164 /* (sub)module name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004165 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004166 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004167
Michal Vasko7fbc8162018-09-17 10:35:16 +02004168 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004169
Radek Krejcie3846472018-10-15 15:24:51 +02004170#define CHECK_ORDER(SECTION) \
4171 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4172
Michal Vasko7fbc8162018-09-17 10:35:16 +02004173 switch (kw) {
4174 /* module header */
4175 case YANG_NAMESPACE:
4176 case YANG_PREFIX:
4177 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004178 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179 return LY_EVALID;
4180 }
Radek Krejcie3846472018-10-15 15:24:51 +02004181 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4182 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004183 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004184 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004185 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004186 return LY_EVALID;
4187 }
Radek Krejcie3846472018-10-15 15:24:51 +02004188 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4189 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004190 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004191 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004192 break;
4193 /* linkage */
4194 case YANG_INCLUDE:
4195 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004196 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004197 break;
4198 /* meta */
4199 case YANG_ORGANIZATION:
4200 case YANG_CONTACT:
4201 case YANG_DESCRIPTION:
4202 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004203 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004204 break;
4205
4206 /* revision */
4207 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004208 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004209 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004210 /* body */
4211 case YANG_ANYDATA:
4212 case YANG_ANYXML:
4213 case YANG_AUGMENT:
4214 case YANG_CHOICE:
4215 case YANG_CONTAINER:
4216 case YANG_DEVIATION:
4217 case YANG_EXTENSION:
4218 case YANG_FEATURE:
4219 case YANG_GROUPING:
4220 case YANG_IDENTITY:
4221 case YANG_LEAF:
4222 case YANG_LEAF_LIST:
4223 case YANG_LIST:
4224 case YANG_NOTIFICATION:
4225 case YANG_RPC:
4226 case YANG_TYPEDEF:
4227 case YANG_USES:
4228 case YANG_CUSTOM:
4229 mod_stmt = Y_MOD_BODY;
4230 break;
4231 default:
4232 /* error handled in the next switch */
4233 break;
4234 }
Radek Krejcie3846472018-10-15 15:24:51 +02004235#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236
Radek Krejcie3846472018-10-15 15:24:51 +02004237 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004238 switch (kw) {
4239 /* module header */
4240 case YANG_YANG_VERSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004241 LY_CHECK_RET(parse_yangversion(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004242 break;
4243 case YANG_NAMESPACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004244 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 +02004245 break;
4246 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004247 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 +02004248 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004249 break;
4250 case YANG_BELONGS_TO:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004251 LY_CHECK_RET(parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004252 break;
4253
4254 /* linkage */
4255 case YANG_INCLUDE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004256 LY_CHECK_RET(parse_include(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004257 break;
4258 case YANG_IMPORT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004259 LY_CHECK_RET(parse_import(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004260 break;
4261
4262 /* meta */
4263 case YANG_ORGANIZATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004264 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 +02004265 break;
4266 case YANG_CONTACT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004267 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 +02004268 break;
4269 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004270 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 +02004271 break;
4272 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004273 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 +02004274 break;
4275
4276 /* revision */
4277 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004278 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004279 break;
4280
4281 /* body */
4282 case YANG_ANYDATA:
4283 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004284 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004285 break;
4286 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004287 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004288 break;
4289 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004290 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004291 break;
4292 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004293 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004294 break;
4295 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004296 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004297 break;
4298 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004299 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004300 break;
4301 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004302 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004303 break;
4304
4305 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004306 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004307 break;
4308 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004309 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004310 break;
4311 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004312 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004313 break;
4314 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004315 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316 break;
4317 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004318 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004319 break;
4320 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004321 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004322 break;
4323 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004324 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004325 break;
4326 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004327 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004328 break;
4329 case YANG_TYPEDEF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004330 LY_CHECK_RET(parse_typedef(ctx, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004331 break;
4332 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004333 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004334 break;
4335
4336 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004337 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004338 return LY_EVALID;
4339 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004340 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004341 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004342
4343 /* mandatory substatements */
4344 if (mod->submodule) {
4345 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004346 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004347 return LY_EVALID;
4348 }
4349 } else {
4350 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004351 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004352 return LY_EVALID;
4353 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004354 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004355 return LY_EVALID;
4356 }
4357 }
4358
Radek Krejcie9e987e2018-10-31 12:50:27 +01004359 /* submodules share the namespace with the module names, so there must not be
4360 * a submodule of the same name in the context, no need for revision matching */
4361 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL);
4362 if (dup && (!mod->submodule || strcmp(dup->belongsto, mod->belongsto))) {
4363 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4364 mod->submodule ? "submodules" : "module and submodule", mod->name);
4365 return LY_EVALID;
4366 }
4367
Michal Vasko7fbc8162018-09-17 10:35:16 +02004368 return ret;
4369}
4370
Radek Krejcid4557c62018-09-17 11:42:09 +02004371LY_ERR
Michal Vasko7fbc8162018-09-17 10:35:16 +02004372yang_parse(struct ly_ctx *ctx, const char *data, struct lysp_module **mod_p)
4373{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004374 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004375 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004376 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004377 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004378 struct lysp_module *mod = NULL;
Radek Krejci86d106e2018-10-18 09:53:19 +02004379 struct ly_parser_ctx context = {0};
Michal Vasko7fbc8162018-09-17 10:35:16 +02004380
Radek Krejci44ceedc2018-10-02 15:54:31 +02004381 context.ctx = ctx;
4382 context.line = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004383
4384 /* "module"/"submodule" */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004385 ret = get_keyword(&context, &data, &kw, &word, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004386 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004387
4388 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004389 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004390 ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004391 goto error;
4392 }
4393
4394 mod = calloc(1, sizeof *mod);
4395 LY_CHECK_ERR_GOTO(!mod, LOGMEM(ctx), error);
4396 if (kw == YANG_SUBMODULE) {
4397 mod->submodule = 1;
4398 }
Radek Krejci9fcacc12018-10-11 15:59:11 +02004399 mod->ctx = ctx;
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004400 context.mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004401
4402 /* substatements */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004403 ret = parse_sub_module(&context, &data, mod);
Radek Krejcic59bc972018-09-17 16:13:06 +02004404 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004405
4406 /* read some trailing spaces or new lines */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004407 ret = get_argument(&context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004408 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004409
4410 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004411 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004412 word_len, word);
4413 free(buf);
4414 goto error;
4415 }
4416 assert(!buf);
4417
4418 *mod_p = mod;
4419 return ret;
4420
4421error:
Radek Krejci9fcacc12018-10-11 15:59:11 +02004422 lysp_module_free(mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004423 return ret;
4424}