blob: dabe200c6252dc83c1369f851127c96f482aac94 [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 */
Michal Vasko7fbc8162018-09-17 10:35:16 +020014
15#include "common.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020016
17#include <assert.h>
18#include <ctype.h>
19#include <errno.h>
20#include <stdint.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
Michal Vasko7fbc8162018-09-17 10:35:16 +020025#include "context.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020026#include "dict.h"
27#include "extensions.h"
28#include "log.h"
29#include "set.h"
30#include "tree.h"
31#include "tree_schema.h"
Radek Krejci70853c52018-10-15 14:46:16 +020032#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020033
34/* Macro to check YANG's yang-char grammar rule */
35#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
36 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
37 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
38 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
39 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
40 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
41 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
42 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
43 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
44 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
45
Radek Krejciceaf2122019-01-02 15:03:26 +010046/**
47 * @brief Try to find object with MEMBER string matching the IDENT in the given ARRAY.
48 * Macro logs an error message and returns LY_EVALID in case of existence of a matching object.
49 *
50 * @param[in] CTX yang parser context for logging.
51 * @param[in] ARRAY [sized array](@ref sizedarrays) of a generic objects with member named MEMBER to search.
52 * @param[in] MEMBER Name of the member of the objects in the ARRAY to compare.
53 * @param[in] STMT Name of the compared YANG statements for logging.
54 * @param[in] IDENT String trying to find in the ARRAY's objects inside the MEMBER member.
55 */
Radek Krejcifaa1eac2018-10-30 14:34:55 +010056#define CHECK_UNIQUENESS(CTX, ARRAY, MEMBER, STMT, IDENT) \
57 if (ARRAY) { \
58 for (unsigned int u = 0; u < LY_ARRAY_SIZE(ARRAY) - 1; ++u) { \
59 if (!strcmp((ARRAY)[u].MEMBER, IDENT)) { \
60 LOGVAL_YANG(CTX, LY_VCODE_DUPIDENT, IDENT, STMT); \
61 return LY_EVALID; \
62 } \
63 } \
64 }
65
Radek Krejciceaf2122019-01-02 15:03:26 +010066/**
67 * @brief Insert WORD into the libyang context's dictionary and store as TARGET.
68 * @param[in] CTX yang parser context to access libyang context.
69 * @param[in] BUF buffer in case the word is not a constant and can be inserted directly (zero-copy)
70 * @param[out] TARGET variable where to store the pointer to the inserted value.
71 * @param[in] WORD string to store.
72 * @param[in] LEN length of the string in WORD to store.
73 */
Radek Krejci9fcacc12018-10-11 15:59:11 +020074#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
75 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
Radek Krejcif09e4e82019-06-14 15:08:11 +020076 else {(TARGET) = lydict_insert((CTX)->ctx, LEN ? WORD : "", LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020077
Radek Krejciceaf2122019-01-02 15:03:26 +010078/**
79 * @brief Move the DATA pointer by COUNT items. Also updates the indent value in yang parser context
80 * @param[in] CTX yang parser context to update its indent value.
81 * @param[in,out] DATA pointer to move
82 * @param[in] COUNT number of items for which the DATA pointer is supposed to move on.
83 */
Radek Krejci2b610482019-01-02 13:36:09 +010084#define MOVE_INPUT(CTX, DATA, COUNT) (*(DATA))+=COUNT;(CTX)->indent+=COUNT
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020085
Michal Vaskoea5abea2018-09-18 13:10:54 +020086/**
87 * @brief Loop through all substatements providing, return if there are none.
88 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020089 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020090 * @param[in] DATA Raw data to read from.
91 * @param[out] KW YANG keyword read.
92 * @param[out] WORD Pointer to the keyword itself.
93 * @param[out] WORD_LEN Length of the keyword.
94 * @param[out] ERR Variable for error storing.
95 *
96 * @return In case there are no substatements or a fatal error encountered.
97 */
Radek Krejci6d6556c2018-11-08 09:37:45 +010098#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010099 LY_CHECK_RET(get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +0200100 if (KW == YANG_SEMICOLON) { \
Radek Krejci6d6556c2018-11-08 09:37:45 +0100101 CHECKGOTO; \
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100102 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +0200103 } \
104 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +0200105 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +0200106 return LY_EVALID; \
107 } \
108 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
109 !ERR && (KW != YANG_RIGHT_BRACE); \
110 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
111
Radek Krejciceaf2122019-01-02 15:03:26 +0100112/**
113 * @brief Check module version is at least 2 (YANG 1.1) because of the keyword presence.
114 * Logs error message and returns LY_EVALID in case of module in YANG version 1.0.
115 * @param[in] CTX yang parser context to get current module and for logging.
116 * @param[in] KW keyword allowed only in YANG version 1.1 (or later) - for logging.
117 * @param[in] PARENT parent statement where the KW is present - for logging.
118 */
119#define YANG_CHECK_STMTVER2_RET(CTX, KW, PARENT) \
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100120 if ((CTX)->mod_version < 2) {LOGVAL_YANG((CTX), LY_VCODE_INCHILDSTMT2, KW, PARENT); return LY_EVALID;}
Radek Krejci10113652018-11-14 16:56:50 +0100121
Radek Krejcif09e4e82019-06-14 15:08:11 +0200122#define YANG_CHECK_NONEMPTY(CTX, OBJECT, VALUE_LEN, STMT) \
123 if (!VALUE_LEN) { \
124 LOGWRN((CTX)->ctx, "Empty argument of %s statement does not make sense.", STMT); \
125 }
126
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200127LY_ERR parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
128LY_ERR parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
129LY_ERR parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
130LY_ERR parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
131LY_ERR parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
132LY_ERR parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200133
Radek Krejci7fc68292019-06-12 13:51:09 +0200134static LY_ERR parse_finalize_reallocated(struct lys_parser_ctx *ctx, struct lysp_grp *groupings, struct lysp_augment *augments,
135 struct lysp_action *actions, struct lysp_notif *notifs);
136
Michal Vaskoea5abea2018-09-18 13:10:54 +0200137/**
138 * @brief Add another character to dynamic buffer, a low-level function.
139 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200140 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200141 *
Radek Krejci404251e2018-10-09 12:06:44 +0200142 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200143 * @param[in, out] input Input string to process.
144 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200145 * @param[in,out] buf Buffer to use, can be moved by realloc().
146 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200147 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200148 *
149 * @return LY_ERR values.
150 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200151LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200152buf_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 +0200153{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200154 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200155 *buf_len += 16;
156 *buf = ly_realloc(*buf, *buf_len);
157 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
158 }
Radek Krejcic0917392019-04-10 13:04:04 +0200159 if (*buf_used) {
160 memcpy(&(*buf)[*buf_used], *input, len);
161 } else {
162 memcpy(*buf, *input, len);
163 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200164
Radek Krejci44ceedc2018-10-02 15:54:31 +0200165 (*buf_used) += len;
166 (*input) += len;
167
Michal Vasko7fbc8162018-09-17 10:35:16 +0200168 return LY_SUCCESS;
169}
170
Michal Vaskoea5abea2018-09-18 13:10:54 +0200171/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200172 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200173 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200174 * @param[in] ctx yang parser context for logging.
175 * @param[in] c UTF8 code point of a character to check.
176 * @return LY_ERR values.
177 */
178static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200179check_stringchar(struct lys_parser_ctx *ctx, unsigned int c)
Radek Krejci44ceedc2018-10-02 15:54:31 +0200180{
181 if (!is_yangutf8char(c)) {
182 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
183 return LY_EVALID;
184 }
185 return LY_SUCCESS;
186}
187
188/**
189 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
190 *
191 * @param[in] ctx yang parser context for logging.
192 * @param[in] c UTF8 code point of a character to check.
193 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200194 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
195 * 0 - colon not yet found (no prefix)
196 * 1 - \p c is the colon character
197 * 2 - prefix already processed, now processing the identifier
198 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200199 * If the identifier cannot be prefixed, NULL is expected.
200 * @return LY_ERR values.
201 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200202LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200203check_identifierchar(struct lys_parser_ctx *ctx, unsigned int c, int first, int *prefix)
Radek Krejci44ceedc2018-10-02 15:54:31 +0200204{
205 if (first || (prefix && (*prefix) == 1)) {
206 if (!is_yangidentstartchar(c)) {
207 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
208 return LY_EVALID;
209 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200210 if (prefix) {
211 if (first) {
212 (*prefix) = 0;
213 } else {
214 (*prefix) = 2;
215 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200216 }
217 } else if (c == ':' && prefix && (*prefix) == 0) {
218 (*prefix) = 1;
219 } else if (!is_yangidentchar(c)) {
220 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
221 return LY_EVALID;
222 }
223
224 return LY_SUCCESS;
225}
226
227/**
228 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
229 *
230 * @param[in] ctx yang parser context for logging.
231 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
232 * when function returns.
233 * @param[in] arg Type of the input string to select method of checking character validity.
234 * @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 +0200235 * 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 +0200236 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
237 * @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 +0200238 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200239 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200240 *
241 * @return LY_ERR values.
242 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200243LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200244buf_store_char(struct lys_parser_ctx *ctx, const char **input, enum yang_arg arg,
Radek Krejci44ceedc2018-10-02 15:54:31 +0200245 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200246{
Radek Krejci404251e2018-10-09 12:06:44 +0200247 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200248 unsigned int c;
249 size_t len;
250
Radek Krejcif29b7c32019-04-09 16:17:49 +0200251 /* check valid combination of input paremeters - if need_buf specified, word_b must be provided */
252 assert(!need_buf || (need_buf && word_b));
253
Radek Krejci44ceedc2018-10-02 15:54:31 +0200254 /* get UTF8 code point (and number of bytes coding the character) */
255 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
256 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
257 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200258 if (c == '\n') {
259 ctx->indent = 0;
260 } else {
261 /* note - even the multibyte character is count as 1 */
262 ++ctx->indent;
263 }
264
Radek Krejci44ceedc2018-10-02 15:54:31 +0200265 /* check character validity */
266 switch (arg) {
267 case Y_IDENTIF_ARG:
268 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
269 break;
270 case Y_PREF_IDENTIF_ARG:
271 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
272 break;
273 case Y_STR_ARG:
274 case Y_MAYBE_STR_ARG:
275 LY_CHECK_RET(check_stringchar(ctx, c));
276 break;
277 }
278
Michal Vasko7fbc8162018-09-17 10:35:16 +0200279 if (word_b && *word_b) {
280 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200281 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200282 return LY_EMEM;
283 }
284
285 /* in case of realloc */
286 *word_p = *word_b;
Radek Krejcif29b7c32019-04-09 16:17:49 +0200287 } else if (word_b && need_buf) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200288 /* first time we need a buffer, copy everything read up to now */
289 if (*word_len) {
290 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200291 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200292 *buf_len = *word_len;
293 memcpy(*word_b, *word_p, *word_len);
294 }
295
296 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200297 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200298 return LY_EMEM;
299 }
300
301 /* in case of realloc */
302 *word_p = *word_b;
303 } else {
304 /* just remember the first character pointer */
305 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200306 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200307 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200308 /* ... and update the word's length */
309 (*word_len) += len;
310 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200311 }
312
313 return LY_SUCCESS;
314}
315
Michal Vaskoea5abea2018-09-18 13:10:54 +0200316/**
317 * @brief Skip YANG comment in data.
318 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200319 * @param[in] ctx yang parser context for logging.
320 * @param[in,out] data Data to read from, automatically moved after the comment.
321 * @param[in] comment Type of the comment to process:
322 * 1 for a one-line comment,
323 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200324 *
325 * @return LY_ERR values.
326 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200327LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200328skip_comment(struct lys_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200329{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200330 /* internal statuses: 0 - comment ended,
331 * 1 - in line comment,
332 * 2 - in block comment,
333 * 3 - in block comment with last read character '*'
334 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200335 while (**data && comment) {
336 switch (comment) {
337 case 1:
338 if (**data == '\n') {
339 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200340 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200341 }
342 break;
343 case 2:
344 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200345 comment = 3;
346 } else if (**data == '\n') {
347 ++ctx->line;
348 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200349 break;
350 case 3:
351 if (**data == '/') {
352 comment = 0;
Radek Krejci5b930492019-06-11 14:54:08 +0200353 } else if (**data != '*') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200354 if (**data == '\n') {
355 ++ctx->line;
356 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200357 comment = 2;
358 }
359 break;
360 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200361 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200362 }
363
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200364 if (**data == '\n') {
365 ctx->indent = 0;
366 } else {
367 ++ctx->indent;
368 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200369 ++(*data);
370 }
371
372 if (!**data && (comment > 1)) {
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200373 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-input, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200374 return LY_EVALID;
375 }
376
377 return LY_SUCCESS;
378}
379
Michal Vaskoea5abea2018-09-18 13:10:54 +0200380/**
381 * @brief Read a quoted string from data.
382 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200383 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200384 * @param[in,out] data Data to read from, always moved to currently handled character.
385 * @param[in] arg Type of YANG keyword argument expected.
386 * @param[out] word_p Pointer to the read quoted string.
387 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
388 * set to NULL. Otherwise equal to \p word_p.
389 * @param[out] word_len Length of the read quoted string.
390 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
391 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
392 * indenation in the final quoted string.
393 *
394 * @return LY_ERR values.
395 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200396static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200397read_qstring(struct lys_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 +0200398 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200399{
400 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
401 * 4 - string finished, now skipping whitespaces looking for +,
402 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200403 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200404 const char *c;
405
406 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200407 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200408 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200409 } else {
410 assert(**data == '\'');
411 string = 1;
412 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200413 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200414
415 while (**data && string) {
416 switch (string) {
417 case 1:
418 switch (**data) {
419 case '\'':
420 /* string may be finished, but check for + */
421 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200422 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200423 break;
424 default:
425 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200426 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 +0200427 break;
428 }
429 break;
430 case 2:
431 switch (**data) {
432 case '\"':
433 /* string may be finished, but check for + */
434 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200435 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200436 break;
437 case '\\':
438 /* special character following */
439 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200440 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200441 break;
442 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200443 if (current_indent < block_indent) {
444 ++current_indent;
445 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200446 } else {
447 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200448 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 +0200449 }
450 break;
451 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200452 if (current_indent < block_indent) {
453 assert(need_buf);
454 current_indent += 8;
455 ctx->indent += 8;
456 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
457 /* store leftover spaces from the tab */
458 c = " ";
459 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 +0200460 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200461 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200462 } else {
463 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200464 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 +0200465 /* additional characters for indentation - only 1 was count in buf_store_char */
466 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200467 }
468 break;
469 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200470 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200471 /* we will be removing the indents so we need our own buffer */
472 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200473
474 /* remove trailing tabs and spaces */
475 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
476 --(*word_len);
477 }
478
479 /* start indentation */
480 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200481 }
482
483 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200484 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
485
486 /* maintain line number */
487 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200488
489 /* reset context indentation counter for possible string after this one */
490 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200491 break;
492 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200493 /* first non-whitespace character, stop eating indentation */
494 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200495
496 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200497 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 +0200498 break;
499 }
500 break;
501 case 3:
502 /* string encoded characters */
503 switch (**data) {
504 case 'n':
505 c = "\n";
506 break;
507 case 't':
508 c = "\t";
509 break;
510 case '\"':
511 c = *data;
512 break;
513 case '\\':
514 c = *data;
515 break;
516 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200517 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200518 return LY_EVALID;
519 }
520
521 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200522 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 +0200523
524 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200525 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200526 break;
527 case 4:
528 switch (**data) {
529 case '+':
530 /* string continues */
531 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200532 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200533 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200534 case '\n':
535 ++ctx->line;
536 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200537 case ' ':
538 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200539 /* just skip */
540 break;
541 default:
542 /* string is finished */
543 goto string_end;
544 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200545 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200546 break;
547 case 5:
548 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200549 case '\n':
550 ++ctx->line;
551 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200552 case ' ':
553 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200554 /* skip */
555 break;
556 case '\'':
557 string = 1;
558 break;
559 case '\"':
560 string = 2;
561 break;
562 default:
563 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200564 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200565 return LY_EVALID;
566 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200567 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200568 break;
569 default:
570 return LY_EINT;
571 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200572 }
573
574string_end:
Radek Krejci4e199f52019-05-28 09:09:28 +0200575 if (arg <= Y_PREF_IDENTIF_ARG && !(*word_len)) {
576 /* empty identifier */
577 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Statement argument is required.");
578 return LY_EVALID;
579 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200580 return LY_SUCCESS;
581}
582
Michal Vaskoea5abea2018-09-18 13:10:54 +0200583/**
584 * @brief Get another YANG string from the raw data.
585 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200586 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200587 * @param[in,out] data Data to read from, always moved to currently handled character.
588 * @param[in] arg Type of YANG keyword argument expected.
Radek Krejcid3ca0632019-04-16 16:54:54 +0200589 * @param[out] flags optional output argument to get flag of the argument's quoting (LYS_*QOUTED - see [schema node flags](@ref snodeflags))
Michal Vasko2ca70f52018-09-27 11:04:51 +0200590 * @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 +0200591 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
592 * set to NULL. Otherwise equal to \p word_p.
593 * @param[out] word_len Length of the read string.
594 *
595 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200596 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200597LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200598get_argument(struct lys_parser_ctx *ctx, const char **data, enum yang_arg arg,
Radek Krejcid3ca0632019-04-16 16:54:54 +0200599 uint16_t *flags, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200600{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200601 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200602
603 /* word buffer - dynamically allocated */
604 *word_b = NULL;
605
606 /* word pointer - just a pointer to data */
607 *word_p = NULL;
608
609 *word_len = 0;
610 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200611 switch (**data) {
612 case '\'':
613 case '\"':
614 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200615 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
616 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
617 "unquoted string character, optsep, semicolon or opening brace");
618 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200619 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200620 if (flags) {
621 (*flags) |= (**data) == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
622 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100623 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200624 goto str_end;
625 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200626 if ((*data)[1] == '/') {
627 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200628 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100629 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200630 } else if ((*data)[1] == '*') {
631 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200632 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100633 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200634 } else {
635 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100636 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 +0200637 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200638 break;
639 case ' ':
640 if (*word_len) {
641 /* word is finished */
642 goto str_end;
643 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200644 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200645 break;
646 case '\t':
647 if (*word_len) {
648 /* word is finished */
649 goto str_end;
650 }
651 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200652 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200653
654 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200655 break;
656 case '\n':
657 if (*word_len) {
658 /* word is finished */
659 goto str_end;
660 }
661 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200662 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200663
664 /* track line numbers */
665 ++ctx->line;
666
667 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200668 break;
669 case ';':
670 case '{':
671 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
672 /* word is finished */
673 goto str_end;
674 }
675
Radek Krejci44ceedc2018-10-02 15:54:31 +0200676 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200677 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200678 case '}':
679 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
680 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
681 "unquoted string character, optsep, semicolon or opening brace");
682 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200683 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200684 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 +0200685 break;
686 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200687 }
688
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200689 /* unexpected end of loop */
690 LOGVAL_YANG(ctx, LY_VCODE_EOF);
691 return LY_EVALID;
692
Michal Vasko7fbc8162018-09-17 10:35:16 +0200693str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200694 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200695 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200696 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
697 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
698 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200699 *word_p = *word_b;
700 }
701
702 return LY_SUCCESS;
703}
704
Michal Vaskoea5abea2018-09-18 13:10:54 +0200705/**
706 * @brief Get another YANG keyword from the raw data.
707 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200708 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200709 * @param[in,out] data Data to read from, always moved to currently handled character.
710 * @param[out] kw YANG keyword read.
711 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
712 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
713 *
714 * @return LY_ERR values.
715 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200716LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200717get_keyword(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200718{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200719 int prefix;
720 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200721 unsigned int c;
722 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200723
724 if (word_p) {
725 *word_p = NULL;
726 *word_len = 0;
727 }
728
729 /* first skip "optsep", comments */
730 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200731 switch (**data) {
732 case '/':
733 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200734 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200735 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100736 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200737 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200738 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200739 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100740 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200741 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200742 /* error - not a comment after all, keyword cannot start with slash */
743 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
744 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200745 }
Radek Krejci13028282019-06-11 14:56:48 +0200746 continue;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200747 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200748 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200749 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200750 ctx->indent = 0;
751 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200752 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200753 /* skip whitespaces (optsep) */
754 ++ctx->indent;
755 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200756 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200757 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200758 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200759 break;
760 default:
761 /* either a keyword start or an invalid character */
762 goto keyword_start;
763 }
764
765 ++(*data);
766 }
767
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200768#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
769#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
770#define IF_KW_PREFIX_END }
771
Michal Vasko7fbc8162018-09-17 10:35:16 +0200772keyword_start:
773 word_start = *data;
774 *kw = YANG_NONE;
775
776 /* read the keyword itself */
777 switch (**data) {
778 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200779 MOVE_INPUT(ctx, data, 1);
780 IF_KW("rgument", 7, YANG_ARGUMENT)
781 else IF_KW("ugment", 6, YANG_AUGMENT)
782 else IF_KW("ction", 5, YANG_ACTION)
783 else IF_KW_PREFIX("ny", 2)
784 IF_KW("data", 4, YANG_ANYDATA)
785 else IF_KW("xml", 3, YANG_ANYXML)
786 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200787 break;
788 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200789 MOVE_INPUT(ctx, data, 1);
790 IF_KW("ase", 3, YANG_BASE)
791 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
792 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200793 break;
794 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200795 MOVE_INPUT(ctx, data, 1);
796 IF_KW("ase", 3, YANG_CASE)
797 else IF_KW("hoice", 5, YANG_CHOICE)
798 else IF_KW_PREFIX("on", 2)
799 IF_KW("fig", 3, YANG_CONFIG)
800 else IF_KW_PREFIX("ta", 2)
801 IF_KW("ct", 2, YANG_CONTACT)
802 else IF_KW("iner", 4, YANG_CONTAINER)
803 IF_KW_PREFIX_END
804 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200805 break;
806 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200807 MOVE_INPUT(ctx, data, 1);
808 IF_KW_PREFIX("e", 1)
809 IF_KW("fault", 5, YANG_DEFAULT)
810 else IF_KW("scription", 9, YANG_DESCRIPTION)
811 else IF_KW_PREFIX("viat", 4)
812 IF_KW("e", 1, YANG_DEVIATE)
813 else IF_KW("ion", 3, YANG_DEVIATION)
814 IF_KW_PREFIX_END
815 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200816 break;
817 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200818 MOVE_INPUT(ctx, data, 1);
819 IF_KW("num", 3, YANG_ENUM)
820 else IF_KW_PREFIX("rror-", 5)
821 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
822 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
823 IF_KW_PREFIX_END
824 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200825 break;
826 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200827 MOVE_INPUT(ctx, data, 1);
828 IF_KW("eature", 6, YANG_FEATURE)
829 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200830 break;
831 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200832 MOVE_INPUT(ctx, data, 1);
833 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200834 break;
835 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200836 MOVE_INPUT(ctx, data, 1);
837 IF_KW("dentity", 7, YANG_IDENTITY)
838 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
839 else IF_KW("mport", 5, YANG_IMPORT)
840 else IF_KW_PREFIX("n", 1)
841 IF_KW("clude", 5, YANG_INCLUDE)
842 else IF_KW("put", 3, YANG_INPUT)
843 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200844 break;
845 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200846 MOVE_INPUT(ctx, data, 1);
847 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200848 break;
849 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200850 MOVE_INPUT(ctx, data, 1);
851 IF_KW_PREFIX("e", 1)
852 IF_KW("af-list", 7, YANG_LEAF_LIST)
853 else IF_KW("af", 2, YANG_LEAF)
854 else IF_KW("ngth", 4, YANG_LENGTH)
855 IF_KW_PREFIX_END
856 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200857 break;
858 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200859 MOVE_INPUT(ctx, data, 1);
860 IF_KW_PREFIX("a", 1)
861 IF_KW("ndatory", 7, YANG_MANDATORY)
862 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
863 IF_KW_PREFIX_END
864 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
865 else IF_KW("ust", 3, YANG_MUST)
866 else IF_KW_PREFIX("od", 2)
867 IF_KW("ule", 3, YANG_MODULE)
868 else IF_KW("ifier", 5, YANG_MODIFIER)
869 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200870 break;
871 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200872 MOVE_INPUT(ctx, data, 1);
873 IF_KW("amespace", 8, YANG_NAMESPACE)
874 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200875 break;
876 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200877 MOVE_INPUT(ctx, data, 1);
878 IF_KW_PREFIX("r", 1)
879 IF_KW("dered-by", 8, YANG_ORDERED_BY)
880 else IF_KW("ganization", 10, YANG_ORGANIZATION)
881 IF_KW_PREFIX_END
882 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200883 break;
884 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200885 MOVE_INPUT(ctx, data, 1);
886 IF_KW("ath", 3, YANG_PATH)
887 else IF_KW("attern", 6, YANG_PATTERN)
888 else IF_KW("osition", 7, YANG_POSITION)
889 else IF_KW_PREFIX("re", 2)
890 IF_KW("fix", 3, YANG_PREFIX)
891 else IF_KW("sence", 5, YANG_PRESENCE)
892 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200893 break;
894 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200895 MOVE_INPUT(ctx, data, 1);
896 IF_KW("ange", 4, YANG_RANGE)
897 else IF_KW_PREFIX("e", 1)
898 IF_KW_PREFIX("f", 1)
899 IF_KW("erence", 6, YANG_REFERENCE)
900 else IF_KW("ine", 3, YANG_REFINE)
901 IF_KW_PREFIX_END
902 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
903 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
904 else IF_KW("vision", 6, YANG_REVISION)
905 IF_KW_PREFIX_END
906 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200907 break;
908 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200909 MOVE_INPUT(ctx, data, 1);
910 IF_KW("tatus", 5, YANG_STATUS)
911 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200912 break;
913 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200914 MOVE_INPUT(ctx, data, 1);
915 IF_KW("ypedef", 6, YANG_TYPEDEF)
916 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200917 break;
918 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200919 MOVE_INPUT(ctx, data, 1);
920 IF_KW_PREFIX("ni", 2)
921 IF_KW("que", 3, YANG_UNIQUE)
922 else IF_KW("ts", 2, YANG_UNITS)
923 IF_KW_PREFIX_END
924 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200925 break;
926 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200927 MOVE_INPUT(ctx, data, 1);
928 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200929 break;
930 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200931 MOVE_INPUT(ctx, data, 1);
932 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200933 break;
934 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200935 MOVE_INPUT(ctx, data, 1);
936 IF_KW("ang-version", 11, YANG_YANG_VERSION)
937 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200938 break;
939 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200940 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200941 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200942 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200943 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200944 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200945 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200946 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200947 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200948 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200949 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200950 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200951 default:
952 break;
953 }
954
Radek Krejci0904c162019-01-02 15:03:59 +0100955#undef IF_KW
956#undef IF_KW_PREFIX
957#undef IF_KW_PREFIX_END
958
Michal Vasko7fbc8162018-09-17 10:35:16 +0200959 if (*kw != YANG_NONE) {
960 /* make sure we have the whole keyword */
961 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200962 case '\n':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200963 case '\t':
Radek Krejciabdd8062019-06-11 16:44:19 +0200964 case ' ':
965 /* mandatory "sep" is just checked, not eaten so nothing in the context is updated */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200966 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200967 case ':':
968 /* keyword is not actually a keyword, but prefix of an extension.
969 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
970 * and we will be checking the keyword (extension instance) itself */
971 prefix = 1;
972 MOVE_INPUT(ctx, data, 1);
973 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200974 case '{':
975 /* allowed only for input and output statements which can be without arguments */
976 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
977 break;
978 }
979 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200980 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200981 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200982 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
983 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200984 return LY_EVALID;
985 }
986 } else {
987 /* still can be an extension */
988 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200989extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200990 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200991 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
992 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200993 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200994 /* check character validity */
995 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200996 }
997 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200998 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200999 return LY_EVALID;
1000 }
1001
1002 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +02001003 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001004 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001005 return LY_EVALID;
1006 }
1007
1008 *kw = YANG_CUSTOM;
1009 }
Radek Krejci626df482018-10-11 15:06:31 +02001010success:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001011 if (word_p) {
1012 *word_p = (char *)word_start;
1013 *word_len = *data - word_start;
1014 }
1015
1016 return LY_SUCCESS;
1017}
1018
Michal Vaskoea5abea2018-09-18 13:10:54 +02001019/**
1020 * @brief Parse extension instance substatements.
1021 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001022 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001023 * @param[in,out] data Data to read from, always moved to currently handled character.
1024 * @param[in] word Extension instance substatement name (keyword).
1025 * @param[in] word_len Extension instance substatement name length.
1026 * @param[in,out] child Children of this extension instance to add to.
1027 *
1028 * @return LY_ERR values.
1029 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001030static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001031parse_ext_substmt(struct lys_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001032 struct lysp_stmt **child)
1033{
1034 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001035 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001036 enum yang_keyword kw;
1037 struct lysp_stmt *stmt, *par_child;
1038
1039 stmt = calloc(1, sizeof *stmt);
1040 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
1041
Radek Krejcibb9b1982019-04-08 14:24:59 +02001042 /* insert into parent statements */
1043 if (!*child) {
1044 *child = stmt;
1045 } else {
1046 for (par_child = *child; par_child->next; par_child = par_child->next);
1047 par_child->next = stmt;
1048 }
1049
Radek Krejci44ceedc2018-10-02 15:54:31 +02001050 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001051
1052 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001053 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001054
Radek Krejci0ae092d2018-09-20 16:43:19 +02001055 if (word) {
1056 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001057 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001058 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001059 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001060 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001061 }
1062
Radek Krejci6d6556c2018-11-08 09:37:45 +01001063 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001064 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001065 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001066 return ret;
1067}
1068
Michal Vaskoea5abea2018-09-18 13:10:54 +02001069/**
1070 * @brief Parse extension instance.
1071 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001072 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001073 * @param[in,out] data Data to read from, always moved to currently handled character.
1074 * @param[in] ext_name Extension instance substatement name (keyword).
1075 * @param[in] ext_name_len Extension instance substatement name length.
1076 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1077 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1078 * @param[in,out] exts Extension instances to add to.
1079 *
1080 * @return LY_ERR values.
1081 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001082static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001083parse_ext(struct lys_parser_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001084 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1085{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001086 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001087 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001088 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001089 struct lysp_ext_instance *e;
1090 enum yang_keyword kw;
1091
Radek Krejci2c4e7172018-10-19 15:56:26 +02001092 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001093
1094 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001095 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001096 e->insubstmt = insubstmt;
1097 e->insubstmt_index = insubstmt_index;
1098
1099 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001100 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001101
Radek Krejci0ae092d2018-09-20 16:43:19 +02001102 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001103 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001104 }
1105
Radek Krejci6d6556c2018-11-08 09:37:45 +01001106 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001107 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001108 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001109 return ret;
1110}
1111
Michal Vaskoea5abea2018-09-18 13:10:54 +02001112/**
1113 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1114 * description, etc...
1115 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001116 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001117 * @param[in,out] data Data to read from, always moved to currently handled character.
1118 * @param[in] substmt Type of this substatement.
1119 * @param[in] substmt_index Index of this substatement.
1120 * @param[in,out] value Place to store the parsed value.
1121 * @param[in] arg Type of the YANG keyword argument (of the value).
1122 * @param[in,out] exts Extension instances to add to.
1123 *
1124 * @return LY_ERR values.
1125 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001126static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001127parse_text_field(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001128 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1129{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001130 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001132 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001133 enum yang_keyword kw;
1134
1135 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001136 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001137 return LY_EVALID;
1138 }
1139
1140 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001141 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001142
1143 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001144 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001145
Radek Krejci6d6556c2018-11-08 09:37:45 +01001146 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001147 switch (kw) {
1148 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001149 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001150 break;
1151 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001152 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001153 return LY_EVALID;
1154 }
1155 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001156 return ret;
1157}
1158
Michal Vaskoea5abea2018-09-18 13:10:54 +02001159/**
1160 * @brief Parse the yang-version statement.
1161 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001162 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001163 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001164 * @param[out] version Storage for the parsed information.
1165 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001166 *
1167 * @return LY_ERR values.
1168 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001169static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001170parse_yangversion(struct lys_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001171{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001172 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001173 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001174 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175 enum yang_keyword kw;
1176
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001177 if (*version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001178 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001179 return LY_EVALID;
1180 }
1181
1182 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001183 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184
1185 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001186 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001187 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001188 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001190 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001191 free(buf);
1192 return LY_EVALID;
1193 }
1194 free(buf);
1195
Radek Krejci6d6556c2018-11-08 09:37:45 +01001196 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001197 switch (kw) {
1198 case YANG_CUSTOM:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001199 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001200 break;
1201 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001202 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001203 return LY_EVALID;
1204 }
1205 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001206 return ret;
1207}
1208
Michal Vaskoea5abea2018-09-18 13:10:54 +02001209/**
1210 * @brief Parse the belongs-to statement.
1211 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001212 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001213 * @param[in,out] data Data to read from, always moved to currently handled character.
1214 * @param[in,out] belongsto Place to store the parsed value.
1215 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1216 * @param[in,out] exts Extension instances to add to.
1217 *
1218 * @return LY_ERR values.
1219 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001220static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001221parse_belongsto(struct lys_parser_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001222{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001223 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001224 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001225 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001226 enum yang_keyword kw;
1227
1228 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001229 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001230 return LY_EVALID;
1231 }
1232
1233 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001234 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001235
Radek Krejci44ceedc2018-10-02 15:54:31 +02001236 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejcif09e4e82019-06-14 15:08:11 +02001237
Radek Krejci6d6556c2018-11-08 09:37:45 +01001238 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001239 switch (kw) {
1240 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001241 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001242 break;
1243 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001244 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001245 break;
1246 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001247 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001248 return LY_EVALID;
1249 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001250 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001251 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001252checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001253 /* mandatory substatements */
1254 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001255 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001256 return LY_EVALID;
1257 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001258 return ret;
1259}
1260
Michal Vaskoea5abea2018-09-18 13:10:54 +02001261/**
1262 * @brief Parse the revision-date statement.
1263 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001264 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001265 * @param[in,out] data Data to read from, always moved to currently handled character.
1266 * @param[in,out] rev Array to store the parsed value in.
1267 * @param[in,out] exts Extension instances to add to.
1268 *
1269 * @return LY_ERR values.
1270 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001271static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001272parse_revisiondate(struct lys_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001273{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001274 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001275 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001276 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001277 enum yang_keyword kw;
1278
1279 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001280 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001281 return LY_EVALID;
1282 }
1283
1284 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001285 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001286
1287 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001288 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001289 free(buf);
1290 return LY_EVALID;
1291 }
1292
1293 /* store value and spend buf if allocated */
1294 strncpy(rev, word, word_len);
1295 free(buf);
1296
Radek Krejci6d6556c2018-11-08 09:37:45 +01001297 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001298 switch (kw) {
1299 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001300 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001301 break;
1302 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001303 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001304 return LY_EVALID;
1305 }
1306 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001307 return ret;
1308}
1309
Michal Vaskoea5abea2018-09-18 13:10:54 +02001310/**
1311 * @brief Parse the include statement.
1312 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001313 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001314 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001315 * @param[in,out] data Data to read from, always moved to currently handled character.
1316 * @param[in,out] includes Parsed includes to add to.
1317 *
1318 * @return LY_ERR values.
1319 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001320static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001321parse_include(struct lys_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001322{
Radek Krejcid33273d2018-10-25 14:55:52 +02001323 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001324 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001325 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001326 enum yang_keyword kw;
1327 struct lysp_include *inc;
1328
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001329 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001330
1331 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001332 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001333
Radek Krejci086c7132018-10-26 15:29:04 +02001334 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1335
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001336 /* submodules share the namespace with the module names, so there must not be
1337 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001338 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001339 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1340 return LY_EVALID;
1341 }
1342
Radek Krejci6d6556c2018-11-08 09:37:45 +01001343 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001344 switch (kw) {
1345 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001346 YANG_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001347 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 +02001348 break;
1349 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001350 YANG_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001351 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 +02001352 break;
1353 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001354 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001355 break;
1356 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001357 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001358 break;
1359 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001360 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001361 return LY_EVALID;
1362 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001363 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001364 return ret;
1365}
1366
Michal Vaskoea5abea2018-09-18 13:10:54 +02001367/**
1368 * @brief Parse the import statement.
1369 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001370 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001371 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001372 * @param[in,out] data Data to read from, always moved to currently handled character.
1373 * @param[in,out] imports Parsed imports to add to.
1374 *
1375 * @return LY_ERR values.
1376 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001377static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001378parse_import(struct lys_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001379{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001380 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001381 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001382 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001383 enum yang_keyword kw;
1384 struct lysp_import *imp;
1385
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001386 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001387
1388 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001389 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001390 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001391
Radek Krejci6d6556c2018-11-08 09:37:45 +01001392 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001393 switch (kw) {
1394 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001395 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001396 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001397 break;
1398 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001399 YANG_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001400 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 +02001401 break;
1402 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001403 YANG_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001404 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 +02001405 break;
1406 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001407 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001408 break;
1409 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001410 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001411 break;
1412 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001413 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001414 return LY_EVALID;
1415 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001416 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001417 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001418checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001419 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001420 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001421
1422 return ret;
1423}
1424
Michal Vaskoea5abea2018-09-18 13:10:54 +02001425/**
1426 * @brief Parse the revision statement.
1427 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001428 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001429 * @param[in,out] data Data to read from, always moved to currently handled character.
1430 * @param[in,out] revs Parsed revisions to add to.
1431 *
1432 * @return LY_ERR values.
1433 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001434static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001435parse_revision(struct lys_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001436{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001437 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001439 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001440 enum yang_keyword kw;
1441 struct lysp_revision *rev;
1442
Radek Krejci2c4e7172018-10-19 15:56:26 +02001443 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001444
1445 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001446 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001447
1448 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001449 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001450 return LY_EVALID;
1451 }
1452
Radek Krejcib7db73a2018-10-24 14:18:40 +02001453 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001454 free(buf);
1455
Radek Krejci6d6556c2018-11-08 09:37:45 +01001456 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001457 switch (kw) {
1458 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001459 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 +02001460 break;
1461 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001462 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 +02001463 break;
1464 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001465 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001466 break;
1467 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001468 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001469 return LY_EVALID;
1470 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001471 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001472 return ret;
1473}
1474
Michal Vaskoea5abea2018-09-18 13:10:54 +02001475/**
1476 * @brief Parse a generic text field that can have more instances such as base.
1477 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001478 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001479 * @param[in,out] data Data to read from, always moved to currently handled character.
1480 * @param[in] substmt Type of this substatement.
1481 * @param[in,out] texts Parsed values to add to.
1482 * @param[in] arg Type of the expected argument.
1483 * @param[in,out] exts Extension instances to add to.
1484 *
1485 * @return LY_ERR values.
1486 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001487static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001488parse_text_fields(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001489 struct lysp_ext_instance **exts)
1490{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001491 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001492 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001493 const char **item;
1494 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001495 enum yang_keyword kw;
1496
1497 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001498 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001499
1500 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001501 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001502
Radek Krejci151a5b72018-10-19 14:21:44 +02001503 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001504 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001505 switch (kw) {
1506 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001507 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001508 break;
1509 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001510 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001511 return LY_EVALID;
1512 }
1513 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001514 return ret;
1515}
1516
Michal Vaskoea5abea2018-09-18 13:10:54 +02001517/**
1518 * @brief Parse the config statement.
1519 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001520 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001521 * @param[in,out] data Data to read from, always moved to currently handled character.
1522 * @param[in,out] flags Flags to add to.
1523 * @param[in,out] exts Extension instances to add to.
1524 *
1525 * @return LY_ERR values.
1526 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001527static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001528parse_config(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001529{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001530 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001531 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001532 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001533 enum yang_keyword kw;
1534
1535 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001536 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001537 return LY_EVALID;
1538 }
1539
1540 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001541 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001542
1543 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1544 *flags |= LYS_CONFIG_W;
1545 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1546 *flags |= LYS_CONFIG_R;
1547 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001548 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001549 free(buf);
1550 return LY_EVALID;
1551 }
1552 free(buf);
1553
Radek Krejci6d6556c2018-11-08 09:37:45 +01001554 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001555 switch (kw) {
1556 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001557 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001558 break;
1559 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001560 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001561 return LY_EVALID;
1562 }
1563 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001564 return ret;
1565}
1566
Michal Vaskoea5abea2018-09-18 13:10:54 +02001567/**
1568 * @brief Parse the mandatory statement.
1569 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001570 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001571 * @param[in,out] data Data to read from, always moved to currently handled character.
1572 * @param[in,out] flags Flags to add to.
1573 * @param[in,out] exts Extension instances to add to.
1574 *
1575 * @return LY_ERR values.
1576 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001577static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001578parse_mandatory(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001579{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001580 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001581 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001582 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001583 enum yang_keyword kw;
1584
1585 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001586 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001587 return LY_EVALID;
1588 }
1589
1590 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001591 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001592
1593 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1594 *flags |= LYS_MAND_TRUE;
1595 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1596 *flags |= LYS_MAND_FALSE;
1597 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001598 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001599 free(buf);
1600 return LY_EVALID;
1601 }
1602 free(buf);
1603
Radek Krejci6d6556c2018-11-08 09:37:45 +01001604 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001605 switch (kw) {
1606 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001607 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001608 break;
1609 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001610 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001611 return LY_EVALID;
1612 }
1613 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001614 return ret;
1615}
1616
Michal Vaskoea5abea2018-09-18 13:10:54 +02001617/**
1618 * @brief Parse a restriction such as range or length.
1619 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001620 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001621 * @param[in,out] data Data to read from, always moved to currently handled character.
1622 * @param[in] restr_kw Type of this particular restriction.
1623 * @param[in,out] exts Extension instances to add to.
1624 *
1625 * @return LY_ERR values.
1626 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001627static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001628parse_restr(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr *restr)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001629{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001630 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001631 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001632 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001633 enum yang_keyword kw;
1634
1635 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001636 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001637
Radek Krejcif09e4e82019-06-14 15:08:11 +02001638 YANG_CHECK_NONEMPTY(ctx, NULL, word_len, ly_stmt2str(restr_kw));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001639 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001640 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001641 switch (kw) {
1642 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001643 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 +02001644 break;
1645 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001646 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 +02001647 break;
1648 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001649 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 +02001650 break;
1651 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001652 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 +02001653 break;
1654 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001655 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001656 break;
1657 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001658 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001659 return LY_EVALID;
1660 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001661 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001662 return ret;
1663}
1664
Michal Vaskoea5abea2018-09-18 13:10:54 +02001665/**
1666 * @brief Parse a restriction that can have more instances such as must.
1667 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001668 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001669 * @param[in,out] data Data to read from, always moved to currently handled character.
1670 * @param[in] restr_kw Type of this particular restriction.
1671 * @param[in,out] restrs Restrictions to add to.
1672 *
1673 * @return LY_ERR values.
1674 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001675static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001676parse_restrs(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr **restrs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001677{
1678 struct lysp_restr *restr;
1679
Radek Krejci2c4e7172018-10-19 15:56:26 +02001680 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001681 return parse_restr(ctx, data, restr_kw, restr);
1682}
1683
Michal Vaskoea5abea2018-09-18 13:10:54 +02001684/**
1685 * @brief Parse the status statement.
1686 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001687 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001688 * @param[in,out] data Data to read from, always moved to currently handled character.
1689 * @param[in,out] flags Flags to add to.
1690 * @param[in,out] exts Extension instances to add to.
1691 *
1692 * @return LY_ERR values.
1693 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001694static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001695parse_status(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001696{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001697 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001698 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001699 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001700 enum yang_keyword kw;
1701
1702 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001703 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001704 return LY_EVALID;
1705 }
1706
1707 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001708 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001709
1710 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1711 *flags |= LYS_STATUS_CURR;
1712 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1713 *flags |= LYS_STATUS_DEPRC;
1714 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1715 *flags |= LYS_STATUS_OBSLT;
1716 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001717 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001718 free(buf);
1719 return LY_EVALID;
1720 }
1721 free(buf);
1722
Radek Krejci6d6556c2018-11-08 09:37:45 +01001723 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001724 switch (kw) {
1725 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001726 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001727 break;
1728 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001729 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001730 return LY_EVALID;
1731 }
1732 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001733 return ret;
1734}
1735
Michal Vaskoea5abea2018-09-18 13:10:54 +02001736/**
1737 * @brief Parse the when statement.
1738 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001739 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001740 * @param[in,out] data Data to read from, always moved to currently handled character.
1741 * @param[in,out] when_p When pointer to parse to.
1742 *
1743 * @return LY_ERR values.
1744 */
Radek Krejcif09e4e82019-06-14 15:08:11 +02001745LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001746parse_when(struct lys_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001747{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001748 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001749 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001750 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001751 enum yang_keyword kw;
1752 struct lysp_when *when;
1753
1754 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001755 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001756 return LY_EVALID;
1757 }
1758
1759 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001760 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001761
1762 /* get value */
Radek Krejci2f54df52019-06-21 10:59:19 +02001763 LY_CHECK_ERR_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len), free(when), LY_EMEM);
Radek Krejcif09e4e82019-06-14 15:08:11 +02001764 YANG_CHECK_NONEMPTY(ctx, when, word_len, "when");
Radek Krejci44ceedc2018-10-02 15:54:31 +02001765 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001766
Radek Krejcif09e4e82019-06-14 15:08:11 +02001767 *when_p = when;
1768
Radek Krejci6d6556c2018-11-08 09:37:45 +01001769 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001770 switch (kw) {
1771 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001772 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 +02001773 break;
1774 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001775 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 +02001776 break;
1777 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001778 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001779 break;
1780 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001781 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001782 return LY_EVALID;
1783 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001784 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001785 return ret;
1786}
1787
Michal Vaskoea5abea2018-09-18 13:10:54 +02001788/**
1789 * @brief Parse the anydata or anyxml statement.
1790 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001791 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001792 * @param[in,out] data Data to read from, always moved to currently handled character.
1793 * @param[in] kw Type of this particular keyword.
1794 * @param[in,out] siblings Siblings to add to.
1795 *
1796 * @return LY_ERR values.
1797 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001798LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001799parse_any(struct lys_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 +02001800{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001801 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001802 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001803 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001804 struct lysp_node *iter;
1805 struct lysp_node_anydata *any;
1806
1807 /* create structure */
1808 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001809 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001810 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001811 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001812
1813 /* insert into siblings */
1814 if (!*siblings) {
1815 *siblings = (struct lysp_node *)any;
1816 } else {
1817 for (iter = *siblings; iter->next; iter = iter->next);
1818 iter->next = (struct lysp_node *)any;
1819 }
1820
1821 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001822 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001823 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001824
1825 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001826 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001827 switch (kw) {
1828 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001829 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001830 break;
1831 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001832 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 +02001833 break;
1834 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001835 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 +02001836 break;
1837 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001838 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001839 break;
1840 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001841 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001842 break;
1843 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001844 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 +02001845 break;
1846 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001847 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001848 break;
1849 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001850 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001851 break;
1852 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001853 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001854 break;
1855 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001856 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001857 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001858 return LY_EVALID;
1859 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001860 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001861 return ret;
1862}
1863
Michal Vaskoea5abea2018-09-18 13:10:54 +02001864/**
1865 * @brief Parse the value or position statement. Substatement of type enum statement.
1866 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001867 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001868 * @param[in,out] data Data to read from, always moved to currently handled character.
1869 * @param[in] val_kw Type of this particular keyword.
1870 * @param[in,out] value Value to write to.
1871 * @param[in,out] flags Flags to write to.
1872 * @param[in,out] exts Extension instances to add to.
1873 *
1874 * @return LY_ERR values.
1875 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001876static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001877parse_type_enum_value_pos(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword val_kw, int64_t *value, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001878 struct lysp_ext_instance **exts)
1879{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001880 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001881 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001882 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001883 long int num;
1884 unsigned long int unum;
1885 enum yang_keyword kw;
1886
1887 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001888 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001889 return LY_EVALID;
1890 }
1891 *flags |= LYS_SET_VALUE;
1892
1893 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001894 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001895
1896 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 +02001897 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001898 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001899 }
1900
1901 errno = 0;
1902 if (val_kw == YANG_VALUE) {
1903 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001904 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
1905 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1906 goto error;
1907 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001908 } else {
1909 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001910 if (unum > UINT64_C(4294967295)) {
1911 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1912 goto error;
1913 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001914 }
1915 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001916 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001917 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001918 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001919 }
1920 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001921 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001922 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001923 }
1924 if (val_kw == YANG_VALUE) {
1925 *value = num;
1926 } else {
1927 *value = unum;
1928 }
1929 free(buf);
1930
Radek Krejci6d6556c2018-11-08 09:37:45 +01001931 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001932 switch (kw) {
1933 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001934 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 +02001935 break;
1936 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001937 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001938 return LY_EVALID;
1939 }
1940 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001941 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001942
1943error:
1944 free(buf);
1945 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001946}
1947
Michal Vaskoea5abea2018-09-18 13:10:54 +02001948/**
1949 * @brief Parse the enum or bit statement. Substatement of type statement.
1950 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001951 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001952 * @param[in,out] data Data to read from, always moved to currently handled character.
1953 * @param[in] enum_kw Type of this particular keyword.
1954 * @param[in,out] enums Enums or bits to add to.
1955 *
1956 * @return LY_ERR values.
1957 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001958static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001959parse_type_enum(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword enum_kw, struct lysp_type_enum **enums)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001960{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001961 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001962 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001963 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001964 enum yang_keyword kw;
1965 struct lysp_type_enum *enm;
1966
Radek Krejci2c4e7172018-10-19 15:56:26 +02001967 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001968
1969 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001970 LY_CHECK_RET(get_argument(ctx, data, enum_kw == YANG_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci8b764662018-11-14 14:15:13 +01001971 if (enum_kw == YANG_ENUM) {
1972 if (!word_len) {
1973 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
1974 free(buf);
1975 return LY_EVALID;
1976 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
1977 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
1978 word_len, word);
1979 free(buf);
1980 return LY_EVALID;
1981 } else {
1982 for (u = 0; u < word_len; ++u) {
1983 if (iscntrl(word[u])) {
1984 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1985 word_len, word, u + 1);
1986 break;
1987 }
1988 }
1989 }
1990 } else { /* YANG_BIT */
1991
1992 }
Radek Krejcif09e4e82019-06-14 15:08:11 +02001993 if (enum_kw == YANG_ENUM) {
1994 YANG_CHECK_NONEMPTY(ctx, NULL, word_len, "enum");
1995 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001996 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001997 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1998
Radek Krejci6d6556c2018-11-08 09:37:45 +01001999 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002000 switch (kw) {
2001 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002002 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 +02002003 break;
2004 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01002005 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002006 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 +02002007 break;
2008 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002009 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 +02002010 break;
2011 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002012 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002013 break;
2014 case YANG_VALUE:
2015 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002016 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002017 break;
2018 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002019 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002020 break;
2021 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002022 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002023 return LY_EVALID;
2024 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002025 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002026 return ret;
2027}
2028
Michal Vaskoea5abea2018-09-18 13:10:54 +02002029/**
2030 * @brief Parse the fraction-digits statement. Substatement of type statement.
2031 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002032 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002033 * @param[in,out] data Data to read from, always moved to currently handled character.
2034 * @param[in,out] fracdig Value to write to.
2035 * @param[in,out] exts Extension instances to add to.
2036 *
2037 * @return LY_ERR values.
2038 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002039static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002040parse_type_fracdigits(struct lys_parser_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002041{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002042 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002043 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002044 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002045 unsigned long int num;
2046 enum yang_keyword kw;
2047
2048 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002049 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002050 return LY_EVALID;
2051 }
2052
2053 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002054 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002055
2056 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002057 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002058 free(buf);
2059 return LY_EVALID;
2060 }
2061
2062 errno = 0;
2063 num = strtoul(word, &ptr, 10);
2064 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002065 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002066 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002067 free(buf);
2068 return LY_EVALID;
2069 }
2070 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002071 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002072 free(buf);
2073 return LY_EVALID;
2074 }
2075 *fracdig = num;
2076 free(buf);
2077
Radek Krejci6d6556c2018-11-08 09:37:45 +01002078 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002079 switch (kw) {
2080 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002081 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002082 break;
2083 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002084 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002085 return LY_EVALID;
2086 }
2087 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002088 return ret;
2089}
2090
Michal Vaskoea5abea2018-09-18 13:10:54 +02002091/**
2092 * @brief Parse the require-instance statement. Substatement of type statement.
2093 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002094 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002095 * @param[in,out] data Data to read from, always moved to currently handled character.
2096 * @param[in,out] reqinst Value to write to.
2097 * @param[in,out] flags Flags to write to.
2098 * @param[in,out] exts Extension instances to add to.
2099 *
2100 * @return LY_ERR values.
2101 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002102static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002103parse_type_reqinstance(struct lys_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002104 struct lysp_ext_instance **exts)
2105{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002106 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002107 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002108 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002109 enum yang_keyword kw;
2110
2111 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002112 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002113 return LY_EVALID;
2114 }
2115 *flags |= LYS_SET_REQINST;
2116
2117 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002118 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002119
2120 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2121 *reqinst = 1;
2122 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002123 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002124 free(buf);
2125 return LY_EVALID;
2126 }
2127 free(buf);
2128
Radek Krejci6d6556c2018-11-08 09:37:45 +01002129 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002130 switch (kw) {
2131 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002132 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002133 break;
2134 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002135 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002136 return LY_EVALID;
2137 }
2138 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002139 return ret;
2140}
2141
Michal Vaskoea5abea2018-09-18 13:10:54 +02002142/**
2143 * @brief Parse the modifier statement. Substatement of type pattern statement.
2144 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002145 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002146 * @param[in,out] data Data to read from, always moved to currently handled character.
2147 * @param[in,out] pat Value to write to.
2148 * @param[in,out] exts Extension instances to add to.
2149 *
2150 * @return LY_ERR values.
2151 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002152static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002153parse_type_pattern_modifier(struct lys_parser_ctx *ctx, const char **data, const char **pat, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002154{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002155 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002156 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002157 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002158 enum yang_keyword kw;
2159
2160 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002161 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002162 return LY_EVALID;
2163 }
2164
2165 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002166 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002167
2168 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002169 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002170 free(buf);
2171 return LY_EVALID;
2172 }
2173 free(buf);
2174
2175 /* replace the value in the dictionary */
2176 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002177 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002178 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002179 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002180
2181 assert(buf[0] == 0x06);
2182 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002183 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002184
Radek Krejci6d6556c2018-11-08 09:37:45 +01002185 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002186 switch (kw) {
2187 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002188 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189 break;
2190 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002191 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002192 return LY_EVALID;
2193 }
2194 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002195 return ret;
2196}
2197
Michal Vaskoea5abea2018-09-18 13:10:54 +02002198/**
2199 * @brief Parse the pattern statement. Substatement of type statement.
2200 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002201 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002202 * @param[in,out] data Data to read from, always moved to currently handled character.
2203 * @param[in,out] patterns Restrictions to add to.
2204 *
2205 * @return LY_ERR values.
2206 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002207static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002208parse_type_pattern(struct lys_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002209{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002210 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002211 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002212 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002213 enum yang_keyword kw;
2214 struct lysp_restr *restr;
2215
Radek Krejci2c4e7172018-10-19 15:56:26 +02002216 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002217
2218 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002219 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002220
2221 /* add special meaning first byte */
2222 if (buf) {
2223 buf = realloc(buf, word_len + 2);
2224 word = buf;
2225 } else {
2226 buf = malloc(word_len + 2);
2227 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002228 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002229 memmove(buf + 1, word, word_len);
2230 buf[0] = 0x06; /* pattern's default regular-match flag */
2231 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2232 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002233
Radek Krejci6d6556c2018-11-08 09:37:45 +01002234 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002235 switch (kw) {
2236 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002237 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 +02002238 break;
2239 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002240 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 +02002241 break;
2242 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002243 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 +02002244 break;
2245 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002246 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 +02002247 break;
2248 case YANG_MODIFIER:
Radek Krejciceaf2122019-01-02 15:03:26 +01002249 YANG_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002250 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002251 break;
2252 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002253 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002254 break;
2255 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002256 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002257 return LY_EVALID;
2258 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002259 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002260 return ret;
2261}
2262
Michal Vaskoea5abea2018-09-18 13:10:54 +02002263/**
2264 * @brief Parse the type statement.
2265 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002266 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002267 * @param[in,out] data Data to read from, always moved to currently handled character.
2268 * @param[in,out] type Type to wrote to.
2269 *
2270 * @return LY_ERR values.
2271 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002272static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002273parse_type(struct lys_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002274{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002275 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002276 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002277 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002278 enum yang_keyword kw;
2279 struct lysp_type *nest_type;
2280
2281 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002282 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002283 return LY_EVALID;
2284 }
2285
2286 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002287 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002288 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002289
Radek Krejci6d6556c2018-11-08 09:37:45 +01002290 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002291 switch (kw) {
2292 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002293 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002294 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002295 break;
2296 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002297 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002298 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002299 break;
2300 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002301 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002302 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002303 break;
2304 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002305 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002306 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002307 break;
2308 case YANG_LENGTH:
2309 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002310 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002311 return LY_EVALID;
2312 }
2313 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002314 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002315
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002316 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002317 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002318 break;
2319 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002320 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002321 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002322 break;
2323 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002324 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002325 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002326 break;
2327 case YANG_RANGE:
2328 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002329 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002330 return LY_EVALID;
2331 }
2332 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002333 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002334
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002335 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002336 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002337 break;
2338 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002339 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002340 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002341 break;
2342 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002343 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2344 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002345 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002346 break;
2347 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002348 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002349 break;
2350 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002351 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002352 return LY_EVALID;
2353 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002354 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002355 return ret;
2356}
2357
Michal Vaskoea5abea2018-09-18 13:10:54 +02002358/**
2359 * @brief Parse the leaf statement.
2360 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002361 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002362 * @param[in,out] data Data to read from, always moved to currently handled character.
2363 * @param[in,out] siblings Siblings to add to.
2364 *
2365 * @return LY_ERR values.
2366 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002367LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002368parse_leaf(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002369{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002370 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002371 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002372 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002373 enum yang_keyword kw;
2374 struct lysp_node *iter;
2375 struct lysp_node_leaf *leaf;
2376
2377 /* create structure */
2378 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002379 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002380 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002381 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002382
2383 /* insert into siblings */
2384 if (!*siblings) {
2385 *siblings = (struct lysp_node *)leaf;
2386 } else {
2387 for (iter = *siblings; iter->next; iter = iter->next);
2388 iter->next = (struct lysp_node *)leaf;
2389 }
2390
2391 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002392 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002393 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002394
2395 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002396 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002397 switch (kw) {
2398 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002399 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002400 break;
2401 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002402 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 +02002403 break;
2404 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002405 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 +02002406 break;
2407 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002408 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 +02002409 break;
2410 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002411 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002412 break;
2413 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002414 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002415 break;
2416 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002417 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 +02002418 break;
2419 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002420 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002421 break;
2422 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002423 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002424 break;
2425 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002426 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 +02002427 break;
2428 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002429 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002430 break;
2431 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002432 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002433 break;
2434 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002435 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002436 return LY_EVALID;
2437 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002438 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002439 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002440checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002441 /* mandatory substatements */
2442 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002443 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002444 return LY_EVALID;
2445 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002446 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
2447 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
2448 return LY_EVALID;
2449 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002450
2451 return ret;
2452}
2453
Michal Vaskoea5abea2018-09-18 13:10:54 +02002454/**
2455 * @brief Parse the max-elements statement.
2456 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002457 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002458 * @param[in,out] data Data to read from, always moved to currently handled character.
2459 * @param[in,out] max Value to write to.
2460 * @param[in,out] flags Flags to write to.
2461 * @param[in,out] exts Extension instances to add to.
2462 *
2463 * @return LY_ERR values.
2464 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002465LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002466parse_maxelements(struct lys_parser_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002467{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002468 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002469 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002470 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002471 unsigned long int num;
2472 enum yang_keyword kw;
2473
2474 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002475 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002476 return LY_EVALID;
2477 }
2478 *flags |= LYS_SET_MAX;
2479
2480 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002481 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002482
2483 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002484 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485 free(buf);
2486 return LY_EVALID;
2487 }
2488
2489 if (strncmp(word, "unbounded", word_len)) {
2490 errno = 0;
2491 num = strtoul(word, &ptr, 10);
2492 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002493 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002494 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002495 free(buf);
2496 return LY_EVALID;
2497 }
2498 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002499 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002500 free(buf);
2501 return LY_EVALID;
2502 }
2503
2504 *max = num;
2505 }
2506 free(buf);
2507
Radek Krejci6d6556c2018-11-08 09:37:45 +01002508 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002509 switch (kw) {
2510 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002511 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002512 break;
2513 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002514 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002515 return LY_EVALID;
2516 }
2517 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002518 return ret;
2519}
2520
Michal Vaskoea5abea2018-09-18 13:10:54 +02002521/**
2522 * @brief Parse the min-elements statement.
2523 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002524 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002525 * @param[in,out] data Data to read from, always moved to currently handled character.
2526 * @param[in,out] min Value to write to.
2527 * @param[in,out] flags Flags to write to.
2528 * @param[in,out] exts Extension instances to add to.
2529 *
2530 * @return LY_ERR values.
2531 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002532LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002533parse_minelements(struct lys_parser_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002534{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002535 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002536 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002537 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002538 unsigned long int num;
2539 enum yang_keyword kw;
2540
2541 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002542 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002543 return LY_EVALID;
2544 }
2545 *flags |= LYS_SET_MIN;
2546
2547 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002548 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002549
2550 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002551 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002552 free(buf);
2553 return LY_EVALID;
2554 }
2555
2556 errno = 0;
2557 num = strtoul(word, &ptr, 10);
2558 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002559 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002560 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002561 free(buf);
2562 return LY_EVALID;
2563 }
2564 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002565 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002566 free(buf);
2567 return LY_EVALID;
2568 }
2569 *min = num;
2570 free(buf);
2571
Radek Krejci6d6556c2018-11-08 09:37:45 +01002572 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002573 switch (kw) {
2574 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002575 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002576 break;
2577 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002578 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002579 return LY_EVALID;
2580 }
2581 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002582 return ret;
2583}
2584
Michal Vaskoea5abea2018-09-18 13:10:54 +02002585/**
2586 * @brief Parse the ordered-by statement.
2587 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002588 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002589 * @param[in,out] data Data to read from, always moved to currently handled character.
2590 * @param[in,out] flags Flags to write to.
2591 * @param[in,out] exts Extension instances to add to.
2592 *
2593 * @return LY_ERR values.
2594 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002595static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002596parse_orderedby(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002597{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002598 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002599 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002600 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002601 enum yang_keyword kw;
2602
2603 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002604 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002605 return LY_EVALID;
2606 }
2607
2608 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002609 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002610
2611 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2612 *flags |= LYS_ORDBY_SYSTEM;
2613 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2614 *flags |= LYS_ORDBY_USER;
2615 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002616 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002617 free(buf);
2618 return LY_EVALID;
2619 }
2620 free(buf);
2621
Radek Krejci6d6556c2018-11-08 09:37:45 +01002622 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002623 switch (kw) {
2624 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002625 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002626 break;
2627 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002628 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002629 return LY_EVALID;
2630 }
2631 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002632 return ret;
2633}
2634
Michal Vaskoea5abea2018-09-18 13:10:54 +02002635/**
2636 * @brief Parse the leaf-list statement.
2637 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002638 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002639 * @param[in,out] data Data to read from, always moved to currently handled character.
2640 * @param[in,out] siblings Siblings to add to.
2641 *
2642 * @return LY_ERR values.
2643 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002644LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002645parse_leaflist(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002646{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002647 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002648 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002649 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002650 enum yang_keyword kw;
2651 struct lysp_node *iter;
2652 struct lysp_node_leaflist *llist;
2653
2654 /* create structure */
2655 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002656 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002657 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002658 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002659
2660 /* insert into siblings */
2661 if (!*siblings) {
2662 *siblings = (struct lysp_node *)llist;
2663 } else {
2664 for (iter = *siblings; iter->next; iter = iter->next);
2665 iter->next = (struct lysp_node *)llist;
2666 }
2667
2668 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002669 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002670 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671
2672 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002673 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002674 switch (kw) {
2675 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002676 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002677 break;
2678 case YANG_DEFAULT:
Radek Krejciceaf2122019-01-02 15:03:26 +01002679 YANG_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002680 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 +02002681 break;
2682 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002683 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 +02002684 break;
2685 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002686 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 +02002687 break;
2688 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002689 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002690 break;
2691 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002692 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002693 break;
2694 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002695 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002696 break;
2697 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002698 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002699 break;
2700 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002701 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 +02002702 break;
2703 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002704 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002705 break;
2706 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002707 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002708 break;
2709 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002710 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 +02002711 break;
2712 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002713 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002714 break;
2715 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002716 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002717 break;
2718 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002719 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002720 return LY_EVALID;
2721 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002722 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002723 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002724checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002725 /* mandatory substatements */
2726 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002727 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002728 return LY_EVALID;
2729 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002730 if ((llist->min) && (llist->dflts)) {
2731 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
2732 return LY_EVALID;
2733 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002734 if (llist->max && llist->min > llist->max) {
2735 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
2736 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2737 llist->min, llist->max);
2738 return LY_EVALID;
2739 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002740
2741 return ret;
2742}
2743
Michal Vaskoea5abea2018-09-18 13:10:54 +02002744/**
2745 * @brief Parse the refine statement.
2746 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002747 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002748 * @param[in,out] data Data to read from, always moved to currently handled character.
2749 * @param[in,out] refines Refines to add to.
2750 *
2751 * @return LY_ERR values.
2752 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002753static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002754parse_refine(struct lys_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002755{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002756 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002757 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002758 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002759 enum yang_keyword kw;
2760 struct lysp_refine *rf;
2761
Radek Krejci2c4e7172018-10-19 15:56:26 +02002762 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002763
2764 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002765 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejcif09e4e82019-06-14 15:08:11 +02002766 YANG_CHECK_NONEMPTY(ctx, NULL, word_len, "refine");
Radek Krejci44ceedc2018-10-02 15:54:31 +02002767 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002768
Radek Krejci6d6556c2018-11-08 09:37:45 +01002769 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002770 switch (kw) {
2771 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002772 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002773 break;
2774 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002775 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 +02002776 break;
2777 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002778 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 +02002779 break;
2780 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01002781 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002782 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 +02002783 break;
2784 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002785 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002786 break;
2787 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002788 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002789 break;
2790 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002791 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002792 break;
2793 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002794 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002795 break;
2796 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002797 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 +02002798 break;
2799 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002800 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 +02002801 break;
2802 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002803 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002804 break;
2805 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002806 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002807 return LY_EVALID;
2808 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002810 return ret;
2811}
2812
Michal Vaskoea5abea2018-09-18 13:10:54 +02002813/**
2814 * @brief Parse the typedef statement.
2815 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002816 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002817 * @param[in,out] data Data to read from, always moved to currently handled character.
2818 * @param[in,out] typedefs Typedefs to add to.
2819 *
2820 * @return LY_ERR values.
2821 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002822static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002823parse_typedef(struct lys_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002824{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002825 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002826 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002827 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002828 enum yang_keyword kw;
2829 struct lysp_tpdf *tpdf;
2830
Radek Krejci2c4e7172018-10-19 15:56:26 +02002831 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002832
2833 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002834 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002835 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002836
2837 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002838 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002839 switch (kw) {
2840 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002841 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 +02002842 break;
2843 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002844 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 +02002845 break;
2846 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002847 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 +02002848 break;
2849 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002850 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002851 break;
2852 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002853 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002854 break;
2855 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002856 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 +02002857 break;
2858 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002859 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 break;
2861 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002862 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863 return LY_EVALID;
2864 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002865 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002866 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002867checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002868 /* mandatory substatements */
2869 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002870 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002871 return LY_EVALID;
2872 }
2873
Radek Krejcibbe09a92018-11-08 09:36:54 +01002874 /* store data for collision check */
Radek Krejci7fc68292019-06-12 13:51:09 +02002875 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01002876 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2877 }
2878
Michal Vasko7fbc8162018-09-17 10:35:16 +02002879 return ret;
2880}
2881
Michal Vaskoea5abea2018-09-18 13:10:54 +02002882/**
2883 * @brief Parse the input or output statement.
2884 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002885 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002886 * @param[in,out] data Data to read from, always moved to currently handled character.
2887 * @param[in] kw Type of this particular keyword
2888 * @param[in,out] inout_p Input/output pointer to write to.
2889 *
2890 * @return LY_ERR values.
2891 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002892static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002893parse_inout(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword inout_kw, struct lysp_node *parent, struct lysp_action_inout *inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002894{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002895 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002896 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002897 size_t word_len;
Radek Krejci10113652018-11-14 16:56:50 +01002898 enum yang_keyword kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002899
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002900 if (inout_p->nodetype) {
Radek Krejci10113652018-11-14 16:56:50 +01002901 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002902 return LY_EVALID;
2903 }
2904
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002905 /* initiate structure */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002906 inout_p->nodetype = &((struct lysp_action*)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002907 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002908
2909 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02002910 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002911 switch (kw) {
2912 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002913 YANG_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002914 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002915 case YANG_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002916 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002917 break;
2918 case YANG_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002919 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002920 break;
2921 case YANG_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002922 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002923 break;
2924 case YANG_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002925 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002926 break;
2927 case YANG_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002928 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002929 break;
2930 case YANG_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002931 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932 break;
2933 case YANG_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002934 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002935 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002936 case YANG_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002937 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002938 break;
2939 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002940 YANG_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002941 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002942 break;
2943 case YANG_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002944 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002945 break;
2946 case YANG_CUSTOM:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002947 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002948 break;
2949 default:
Radek Krejci10113652018-11-14 16:56:50 +01002950 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002951 return LY_EVALID;
2952 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002953 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002954 LY_CHECK_RET(ret);
2955checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002956 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02002957 LY_CHECK_RET(parse_finalize_reallocated(ctx, inout_p->groupings, NULL, NULL, NULL));
2958
Michal Vasko7fbc8162018-09-17 10:35:16 +02002959 return ret;
2960}
2961
Michal Vaskoea5abea2018-09-18 13:10:54 +02002962/**
2963 * @brief Parse the action statement.
2964 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002965 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002966 * @param[in,out] data Data to read from, always moved to currently handled character.
2967 * @param[in,out] actions Actions to add to.
2968 *
2969 * @return LY_ERR values.
2970 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002971LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002972parse_action(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002973{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002974 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002976 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002977 enum yang_keyword kw;
2978 struct lysp_action *act;
2979
Radek Krejci2c4e7172018-10-19 15:56:26 +02002980 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002981
2982 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002983 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002984 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002985 act->nodetype = LYS_ACTION;
2986 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002987
Radek Krejci7fc68292019-06-12 13:51:09 +02002988 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002989 switch (kw) {
2990 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002991 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 +02002992 break;
2993 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002994 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 +02002995 break;
2996 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002997 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 +02002998 break;
2999 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003000 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003001 break;
3002
3003 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003004 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003005 break;
3006 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003007 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003008 break;
3009
3010 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003011 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003012 break;
3013 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003014 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003015 break;
3016 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003017 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003018 break;
3019 default:
Radek Krejcif538ce52019-03-05 10:46:14 +01003020 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003021 return LY_EVALID;
3022 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003023 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003024 LY_CHECK_RET(ret);
3025checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003026 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02003027 LY_CHECK_RET(parse_finalize_reallocated(ctx, act->groupings, NULL, NULL, NULL));
3028
Michal Vasko7fbc8162018-09-17 10:35:16 +02003029 return ret;
3030}
3031
Michal Vaskoea5abea2018-09-18 13:10:54 +02003032/**
3033 * @brief Parse the notification statement.
3034 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003035 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003036 * @param[in,out] data Data to read from, always moved to currently handled character.
3037 * @param[in,out] notifs Notifications to add to.
3038 *
3039 * @return LY_ERR values.
3040 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003041LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003042parse_notif(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003043{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003044 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003045 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003046 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003047 enum yang_keyword kw;
3048 struct lysp_notif *notif;
3049
Radek Krejci2c4e7172018-10-19 15:56:26 +02003050 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003051
3052 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003053 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003054 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003055 notif->nodetype = LYS_NOTIF;
3056 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003057
Radek Krejci7fc68292019-06-12 13:51:09 +02003058 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003059 switch (kw) {
3060 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003061 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 +02003062 break;
3063 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003064 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 +02003065 break;
3066 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003067 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 +02003068 break;
3069 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003070 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071 break;
3072
3073 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003074 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01003075 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003077 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003078 break;
3079 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003080 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003081 break;
3082 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003083 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003084 break;
3085 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003086 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003087 break;
3088 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003089 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003090 break;
3091 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003092 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003093 break;
3094 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003095 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003096 break;
3097
3098 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01003099 YANG_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003100 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003101 break;
3102 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003103 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003104 break;
3105 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003106 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003107 break;
3108 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003109 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003110 break;
3111 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003112 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003113 return LY_EVALID;
3114 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003115 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003116 LY_CHECK_RET(ret);
3117checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003118 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02003119 LY_CHECK_RET(parse_finalize_reallocated(ctx, notif->groupings, NULL, NULL, NULL));
3120
Michal Vasko7fbc8162018-09-17 10:35:16 +02003121 return ret;
3122}
3123
Michal Vaskoea5abea2018-09-18 13:10:54 +02003124/**
3125 * @brief Parse the grouping statement.
3126 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003127 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003128 * @param[in,out] data Data to read from, always moved to currently handled character.
3129 * @param[in,out] groupings Groupings to add to.
3130 *
3131 * @return LY_ERR values.
3132 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003133LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003134parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003136 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003137 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003138 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003139 enum yang_keyword kw;
3140 struct lysp_grp *grp;
3141
Radek Krejci2c4e7172018-10-19 15:56:26 +02003142 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003143
3144 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003145 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003146 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003147 grp->nodetype = LYS_GROUPING;
3148 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003149
Radek Krejci7fc68292019-06-12 13:51:09 +02003150 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003151 switch (kw) {
3152 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003153 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 +02003154 break;
3155 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003156 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 +02003157 break;
3158 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003159 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003160 break;
3161
3162 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003163 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01003164 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003165 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003166 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003167 break;
3168 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003169 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003170 break;
3171 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003172 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003173 break;
3174 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003175 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003176 break;
3177 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003178 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003179 break;
3180 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003181 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003182 break;
3183 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003184 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003185 break;
3186
3187 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003188 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003189 break;
3190 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003191 YANG_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003192 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003193 break;
3194 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003195 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003196 break;
3197 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003198 YANG_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003199 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003200 break;
3201 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003202 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003203 break;
3204 default:
Radek Krejci10113652018-11-14 16:56:50 +01003205 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003206 return LY_EVALID;
3207 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003208 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003209 LY_CHECK_RET(ret);
3210checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003211 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02003212 LY_CHECK_RET(parse_finalize_reallocated(ctx, grp->groupings, NULL, grp->actions, grp->notifs));
3213
Michal Vasko7fbc8162018-09-17 10:35:16 +02003214 return ret;
3215}
3216
Michal Vaskoea5abea2018-09-18 13:10:54 +02003217/**
3218 * @brief Parse the refine statement.
3219 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003220 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003221 * @param[in,out] data Data to read from, always moved to currently handled character.
3222 * @param[in,out] augments Augments to add to.
3223 *
3224 * @return LY_ERR values.
3225 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003226LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003227parse_augment(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003228{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003229 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003230 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003231 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003232 enum yang_keyword kw;
3233 struct lysp_augment *aug;
3234
Radek Krejci2c4e7172018-10-19 15:56:26 +02003235 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003236
3237 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003238 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejcif09e4e82019-06-14 15:08:11 +02003239 YANG_CHECK_NONEMPTY(ctx, NULL, word_len, "augment");
Radek Krejci44ceedc2018-10-02 15:54:31 +02003240 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003241 aug->nodetype = LYS_AUGMENT;
3242 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003243
Radek Krejci7fc68292019-06-12 13:51:09 +02003244 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003245 switch (kw) {
3246 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003247 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 +02003248 break;
3249 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003250 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 +02003251 break;
3252 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003253 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 +02003254 break;
3255 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003256 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003257 break;
3258 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003259 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003260 break;
3261
3262 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003263 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01003264 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003265 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003266 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003267 break;
3268 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003269 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003270 break;
3271 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003272 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003273 break;
3274 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003275 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003276 break;
3277 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003278 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003279 break;
3280 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003281 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003282 break;
3283 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003284 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003285 break;
3286 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003287 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003288 break;
3289
3290 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003291 YANG_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003292 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003293 break;
3294 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003295 YANG_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003296 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 break;
3298 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003299 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003300 break;
3301 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003302 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003303 return LY_EVALID;
3304 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003305 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003306 LY_CHECK_RET(ret);
3307checks:
3308 /* finalize parent pointers to the reallocated items */
3309 LY_CHECK_RET(parse_finalize_reallocated(ctx, NULL, NULL, aug->actions, aug->notifs));
3310
Michal Vasko7fbc8162018-09-17 10:35:16 +02003311 return ret;
3312}
3313
Michal Vaskoea5abea2018-09-18 13:10:54 +02003314/**
Radek Krejci7fc68292019-06-12 13:51:09 +02003315 * @brief Finalize some of the structures in case they are stored in sized array,
3316 * which can be possibly reallocated and some other data may point to them.
3317 *
3318 * Update parent pointers in the nodes inside grouping/augment/RPC/Notification, which could be reallocated.
3319 *
3320 * @param[in] mod Parsed module to be updated.
3321 * @return LY_ERR value (currently only LY_SUCCESS, but it can change in future).
3322 */
3323static LY_ERR
3324parse_finalize_reallocated(struct lys_parser_ctx *ctx, struct lysp_grp *groupings, struct lysp_augment *augments,
3325 struct lysp_action *actions, struct lysp_notif *notifs)
3326{
3327 unsigned int u, v;
3328 struct lysp_node *child;
3329
3330 /* finalize parent pointers to the reallocated items */
3331
3332 /* gropings */
3333 LY_ARRAY_FOR(groupings, u) {
3334 LY_LIST_FOR(groupings[u].data, child) {
3335 child->parent = (struct lysp_node*)&groupings[u];
3336 }
3337 LY_ARRAY_FOR(groupings[u].actions, v) {
3338 groupings[u].actions[v].parent = (struct lysp_node*)&groupings[u];
3339 }
3340 LY_ARRAY_FOR(groupings[u].notifs, v) {
3341 groupings[u].notifs[v].parent = (struct lysp_node*)&groupings[u];
3342 }
3343 LY_ARRAY_FOR(groupings[u].groupings, v) {
3344 groupings[u].groupings[v].parent = (struct lysp_node*)&groupings[u];
3345 }
3346 if (groupings[u].typedefs) {
3347 ly_set_add(&ctx->tpdfs_nodes, &groupings[u], 0);
3348 }
3349 }
3350
3351 /* augments */
3352 LY_ARRAY_FOR(augments, u) {
3353 LY_LIST_FOR(augments[u].child, child) {
3354 child->parent = (struct lysp_node*)&augments[u];
3355 }
3356 LY_ARRAY_FOR(augments[u].actions, v) {
3357 augments[u].actions[v].parent = (struct lysp_node*)&augments[u];
3358 }
3359 LY_ARRAY_FOR(augments[u].notifs, v) {
3360 augments[u].notifs[v].parent = (struct lysp_node*)&augments[u];
3361 }
3362 }
3363
3364 /* actions */
3365 LY_ARRAY_FOR(actions, u) {
3366 if (actions[u].input.parent) {
3367 actions[u].input.parent = (struct lysp_node*)&actions[u];
3368 LY_LIST_FOR(actions[u].input.data, child) {
3369 child->parent = (struct lysp_node*)&actions[u].input;
3370 }
3371 LY_ARRAY_FOR(actions[u].input.groupings, v) {
3372 actions[u].input.groupings[v].parent = (struct lysp_node*)&actions[u].input;
3373 }
3374 if (actions[u].input.typedefs) {
3375 ly_set_add(&ctx->tpdfs_nodes, &actions[u].input, 0);
3376 }
3377 }
3378 if (actions[u].output.parent) {
3379 actions[u].output.parent = (struct lysp_node*)&actions[u];
3380 LY_LIST_FOR(actions[u].output.data, child) {
3381 child->parent = (struct lysp_node*)&actions[u].output;
3382 }
3383 LY_ARRAY_FOR(actions[u].output.groupings, v) {
3384 actions[u].output.groupings[v].parent = (struct lysp_node*)&actions[u].output;
3385 }
3386 if (actions[u].output.typedefs) {
3387 ly_set_add(&ctx->tpdfs_nodes, &actions[u].output, 0);
3388 }
3389 }
3390 LY_ARRAY_FOR(actions[u].groupings, v) {
3391 actions[u].groupings[v].parent = (struct lysp_node*)&actions[u];
3392 }
3393 if (actions[u].typedefs) {
3394 ly_set_add(&ctx->tpdfs_nodes, &actions[u], 0);
3395 }
3396 }
3397
3398 /* notifications */
3399 LY_ARRAY_FOR(notifs, u) {
3400 LY_LIST_FOR(notifs[u].data, child) {
3401 child->parent = (struct lysp_node*)&notifs[u];
3402 }
3403 LY_ARRAY_FOR(notifs[u].groupings, v) {
3404 notifs[u].groupings[v].parent = (struct lysp_node*)&notifs[u];
3405 }
3406 if (notifs[u].typedefs) {
3407 ly_set_add(&ctx->tpdfs_nodes, &notifs[u], 0);
3408 }
3409 }
3410
3411 return LY_SUCCESS;
3412}
3413
3414/**
Michal Vaskoea5abea2018-09-18 13:10:54 +02003415 * @brief Parse the uses statement.
3416 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003417 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003418 * @param[in,out] data Data to read from, always moved to currently handled character.
3419 * @param[in,out] siblings Siblings to add to.
3420 *
3421 * @return LY_ERR values.
3422 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003423LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003424parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003425{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003426 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003427 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003428 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003429 enum yang_keyword kw;
3430 struct lysp_node *iter;
3431 struct lysp_node_uses *uses;
3432
3433 /* create structure */
3434 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003435 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003436 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003437 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003438
3439 /* insert into siblings */
3440 if (!*siblings) {
3441 *siblings = (struct lysp_node *)uses;
3442 } else {
3443 for (iter = *siblings; iter->next; iter = iter->next);
3444 iter->next = (struct lysp_node *)uses;
3445 }
3446
3447 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003448 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003449 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003450
3451 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003452 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003453 switch (kw) {
3454 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003455 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 +02003456 break;
3457 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003458 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 +02003459 break;
3460 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003461 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 +02003462 break;
3463 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003464 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003465 break;
3466 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003467 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003468 break;
3469
3470 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003471 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003472 break;
3473 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003474 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003475 break;
3476 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003477 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003478 break;
3479 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003480 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003481 return LY_EVALID;
3482 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003484checks:
3485 /* finalize parent pointers to the reallocated items */
3486 LY_CHECK_RET(parse_finalize_reallocated(ctx, NULL, uses->augments, NULL, NULL));
3487
Michal Vasko7fbc8162018-09-17 10:35:16 +02003488 return ret;
3489}
3490
Michal Vaskoea5abea2018-09-18 13:10:54 +02003491/**
3492 * @brief Parse the case statement.
3493 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003494 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003495 * @param[in,out] data Data to read from, always moved to currently handled character.
3496 * @param[in,out] siblings Siblings to add to.
3497 *
3498 * @return LY_ERR values.
3499 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003500LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003501parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003502{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003503 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003504 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003505 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003506 enum yang_keyword kw;
3507 struct lysp_node *iter;
3508 struct lysp_node_case *cas;
3509
3510 /* create structure */
3511 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003512 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003513 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003514 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003515
3516 /* insert into siblings */
3517 if (!*siblings) {
3518 *siblings = (struct lysp_node *)cas;
3519 } else {
3520 for (iter = *siblings; iter->next; iter = iter->next);
3521 iter->next = (struct lysp_node *)cas;
3522 }
3523
3524 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003525 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003526 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003527
3528 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003529 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530 switch (kw) {
3531 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003532 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 +02003533 break;
3534 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003535 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536 break;
3537 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003538 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003539 break;
3540 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003541 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003542 break;
3543 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003544 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003545 break;
3546
3547 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003548 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003549 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003550 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003551 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003552 break;
3553 case YANG_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003554 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003555 break;
3556 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003557 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 break;
3559 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003560 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561 break;
3562 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003563 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003564 break;
3565 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003566 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567 break;
3568 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003569 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003570 break;
3571 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003572 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003573 break;
3574 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003575 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003576 return LY_EVALID;
3577 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003579 return ret;
3580}
3581
Michal Vaskoea5abea2018-09-18 13:10:54 +02003582/**
3583 * @brief Parse the choice statement.
3584 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003585 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003586 * @param[in,out] data Data to read from, always moved to currently handled character.
3587 * @param[in,out] siblings Siblings to add to.
3588 *
3589 * @return LY_ERR values.
3590 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003591LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003592parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003593{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003594 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003595 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003596 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003597 enum yang_keyword kw;
3598 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003599 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003600
3601 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003602 choice = calloc(1, sizeof *choice);
3603 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3604 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003605 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003606
3607 /* insert into siblings */
3608 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003609 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610 } else {
3611 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003612 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613 }
3614
3615 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003616 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003617 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003618
3619 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003620 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003621 switch (kw) {
3622 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003623 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003624 break;
3625 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003626 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 +02003627 break;
3628 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003629 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 +02003630 break;
3631 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003632 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003633 break;
3634 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003635 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 +02003636 break;
3637 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003638 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003639 break;
3640 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003641 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003642 break;
3643 case YANG_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003644 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_PREF_IDENTIF_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003645 break;
3646
3647 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003648 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003649 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003650 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003651 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003652 break;
3653 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003654 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003655 break;
3656 case YANG_CHOICE:
Radek Krejciceaf2122019-01-02 15:03:26 +01003657 YANG_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003658 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003659 break;
3660 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003661 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003662 break;
3663 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003664 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003665 break;
3666 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003667 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003668 break;
3669 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003670 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003671 break;
3672 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003673 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003674 break;
3675 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003676 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003677 return LY_EVALID;
3678 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003679 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003680 LY_CHECK_RET(ret);
3681checks:
3682 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
3683 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
3684 return LY_EVALID;
3685 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003686 return ret;
3687}
3688
Michal Vaskoea5abea2018-09-18 13:10:54 +02003689/**
3690 * @brief Parse the container statement.
3691 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003692 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003693 * @param[in,out] data Data to read from, always moved to currently handled character.
3694 * @param[in,out] siblings Siblings to add to.
3695 *
3696 * @return LY_ERR values.
3697 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003698LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003699parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003700{
3701 LY_ERR ret = 0;
3702 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003703 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003704 enum yang_keyword kw;
3705 struct lysp_node *iter;
3706 struct lysp_node_container *cont;
3707
3708 /* create structure */
3709 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003710 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003711 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003712 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003713
3714 /* insert into siblings */
3715 if (!*siblings) {
3716 *siblings = (struct lysp_node *)cont;
3717 } else {
3718 for (iter = *siblings; iter->next; iter = iter->next);
3719 iter->next = (struct lysp_node *)cont;
3720 }
3721
3722 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003723 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003724 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725
3726 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003727 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003728 switch (kw) {
3729 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003730 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003731 break;
3732 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003733 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 +02003734 break;
3735 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003736 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 +02003737 break;
3738 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003739 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 +02003740 break;
3741 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003742 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003743 break;
3744 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003745 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746 break;
3747 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003748 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 +02003749 break;
3750
3751 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003752 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003753 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003754 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003755 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003756 break;
3757 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003758 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003759 break;
3760 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003761 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003762 break;
3763 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003764 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003765 break;
3766 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003767 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003768 break;
3769 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003770 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003771 break;
3772 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003773 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003774 break;
3775
3776 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003777 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003778 break;
3779 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003780 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003781 break;
3782 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003783 YANG_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003784 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003785 break;
3786 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003787 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003788 break;
3789 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003790 YANG_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003791 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003792 break;
3793 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003794 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003795 break;
3796 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003797 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003798 return LY_EVALID;
3799 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003800 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003801checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003802 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02003803 LY_CHECK_RET(parse_finalize_reallocated(ctx, cont->groupings, NULL, cont->actions, cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003804 return ret;
3805}
3806
Michal Vaskoea5abea2018-09-18 13:10:54 +02003807/**
3808 * @brief Parse the list statement.
3809 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003810 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003811 * @param[in,out] data Data to read from, always moved to currently handled character.
3812 * @param[in,out] siblings Siblings to add to.
3813 *
3814 * @return LY_ERR values.
3815 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003816LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003817parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003818{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003819 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003820 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003821 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003822 enum yang_keyword kw;
3823 struct lysp_node *iter;
3824 struct lysp_node_list *list;
3825
3826 /* create structure */
3827 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003828 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003829 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003830 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003831
3832 /* insert into siblings */
3833 if (!*siblings) {
3834 *siblings = (struct lysp_node *)list;
3835 } else {
3836 for (iter = *siblings; iter->next; iter = iter->next);
3837 iter->next = (struct lysp_node *)list;
3838 }
3839
3840 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003841 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003842 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003843
3844 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003845 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003846 switch (kw) {
3847 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003848 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003849 break;
3850 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003851 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 +02003852 break;
3853 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003854 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 +02003855 break;
3856 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003857 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 +02003858 break;
3859 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003860 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003861 break;
3862 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003863 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003864 break;
3865 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003866 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 +02003867 break;
3868 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003869 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003870 break;
3871 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003872 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003873 break;
3874 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003875 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003876 break;
3877 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003878 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 +02003879 break;
3880
3881 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003882 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003883 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003884 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003885 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003886 break;
3887 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003888 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003889 break;
3890 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003891 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003892 break;
3893 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003894 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003895 break;
3896 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003897 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003898 break;
3899 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003900 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003901 break;
3902 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003903 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003904 break;
3905
3906 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003907 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908 break;
3909 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003910 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003911 break;
3912 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003913 YANG_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003914 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003915 break;
3916 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003917 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003918 break;
3919 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003920 YANG_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003921 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 break;
3923 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003924 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003925 break;
3926 default:
Radek Krejci10113652018-11-14 16:56:50 +01003927 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003928 return LY_EVALID;
3929 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003930 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003931 LY_CHECK_RET(ret);
3932checks:
Radek Krejci7fc68292019-06-12 13:51:09 +02003933 /* finalize parent pointers to the reallocated items */
3934 LY_CHECK_RET(parse_finalize_reallocated(ctx, list->groupings, NULL, list->actions, list->notifs));
3935
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003936 if (list->max && list->min > list->max) {
3937 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
3938 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3939 list->min, list->max);
3940 return LY_EVALID;
3941 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003942
3943 return ret;
3944}
3945
Michal Vaskoea5abea2018-09-18 13:10:54 +02003946/**
3947 * @brief Parse the yin-element statement.
3948 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003949 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003950 * @param[in,out] data Data to read from, always moved to currently handled character.
3951 * @param[in,out] flags Flags to write to.
3952 * @param[in,out] exts Extension instances to add to.
3953 *
3954 * @return LY_ERR values.
3955 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003956static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003957parse_yinelement(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003958{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003959 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003960 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003961 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003962 enum yang_keyword kw;
3963
3964 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003965 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003966 return LY_EVALID;
3967 }
3968
3969 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003970 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003971
3972 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3973 *flags |= LYS_YINELEM_TRUE;
3974 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3975 *flags |= LYS_YINELEM_FALSE;
3976 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003977 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003978 free(buf);
3979 return LY_EVALID;
3980 }
3981 free(buf);
3982
Radek Krejci6d6556c2018-11-08 09:37:45 +01003983 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003984 switch (kw) {
3985 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003986 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3987 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003988 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003989 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003990 return LY_EVALID;
3991 }
3992 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003993 return ret;
3994}
3995
Michal Vaskoea5abea2018-09-18 13:10:54 +02003996/**
3997 * @brief Parse the yin-element statement.
3998 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003999 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004000 * @param[in,out] data Data to read from, always moved to currently handled character.
4001 * @param[in,out] argument Value to write to.
4002 * @param[in,out] flags Flags to write to.
4003 * @param[in,out] exts Extension instances to add to.
4004 *
4005 * @return LY_ERR values.
4006 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004007static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004008parse_argument(struct lys_parser_ctx *ctx, const char **data, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004009{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004010 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004011 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004012 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004013 enum yang_keyword kw;
4014
4015 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004016 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017 return LY_EVALID;
4018 }
4019
4020 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004021 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004022 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004023
Radek Krejci6d6556c2018-11-08 09:37:45 +01004024 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004025 switch (kw) {
4026 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004027 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004028 break;
4029 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004030 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004031 break;
4032 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004033 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004034 return LY_EVALID;
4035 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004036 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004037 return ret;
4038}
4039
Michal Vaskoea5abea2018-09-18 13:10:54 +02004040/**
4041 * @brief Parse the extension 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] extensions Extensions to add to.
4046 *
4047 * @return LY_ERR values.
4048 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004049static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004050parse_extension(struct lys_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
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_ext *ex;
4057
Radek Krejci2c4e7172018-10-19 15:56:26 +02004058 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004059
4060 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004061 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004062 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004063
Radek Krejci6d6556c2018-11-08 09:37:45 +01004064 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004065 switch (kw) {
4066 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004067 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 +02004068 break;
4069 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004070 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 +02004071 break;
4072 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004073 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004074 break;
4075 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004076 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004077 break;
4078 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004079 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004080 break;
4081 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004082 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004083 return LY_EVALID;
4084 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004085 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004086 return ret;
4087}
4088
Michal Vaskoea5abea2018-09-18 13:10:54 +02004089/**
4090 * @brief Parse the deviate statement.
4091 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004092 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004093 * @param[in,out] data Data to read from, always moved to currently handled character.
4094 * @param[in,out] deviates Deviates to add to.
4095 *
4096 * @return LY_ERR values.
4097 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004098LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004099parse_deviate(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004100{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004101 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004102 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004103 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004104 enum yang_keyword kw;
4105 struct lysp_deviate *iter, *d;
4106 struct lysp_deviate_add *d_add = NULL;
4107 struct lysp_deviate_rpl *d_rpl = NULL;
4108 struct lysp_deviate_del *d_del = NULL;
4109 const char **d_units, ***d_uniques, ***d_dflts;
4110 struct lysp_restr **d_musts;
4111 uint16_t *d_flags;
4112 uint32_t *d_min, *d_max;
4113
4114 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004115 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004116
4117 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4118 dev_mod = LYS_DEV_NOT_SUPPORTED;
4119 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4120 dev_mod = LYS_DEV_ADD;
4121 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4122 dev_mod = LYS_DEV_REPLACE;
4123 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4124 dev_mod = LYS_DEV_DELETE;
4125 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004126 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004127 free(buf);
4128 return LY_EVALID;
4129 }
4130 free(buf);
4131
4132 /* create structure */
4133 switch (dev_mod) {
4134 case LYS_DEV_NOT_SUPPORTED:
4135 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004136 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004137 break;
4138 case LYS_DEV_ADD:
4139 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004140 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004141 d = (struct lysp_deviate *)d_add;
4142 d_units = &d_add->units;
4143 d_uniques = &d_add->uniques;
4144 d_dflts = &d_add->dflts;
4145 d_musts = &d_add->musts;
4146 d_flags = &d_add->flags;
4147 d_min = &d_add->min;
4148 d_max = &d_add->max;
4149 break;
4150 case LYS_DEV_REPLACE:
4151 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004152 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004153 d = (struct lysp_deviate *)d_rpl;
4154 d_units = &d_rpl->units;
4155 d_flags = &d_rpl->flags;
4156 d_min = &d_rpl->min;
4157 d_max = &d_rpl->max;
4158 break;
4159 case LYS_DEV_DELETE:
4160 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004161 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004162 d = (struct lysp_deviate *)d_del;
4163 d_units = &d_del->units;
4164 d_uniques = &d_del->uniques;
4165 d_dflts = &d_del->dflts;
4166 d_musts = &d_del->musts;
4167 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004168 break;
4169 default:
4170 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004171 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004172 }
4173 d->mod = dev_mod;
4174
4175 /* insert into siblings */
4176 if (!*deviates) {
4177 *deviates = d;
4178 } else {
4179 for (iter = *deviates; iter->next; iter = iter->next);
4180 iter->next = d;
4181 }
4182
Radek Krejci6d6556c2018-11-08 09:37:45 +01004183 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004184 switch (kw) {
4185 case YANG_CONFIG:
4186 switch (dev_mod) {
4187 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004188 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004189 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004190 return LY_EVALID;
4191 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004192 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004193 break;
4194 }
4195 break;
4196 case YANG_DEFAULT:
4197 switch (dev_mod) {
4198 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004199 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004200 return LY_EVALID;
4201 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004202 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 +02004203 break;
4204 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004205 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 +02004206 break;
4207 }
4208 break;
4209 case YANG_MANDATORY:
4210 switch (dev_mod) {
4211 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004212 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004213 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004214 return LY_EVALID;
4215 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004216 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004217 break;
4218 }
4219 break;
4220 case YANG_MAX_ELEMENTS:
4221 switch (dev_mod) {
4222 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004223 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004224 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004225 return LY_EVALID;
4226 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004227 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004228 break;
4229 }
4230 break;
4231 case YANG_MIN_ELEMENTS:
4232 switch (dev_mod) {
4233 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004234 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004235 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236 return LY_EVALID;
4237 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004238 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004239 break;
4240 }
4241 break;
4242 case YANG_MUST:
4243 switch (dev_mod) {
4244 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004245 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004246 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004247 return LY_EVALID;
4248 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004249 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004250 break;
4251 }
4252 break;
4253 case YANG_TYPE:
4254 switch (dev_mod) {
4255 case LYS_DEV_NOT_SUPPORTED:
4256 case LYS_DEV_ADD:
4257 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004258 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004259 return LY_EVALID;
4260 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004261 if (d_rpl->type) {
4262 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4263 return LY_EVALID;
4264 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004265 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004266 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004267 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004268 break;
4269 }
4270 break;
4271 case YANG_UNIQUE:
4272 switch (dev_mod) {
4273 case LYS_DEV_NOT_SUPPORTED:
4274 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004275 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004276 return LY_EVALID;
4277 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004278 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 +02004279 break;
4280 }
4281 break;
4282 case YANG_UNITS:
4283 switch (dev_mod) {
4284 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004285 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004286 return LY_EVALID;
4287 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004288 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 +02004289 break;
4290 }
4291 break;
4292 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004293 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004294 break;
4295 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004296 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004297 return LY_EVALID;
4298 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004299 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004300 return ret;
4301}
4302
Michal Vaskoea5abea2018-09-18 13:10:54 +02004303/**
4304 * @brief Parse the deviation statement.
4305 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004306 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004307 * @param[in,out] data Data to read from, always moved to currently handled character.
4308 * @param[in,out] deviations Deviations to add to.
4309 *
4310 * @return LY_ERR values.
4311 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004312LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004313parse_deviation(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004314{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004315 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004317 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004318 enum yang_keyword kw;
4319 struct lysp_deviation *dev;
4320
Radek Krejci2c4e7172018-10-19 15:56:26 +02004321 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004322
4323 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004324 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejcif09e4e82019-06-14 15:08:11 +02004325 YANG_CHECK_NONEMPTY(ctx, NULL, word_len, "deviation");
Radek Krejci44ceedc2018-10-02 15:54:31 +02004326 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004327
Radek Krejci6d6556c2018-11-08 09:37:45 +01004328 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004329 switch (kw) {
4330 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004331 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 +02004332 break;
4333 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004334 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004335 break;
4336 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004337 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 +02004338 break;
4339 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004340 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004341 break;
4342 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004343 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004344 return LY_EVALID;
4345 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004346 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004347 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004348checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004349 /* mandatory substatements */
4350 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004351 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004352 return LY_EVALID;
4353 }
4354
4355 return ret;
4356}
4357
Michal Vaskoea5abea2018-09-18 13:10:54 +02004358/**
4359 * @brief Parse the feature statement.
4360 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004361 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004362 * @param[in,out] data Data to read from, always moved to currently handled character.
4363 * @param[in,out] features Features to add to.
4364 *
4365 * @return LY_ERR values.
4366 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004367LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004368parse_feature(struct lys_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004369{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004370 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004371 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004372 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004373 enum yang_keyword kw;
4374 struct lysp_feature *feat;
4375
Radek Krejci2c4e7172018-10-19 15:56:26 +02004376 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004377
4378 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004379 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004380 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004381
Radek Krejci6d6556c2018-11-08 09:37:45 +01004382 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004383 switch (kw) {
4384 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004385 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 +02004386 break;
4387 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004388 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 +02004389 break;
4390 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004391 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 +02004392 break;
4393 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004394 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004395 break;
4396 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004397 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004398 break;
4399 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004400 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004401 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004402 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004403 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004404 return ret;
4405}
4406
Michal Vaskoea5abea2018-09-18 13:10:54 +02004407/**
4408 * @brief Parse the identity statement.
4409 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004410 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004411 * @param[in,out] data Data to read from, always moved to currently handled character.
4412 * @param[in,out] identities Identities to add to.
4413 *
4414 * @return LY_ERR values.
4415 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004416LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004417parse_identity(struct lys_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004418{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004419 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004420 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004421 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422 enum yang_keyword kw;
4423 struct lysp_ident *ident;
4424
Radek Krejci2c4e7172018-10-19 15:56:26 +02004425 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004426
4427 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004428 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004429 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004430
Radek Krejci6d6556c2018-11-08 09:37:45 +01004431 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004432 switch (kw) {
4433 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004434 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 +02004435 break;
4436 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01004437 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004438 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 +02004439 break;
4440 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004441 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 +02004442 break;
4443 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004444 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004445 break;
4446 case YANG_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004447 if (ident->bases && ctx->mod_version < 2) {
Radek Krejci10113652018-11-14 16:56:50 +01004448 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4449 return LY_EVALID;
4450 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004451 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 +02004452 break;
4453 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004454 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004455 break;
4456 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004457 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004458 return LY_EVALID;
4459 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004460 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004461 return ret;
4462}
4463
Michal Vaskoea5abea2018-09-18 13:10:54 +02004464/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004465 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004466 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004467 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004468 * @param[in,out] data Data to read from, always moved to currently handled character.
4469 * @param[in,out] mod Module to write to.
4470 *
4471 * @return LY_ERR values.
4472 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004473LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004474parse_module(struct lys_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004475{
4476 LY_ERR ret = 0;
4477 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004478 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004479 enum yang_keyword kw, prev_kw = 0;
4480 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004481 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004482
4483 /* (sub)module name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004484 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004485 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004486
Radek Krejci6d6556c2018-11-08 09:37:45 +01004487 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004488
Radek Krejcie3846472018-10-15 15:24:51 +02004489#define CHECK_ORDER(SECTION) \
4490 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4491
Michal Vasko7fbc8162018-09-17 10:35:16 +02004492 switch (kw) {
4493 /* module header */
4494 case YANG_NAMESPACE:
4495 case YANG_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004496 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4497 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004498 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004499 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004500 break;
4501 /* linkage */
4502 case YANG_INCLUDE:
4503 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004504 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004505 break;
4506 /* meta */
4507 case YANG_ORGANIZATION:
4508 case YANG_CONTACT:
4509 case YANG_DESCRIPTION:
4510 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004511 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004512 break;
4513
4514 /* revision */
4515 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004516 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004517 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004518 /* body */
4519 case YANG_ANYDATA:
4520 case YANG_ANYXML:
4521 case YANG_AUGMENT:
4522 case YANG_CHOICE:
4523 case YANG_CONTAINER:
4524 case YANG_DEVIATION:
4525 case YANG_EXTENSION:
4526 case YANG_FEATURE:
4527 case YANG_GROUPING:
4528 case YANG_IDENTITY:
4529 case YANG_LEAF:
4530 case YANG_LEAF_LIST:
4531 case YANG_LIST:
4532 case YANG_NOTIFICATION:
4533 case YANG_RPC:
4534 case YANG_TYPEDEF:
4535 case YANG_USES:
4536 case YANG_CUSTOM:
4537 mod_stmt = Y_MOD_BODY;
4538 break;
4539 default:
4540 /* error handled in the next switch */
4541 break;
4542 }
Radek Krejcie3846472018-10-15 15:24:51 +02004543#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004544
Radek Krejcie3846472018-10-15 15:24:51 +02004545 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004546 switch (kw) {
4547 /* module header */
4548 case YANG_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004549 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4550 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004551 break;
4552 case YANG_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004553 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->mod->ns, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004554 break;
4555 case YANG_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004556 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->mod->prefix, Y_IDENTIF_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004557 break;
4558
4559 /* linkage */
4560 case YANG_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004561 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004562 break;
4563 case YANG_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004564 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004565 break;
4566
4567 /* meta */
4568 case YANG_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004569 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->mod->org, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004570 break;
4571 case YANG_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004572 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->mod->contact, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004573 break;
4574 case YANG_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004575 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->mod->dsc, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004576 break;
4577 case YANG_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004578 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->mod->ref, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004579 break;
4580
4581 /* revision */
4582 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004583 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004584 break;
4585
4586 /* body */
4587 case YANG_ANYDATA:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004588 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004589 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004590 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004591 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004592 break;
4593 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004594 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004595 break;
4596 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004597 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004598 break;
4599 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004600 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004601 break;
4602 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004603 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004604 break;
4605 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004606 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004607 break;
4608 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004609 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004610 break;
4611
4612 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004613 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004614 break;
4615 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004616 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004617 break;
4618 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004619 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004620 break;
4621 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004622 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004623 break;
4624 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004625 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004626 break;
4627 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004628 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004629 break;
4630 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004631 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004632 break;
4633 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004634 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004635 break;
4636 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004637 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004638 break;
4639 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004640 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004641 break;
4642
4643 default:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004644 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004645 return LY_EVALID;
4646 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004647 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004648 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004649
Radek Krejci6d6556c2018-11-08 09:37:45 +01004650checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004651 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02004652 LY_CHECK_RET(parse_finalize_reallocated(ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004653
Michal Vasko7fbc8162018-09-17 10:35:16 +02004654 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004655 if (!mod->mod->ns) {
4656 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
4657 return LY_EVALID;
4658 } else if (!mod->mod->prefix) {
4659 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
4660 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004661 }
4662
Radek Krejcie9e987e2018-10-31 12:50:27 +01004663 /* submodules share the namespace with the module names, so there must not be
4664 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004665 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4666 if (dup) {
4667 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
4668 return LY_EVALID;
4669 }
4670
4671 return ret;
4672}
4673
4674/**
4675 * @brief Parse submodule substatements.
4676 *
4677 * @param[in] ctx yang parser context for logging.
4678 * @param[in,out] data Data to read from, always moved to currently handled character.
4679 * @param[out] submod Parsed submodule structure.
4680 *
4681 * @return LY_ERR values.
4682 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004683LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004684parse_submodule(struct lys_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004685{
4686 LY_ERR ret = 0;
4687 char *buf, *word;
4688 size_t word_len;
4689 enum yang_keyword kw, prev_kw = 0;
4690 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4691 struct lysp_submodule *dup;
4692
4693 /* submodule name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004694 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004695 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4696
4697 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4698
4699#define CHECK_ORDER(SECTION) \
4700 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4701
4702 switch (kw) {
4703 /* module header */
4704 case YANG_BELONGS_TO:
4705 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4706 break;
4707 case YANG_YANG_VERSION:
4708 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4709 break;
4710 /* linkage */
4711 case YANG_INCLUDE:
4712 case YANG_IMPORT:
4713 CHECK_ORDER(Y_MOD_LINKAGE);
4714 break;
4715 /* meta */
4716 case YANG_ORGANIZATION:
4717 case YANG_CONTACT:
4718 case YANG_DESCRIPTION:
4719 case YANG_REFERENCE:
4720 CHECK_ORDER(Y_MOD_META);
4721 break;
4722
4723 /* revision */
4724 case YANG_REVISION:
4725 CHECK_ORDER(Y_MOD_REVISION);
4726 break;
4727 /* body */
4728 case YANG_ANYDATA:
4729 case YANG_ANYXML:
4730 case YANG_AUGMENT:
4731 case YANG_CHOICE:
4732 case YANG_CONTAINER:
4733 case YANG_DEVIATION:
4734 case YANG_EXTENSION:
4735 case YANG_FEATURE:
4736 case YANG_GROUPING:
4737 case YANG_IDENTITY:
4738 case YANG_LEAF:
4739 case YANG_LEAF_LIST:
4740 case YANG_LIST:
4741 case YANG_NOTIFICATION:
4742 case YANG_RPC:
4743 case YANG_TYPEDEF:
4744 case YANG_USES:
4745 case YANG_CUSTOM:
4746 mod_stmt = Y_MOD_BODY;
4747 break;
4748 default:
4749 /* error handled in the next switch */
4750 break;
4751 }
4752#undef CHECK_ORDER
4753
4754 prev_kw = kw;
4755 switch (kw) {
4756 /* module header */
4757 case YANG_YANG_VERSION:
4758 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4759 ctx->mod_version = submod->version;
4760 break;
4761 case YANG_BELONGS_TO:
4762 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4763 break;
4764
4765 /* linkage */
4766 case YANG_INCLUDE:
4767 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4768 break;
4769 case YANG_IMPORT:
4770 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4771 break;
4772
4773 /* meta */
4774 case YANG_ORGANIZATION:
4775 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4776 break;
4777 case YANG_CONTACT:
4778 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4779 break;
4780 case YANG_DESCRIPTION:
4781 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4782 break;
4783 case YANG_REFERENCE:
4784 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4785 break;
4786
4787 /* revision */
4788 case YANG_REVISION:
4789 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4790 break;
4791
4792 /* body */
4793 case YANG_ANYDATA:
4794 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
4795 /* fall through */
4796 case YANG_ANYXML:
4797 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4798 break;
4799 case YANG_CHOICE:
4800 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4801 break;
4802 case YANG_CONTAINER:
4803 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4804 break;
4805 case YANG_LEAF:
4806 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4807 break;
4808 case YANG_LEAF_LIST:
4809 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4810 break;
4811 case YANG_LIST:
4812 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4813 break;
4814 case YANG_USES:
4815 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4816 break;
4817
4818 case YANG_AUGMENT:
4819 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4820 break;
4821 case YANG_DEVIATION:
4822 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4823 break;
4824 case YANG_EXTENSION:
4825 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4826 break;
4827 case YANG_FEATURE:
4828 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4829 break;
4830 case YANG_GROUPING:
4831 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4832 break;
4833 case YANG_IDENTITY:
4834 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4835 break;
4836 case YANG_NOTIFICATION:
4837 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4838 break;
4839 case YANG_RPC:
4840 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4841 break;
4842 case YANG_TYPEDEF:
4843 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4844 break;
4845 case YANG_CUSTOM:
4846 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4847 break;
4848
4849 default:
4850 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
4851 return LY_EVALID;
4852 }
4853 }
4854 LY_CHECK_RET(ret);
4855
4856checks:
4857 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02004858 LY_CHECK_RET(parse_finalize_reallocated(ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004859
4860 /* mandatory substatements */
4861 if (!submod->belongsto) {
4862 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
4863 return LY_EVALID;
4864 }
4865
4866 /* submodules share the namespace with the module names, so there must not be
4867 * a submodule of the same name in the context, no need for revision matching */
4868 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4869 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
4870 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004871 return LY_EVALID;
4872 }
4873
Michal Vasko7fbc8162018-09-17 10:35:16 +02004874 return ret;
4875}
4876
Radek Krejcid4557c62018-09-17 11:42:09 +02004877LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004878yang_parse_submodule(struct lys_parser_ctx *context, const char *data, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004879{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004880 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004881 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004882 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004883 enum yang_keyword kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004884 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004885
4886 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004887 ret = get_keyword(context, &data, &kw, &word, &word_len);
4888 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004889
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004890 if (kw == YANG_MODULE) {
4891 LOGERR(context->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
4892 ret = LY_EINVAL;
4893 goto cleanup;
4894 } else if (kw != YANG_SUBMODULE) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004895 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004896 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004897 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004898 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004899 }
4900
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004901 mod_p = calloc(1, sizeof *mod_p);
4902 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4903 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004904
4905 /* substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004906 ret = parse_submodule(context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004907 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004908
4909 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004910 while(*data && isspace(*data)) {
4911 data++;
4912 }
4913 if (*data) {
4914 LOGVAL_YANG(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
4915 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004916 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004917 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004918 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004919
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004920 mod_p->parsing = 0;
4921 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004922
Radek Krejcibbe09a92018-11-08 09:36:54 +01004923cleanup:
4924 if (ret) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004925 lysp_submodule_free(context->ctx, mod_p);
4926 }
4927
4928 return ret;
4929}
4930
4931LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004932yang_parse_module(struct lys_parser_ctx *context, const char *data, struct lys_module *mod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004933{
4934 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004935 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004936 size_t word_len;
4937 enum yang_keyword kw;
4938 struct lysp_module *mod_p = NULL;
4939
4940 /* "module"/"submodule" */
4941 ret = get_keyword(context, &data, &kw, &word, &word_len);
4942 LY_CHECK_GOTO(ret, cleanup);
4943
4944 if (kw == YANG_SUBMODULE) {
4945 LOGERR(context->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
4946 ret = LY_EINVAL;
4947 goto cleanup;
4948 } else if (kw != YANG_MODULE) {
4949 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
4950 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004951 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004952 goto cleanup;
4953 }
4954
4955 mod_p = calloc(1, sizeof *mod_p);
4956 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4957 mod_p->mod = mod;
4958 mod_p->parsing = 1;
4959
4960 /* substatements */
4961 ret = parse_module(context, &data, mod_p);
4962 LY_CHECK_GOTO(ret, cleanup);
4963
4964 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004965 while(*data && isspace(*data)) {
4966 data++;
4967 }
4968 if (*data) {
4969 LOGVAL_YANG(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
4970 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004971 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004972 goto cleanup;
4973 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004974
4975 mod_p->parsing = 0;
4976 mod->parsed = mod_p;
4977
4978cleanup:
4979 if (ret) {
4980 lysp_module_free(mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004981 }
4982
Michal Vasko7fbc8162018-09-17 10:35:16 +02004983 return ret;
4984}