blob: 83ad888c6d104aeaf1de5974dfb52643c20168a3 [file] [log] [blame]
Michal Vasko7fbc8162018-09-17 10:35:16 +02001/**
2 * @file parser_yang.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YANG parser
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <errno.h>
22#include <ctype.h>
23#include <string.h>
24#include <dirent.h>
25#include <assert.h>
26
27#include "common.h"
28#include "context.h"
29#include "libyang.h"
Radek Krejci70853c52018-10-15 14:46:16 +020030#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020031
32/* Macro to check YANG's yang-char grammar rule */
33#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
34 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
35 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
36 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
37 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
38 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
39 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
40 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
41 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
42 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
43
Radek Krejciceaf2122019-01-02 15:03:26 +010044/**
45 * @brief Try to find object with MEMBER string matching the IDENT in the given ARRAY.
46 * Macro logs an error message and returns LY_EVALID in case of existence of a matching object.
47 *
48 * @param[in] CTX yang parser context for logging.
49 * @param[in] ARRAY [sized array](@ref sizedarrays) of a generic objects with member named MEMBER to search.
50 * @param[in] MEMBER Name of the member of the objects in the ARRAY to compare.
51 * @param[in] STMT Name of the compared YANG statements for logging.
52 * @param[in] IDENT String trying to find in the ARRAY's objects inside the MEMBER member.
53 */
Radek Krejcifaa1eac2018-10-30 14:34:55 +010054#define CHECK_UNIQUENESS(CTX, ARRAY, MEMBER, STMT, IDENT) \
55 if (ARRAY) { \
56 for (unsigned int u = 0; u < LY_ARRAY_SIZE(ARRAY) - 1; ++u) { \
57 if (!strcmp((ARRAY)[u].MEMBER, IDENT)) { \
58 LOGVAL_YANG(CTX, LY_VCODE_DUPIDENT, IDENT, STMT); \
59 return LY_EVALID; \
60 } \
61 } \
62 }
63
Radek Krejciceaf2122019-01-02 15:03:26 +010064/**
65 * @brief Insert WORD into the libyang context's dictionary and store as TARGET.
66 * @param[in] CTX yang parser context to access libyang context.
67 * @param[in] BUF buffer in case the word is not a constant and can be inserted directly (zero-copy)
68 * @param[out] TARGET variable where to store the pointer to the inserted value.
69 * @param[in] WORD string to store.
70 * @param[in] LEN length of the string in WORD to store.
71 */
Radek Krejci9fcacc12018-10-11 15:59:11 +020072#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
73 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
74 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020075
Radek Krejciceaf2122019-01-02 15:03:26 +010076/**
77 * @brief Move the DATA pointer by COUNT items. Also updates the indent value in yang parser context
78 * @param[in] CTX yang parser context to update its indent value.
79 * @param[in,out] DATA pointer to move
80 * @param[in] COUNT number of items for which the DATA pointer is supposed to move on.
81 */
Radek Krejci2b610482019-01-02 13:36:09 +010082#define MOVE_INPUT(CTX, DATA, COUNT) (*(DATA))+=COUNT;(CTX)->indent+=COUNT
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020083
Michal Vaskoea5abea2018-09-18 13:10:54 +020084/**
85 * @brief Loop through all substatements providing, return if there are none.
86 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020087 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020088 * @param[in] DATA Raw data to read from.
89 * @param[out] KW YANG keyword read.
90 * @param[out] WORD Pointer to the keyword itself.
91 * @param[out] WORD_LEN Length of the keyword.
92 * @param[out] ERR Variable for error storing.
93 *
94 * @return In case there are no substatements or a fatal error encountered.
95 */
Radek Krejci6d6556c2018-11-08 09:37:45 +010096#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010097 LY_CHECK_RET(get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020098 if (KW == YANG_SEMICOLON) { \
Radek Krejci6d6556c2018-11-08 09:37:45 +010099 CHECKGOTO; \
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100100 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +0200101 } \
102 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +0200103 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +0200104 return LY_EVALID; \
105 } \
106 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
107 !ERR && (KW != YANG_RIGHT_BRACE); \
108 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
109
Radek Krejciceaf2122019-01-02 15:03:26 +0100110/**
111 * @brief Check module version is at least 2 (YANG 1.1) because of the keyword presence.
112 * Logs error message and returns LY_EVALID in case of module in YANG version 1.0.
113 * @param[in] CTX yang parser context to get current module and for logging.
114 * @param[in] KW keyword allowed only in YANG version 1.1 (or later) - for logging.
115 * @param[in] PARENT parent statement where the KW is present - for logging.
116 */
117#define YANG_CHECK_STMTVER2_RET(CTX, KW, PARENT) \
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100118 if ((CTX)->mod_version < 2) {LOGVAL_YANG((CTX), LY_VCODE_INCHILDSTMT2, KW, PARENT); return LY_EVALID;}
Radek Krejci10113652018-11-14 16:56:50 +0100119
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100120static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
121static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
122static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
123static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
124static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
125static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200126
Michal Vaskoea5abea2018-09-18 13:10:54 +0200127/**
128 * @brief Add another character to dynamic buffer, a low-level function.
129 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200130 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200131 *
Radek Krejci404251e2018-10-09 12:06:44 +0200132 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200133 * @param[in, out] input Input string to process.
134 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200135 * @param[in,out] buf Buffer to use, can be moved by realloc().
136 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200137 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200138 *
139 * @return LY_ERR values.
140 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200141static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200142buf_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 +0200143{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200144 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200145 *buf_len += 16;
146 *buf = ly_realloc(*buf, *buf_len);
147 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
148 }
Radek Krejcic0917392019-04-10 13:04:04 +0200149 if (*buf_used) {
150 memcpy(&(*buf)[*buf_used], *input, len);
151 } else {
152 memcpy(*buf, *input, len);
153 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200154
Radek Krejci44ceedc2018-10-02 15:54:31 +0200155 (*buf_used) += len;
156 (*input) += len;
157
Michal Vasko7fbc8162018-09-17 10:35:16 +0200158 return LY_SUCCESS;
159}
160
Michal Vaskoea5abea2018-09-18 13:10:54 +0200161/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200162 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200163 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200164 * @param[in] ctx yang parser context for logging.
165 * @param[in] c UTF8 code point of a character to check.
166 * @return LY_ERR values.
167 */
168static LY_ERR
169check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
170{
171 if (!is_yangutf8char(c)) {
172 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
173 return LY_EVALID;
174 }
175 return LY_SUCCESS;
176}
177
178/**
179 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
180 *
181 * @param[in] ctx yang parser context for logging.
182 * @param[in] c UTF8 code point of a character to check.
183 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200184 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
185 * 0 - colon not yet found (no prefix)
186 * 1 - \p c is the colon character
187 * 2 - prefix already processed, now processing the identifier
188 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200189 * If the identifier cannot be prefixed, NULL is expected.
190 * @return LY_ERR values.
191 */
192static LY_ERR
193check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
194{
195 if (first || (prefix && (*prefix) == 1)) {
196 if (!is_yangidentstartchar(c)) {
197 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
198 return LY_EVALID;
199 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200200 if (prefix) {
201 if (first) {
202 (*prefix) = 0;
203 } else {
204 (*prefix) = 2;
205 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200206 }
207 } else if (c == ':' && prefix && (*prefix) == 0) {
208 (*prefix) = 1;
209 } else if (!is_yangidentchar(c)) {
210 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
211 return LY_EVALID;
212 }
213
214 return LY_SUCCESS;
215}
216
217/**
218 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
219 *
220 * @param[in] ctx yang parser context for logging.
221 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
222 * when function returns.
223 * @param[in] arg Type of the input string to select method of checking character validity.
224 * @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 +0200225 * 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 +0200226 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
227 * @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 +0200228 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200229 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200230 *
231 * @return LY_ERR values.
232 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200233static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200234buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
235 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200236{
Radek Krejci404251e2018-10-09 12:06:44 +0200237 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200238 unsigned int c;
239 size_t len;
240
Radek Krejcif29b7c32019-04-09 16:17:49 +0200241 /* check valid combination of input paremeters - if need_buf specified, word_b must be provided */
242 assert(!need_buf || (need_buf && word_b));
243
Radek Krejci44ceedc2018-10-02 15:54:31 +0200244 /* get UTF8 code point (and number of bytes coding the character) */
245 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
246 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
247 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200248 if (c == '\n') {
249 ctx->indent = 0;
250 } else {
251 /* note - even the multibyte character is count as 1 */
252 ++ctx->indent;
253 }
254
Radek Krejci44ceedc2018-10-02 15:54:31 +0200255 /* check character validity */
256 switch (arg) {
257 case Y_IDENTIF_ARG:
258 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
259 break;
260 case Y_PREF_IDENTIF_ARG:
261 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
262 break;
263 case Y_STR_ARG:
264 case Y_MAYBE_STR_ARG:
265 LY_CHECK_RET(check_stringchar(ctx, c));
266 break;
267 }
268
Michal Vasko7fbc8162018-09-17 10:35:16 +0200269 if (word_b && *word_b) {
270 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200271 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200272 return LY_EMEM;
273 }
274
275 /* in case of realloc */
276 *word_p = *word_b;
Radek Krejcif29b7c32019-04-09 16:17:49 +0200277 } else if (word_b && need_buf) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200278 /* first time we need a buffer, copy everything read up to now */
279 if (*word_len) {
280 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200281 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200282 *buf_len = *word_len;
283 memcpy(*word_b, *word_p, *word_len);
284 }
285
286 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200287 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200288 return LY_EMEM;
289 }
290
291 /* in case of realloc */
292 *word_p = *word_b;
293 } else {
294 /* just remember the first character pointer */
295 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200296 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200297 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200298 /* ... and update the word's length */
299 (*word_len) += len;
300 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200301 }
302
303 return LY_SUCCESS;
304}
305
Michal Vaskoea5abea2018-09-18 13:10:54 +0200306/**
307 * @brief Skip YANG comment in data.
308 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200309 * @param[in] ctx yang parser context for logging.
310 * @param[in,out] data Data to read from, automatically moved after the comment.
311 * @param[in] comment Type of the comment to process:
312 * 1 for a one-line comment,
313 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200314 *
315 * @return LY_ERR values.
316 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200317static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200318skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200319{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200320 /* internal statuses: 0 - comment ended,
321 * 1 - in line comment,
322 * 2 - in block comment,
323 * 3 - in block comment with last read character '*'
324 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200325 while (**data && comment) {
326 switch (comment) {
327 case 1:
328 if (**data == '\n') {
329 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200330 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200331 }
332 break;
333 case 2:
334 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200335 comment = 3;
336 } else if (**data == '\n') {
337 ++ctx->line;
338 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200339 break;
340 case 3:
341 if (**data == '/') {
342 comment = 0;
343 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200344 if (**data == '\n') {
345 ++ctx->line;
346 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200347 comment = 2;
348 }
349 break;
350 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200351 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200352 }
353
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200354 if (**data == '\n') {
355 ctx->indent = 0;
356 } else {
357 ++ctx->indent;
358 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200359 ++(*data);
360 }
361
362 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200363 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200364 return LY_EVALID;
365 }
366
367 return LY_SUCCESS;
368}
369
Michal Vaskoea5abea2018-09-18 13:10:54 +0200370/**
371 * @brief Read a quoted string from data.
372 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200373 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200374 * @param[in,out] data Data to read from, always moved to currently handled character.
375 * @param[in] arg Type of YANG keyword argument expected.
376 * @param[out] word_p Pointer to the read quoted string.
377 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
378 * set to NULL. Otherwise equal to \p word_p.
379 * @param[out] word_len Length of the read quoted string.
380 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
381 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
382 * indenation in the final quoted string.
383 *
384 * @return LY_ERR values.
385 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200386static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200387read_qstring(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len,
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200388 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200389{
390 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
391 * 4 - string finished, now skipping whitespaces looking for +,
392 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200393 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200394 const char *c;
395
396 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200397 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200398 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200399 } else {
400 assert(**data == '\'');
401 string = 1;
402 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200403 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200404
405 while (**data && string) {
406 switch (string) {
407 case 1:
408 switch (**data) {
409 case '\'':
410 /* string may be finished, but check for + */
411 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200412 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200413 break;
414 default:
415 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200416 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 +0200417 break;
418 }
419 break;
420 case 2:
421 switch (**data) {
422 case '\"':
423 /* string may be finished, but check for + */
424 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200425 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200426 break;
427 case '\\':
428 /* special character following */
429 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200430 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200431 break;
432 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200433 if (current_indent < block_indent) {
434 ++current_indent;
435 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200436 } else {
437 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200438 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200439 }
440 break;
441 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200442 if (current_indent < block_indent) {
443 assert(need_buf);
444 current_indent += 8;
445 ctx->indent += 8;
446 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
447 /* store leftover spaces from the tab */
448 c = " ";
449 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 +0200450 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200451 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200452 } else {
453 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200454 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 +0200455 /* additional characters for indentation - only 1 was count in buf_store_char */
456 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200457 }
458 break;
459 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200460 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200461 /* we will be removing the indents so we need our own buffer */
462 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200463
464 /* remove trailing tabs and spaces */
465 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
466 --(*word_len);
467 }
468
469 /* start indentation */
470 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200471 }
472
473 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200474 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
475
476 /* maintain line number */
477 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200478
479 /* reset context indentation counter for possible string after this one */
480 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200481 break;
482 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200483 /* first non-whitespace character, stop eating indentation */
484 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200485
486 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200487 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 +0200488 break;
489 }
490 break;
491 case 3:
492 /* string encoded characters */
493 switch (**data) {
494 case 'n':
495 c = "\n";
496 break;
497 case 't':
498 c = "\t";
499 break;
500 case '\"':
501 c = *data;
502 break;
503 case '\\':
504 c = *data;
505 break;
506 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200507 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200508 return LY_EVALID;
509 }
510
511 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200512 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 +0200513
514 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200515 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200516 break;
517 case 4:
518 switch (**data) {
519 case '+':
520 /* string continues */
521 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200522 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200523 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200524 case '\n':
525 ++ctx->line;
526 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200527 case ' ':
528 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200529 /* just skip */
530 break;
531 default:
532 /* string is finished */
533 goto string_end;
534 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200535 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200536 break;
537 case 5:
538 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200539 case '\n':
540 ++ctx->line;
541 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200542 case ' ':
543 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200544 /* skip */
545 break;
546 case '\'':
547 string = 1;
548 break;
549 case '\"':
550 string = 2;
551 break;
552 default:
553 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200554 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200555 return LY_EVALID;
556 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200557 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200558 break;
559 default:
560 return LY_EINT;
561 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200562 }
563
564string_end:
565 return LY_SUCCESS;
566}
567
Michal Vaskoea5abea2018-09-18 13:10:54 +0200568/**
569 * @brief Get another YANG string from the raw data.
570 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200571 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200572 * @param[in,out] data Data to read from, always moved to currently handled character.
573 * @param[in] arg Type of YANG keyword argument expected.
Radek Krejcid3ca0632019-04-16 16:54:54 +0200574 * @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 +0200575 * @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 +0200576 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
577 * set to NULL. Otherwise equal to \p word_p.
578 * @param[out] word_len Length of the read string.
579 *
580 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200581 */
582static LY_ERR
Radek Krejcid3ca0632019-04-16 16:54:54 +0200583get_argument(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg,
584 uint16_t *flags, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200585{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200586 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200587
588 /* word buffer - dynamically allocated */
589 *word_b = NULL;
590
591 /* word pointer - just a pointer to data */
592 *word_p = NULL;
593
594 *word_len = 0;
595 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200596 switch (**data) {
597 case '\'':
598 case '\"':
599 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200600 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
601 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
602 "unquoted string character, optsep, semicolon or opening brace");
603 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200604 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200605 if (flags) {
606 (*flags) |= (**data) == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
607 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100608 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200609 goto str_end;
610 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200611 if ((*data)[1] == '/') {
612 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200613 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100614 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200615 } else if ((*data)[1] == '*') {
616 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200617 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100618 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200619 } else {
620 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100621 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 +0200622 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200623 break;
624 case ' ':
625 if (*word_len) {
626 /* word is finished */
627 goto str_end;
628 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200629 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200630 break;
631 case '\t':
632 if (*word_len) {
633 /* word is finished */
634 goto str_end;
635 }
636 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200637 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200638
639 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200640 break;
641 case '\n':
642 if (*word_len) {
643 /* word is finished */
644 goto str_end;
645 }
646 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200647 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200648
649 /* track line numbers */
650 ++ctx->line;
651
652 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200653 break;
654 case ';':
655 case '{':
656 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
657 /* word is finished */
658 goto str_end;
659 }
660
Radek Krejci44ceedc2018-10-02 15:54:31 +0200661 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200662 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200663 case '}':
664 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
665 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
666 "unquoted string character, optsep, semicolon or opening brace");
667 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200668 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200669 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 +0200670 break;
671 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200672 }
673
674str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200675 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200676 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200677 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
678 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
679 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200680 *word_p = *word_b;
681 }
682
683 return LY_SUCCESS;
684}
685
Michal Vaskoea5abea2018-09-18 13:10:54 +0200686/**
687 * @brief Get another YANG keyword from the raw data.
688 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200689 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200690 * @param[in,out] data Data to read from, always moved to currently handled character.
691 * @param[out] kw YANG keyword read.
692 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
693 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
694 *
695 * @return LY_ERR values.
696 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200697static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200698get_keyword(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200699{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200700 int prefix;
701 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200702 unsigned int c;
703 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200704
705 if (word_p) {
706 *word_p = NULL;
707 *word_len = 0;
708 }
709
710 /* first skip "optsep", comments */
711 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200712 switch (**data) {
713 case '/':
714 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200715 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200716 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100717 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200718 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200719 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200720 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100721 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200722 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200723 /* error - not a comment after all, keyword cannot start with slash */
724 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
725 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200726 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200727 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200728 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200729 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200730 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200731 ctx->indent = 0;
732 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200733 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200734 /* skip whitespaces (optsep) */
735 ++ctx->indent;
736 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200737 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200738 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200739 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200740 break;
741 default:
742 /* either a keyword start or an invalid character */
743 goto keyword_start;
744 }
745
746 ++(*data);
747 }
748
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200749#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
750#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
751#define IF_KW_PREFIX_END }
752
Michal Vasko7fbc8162018-09-17 10:35:16 +0200753keyword_start:
754 word_start = *data;
755 *kw = YANG_NONE;
756
757 /* read the keyword itself */
758 switch (**data) {
759 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200760 MOVE_INPUT(ctx, data, 1);
761 IF_KW("rgument", 7, YANG_ARGUMENT)
762 else IF_KW("ugment", 6, YANG_AUGMENT)
763 else IF_KW("ction", 5, YANG_ACTION)
764 else IF_KW_PREFIX("ny", 2)
765 IF_KW("data", 4, YANG_ANYDATA)
766 else IF_KW("xml", 3, YANG_ANYXML)
767 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200768 break;
769 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200770 MOVE_INPUT(ctx, data, 1);
771 IF_KW("ase", 3, YANG_BASE)
772 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
773 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200774 break;
775 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200776 MOVE_INPUT(ctx, data, 1);
777 IF_KW("ase", 3, YANG_CASE)
778 else IF_KW("hoice", 5, YANG_CHOICE)
779 else IF_KW_PREFIX("on", 2)
780 IF_KW("fig", 3, YANG_CONFIG)
781 else IF_KW_PREFIX("ta", 2)
782 IF_KW("ct", 2, YANG_CONTACT)
783 else IF_KW("iner", 4, YANG_CONTAINER)
784 IF_KW_PREFIX_END
785 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200786 break;
787 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200788 MOVE_INPUT(ctx, data, 1);
789 IF_KW_PREFIX("e", 1)
790 IF_KW("fault", 5, YANG_DEFAULT)
791 else IF_KW("scription", 9, YANG_DESCRIPTION)
792 else IF_KW_PREFIX("viat", 4)
793 IF_KW("e", 1, YANG_DEVIATE)
794 else IF_KW("ion", 3, YANG_DEVIATION)
795 IF_KW_PREFIX_END
796 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200797 break;
798 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200799 MOVE_INPUT(ctx, data, 1);
800 IF_KW("num", 3, YANG_ENUM)
801 else IF_KW_PREFIX("rror-", 5)
802 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
803 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
804 IF_KW_PREFIX_END
805 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200806 break;
807 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200808 MOVE_INPUT(ctx, data, 1);
809 IF_KW("eature", 6, YANG_FEATURE)
810 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200811 break;
812 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200813 MOVE_INPUT(ctx, data, 1);
814 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200815 break;
816 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200817 MOVE_INPUT(ctx, data, 1);
818 IF_KW("dentity", 7, YANG_IDENTITY)
819 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
820 else IF_KW("mport", 5, YANG_IMPORT)
821 else IF_KW_PREFIX("n", 1)
822 IF_KW("clude", 5, YANG_INCLUDE)
823 else IF_KW("put", 3, YANG_INPUT)
824 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200825 break;
826 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200827 MOVE_INPUT(ctx, data, 1);
828 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200829 break;
830 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200831 MOVE_INPUT(ctx, data, 1);
832 IF_KW_PREFIX("e", 1)
833 IF_KW("af-list", 7, YANG_LEAF_LIST)
834 else IF_KW("af", 2, YANG_LEAF)
835 else IF_KW("ngth", 4, YANG_LENGTH)
836 IF_KW_PREFIX_END
837 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200838 break;
839 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200840 MOVE_INPUT(ctx, data, 1);
841 IF_KW_PREFIX("a", 1)
842 IF_KW("ndatory", 7, YANG_MANDATORY)
843 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
844 IF_KW_PREFIX_END
845 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
846 else IF_KW("ust", 3, YANG_MUST)
847 else IF_KW_PREFIX("od", 2)
848 IF_KW("ule", 3, YANG_MODULE)
849 else IF_KW("ifier", 5, YANG_MODIFIER)
850 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200851 break;
852 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200853 MOVE_INPUT(ctx, data, 1);
854 IF_KW("amespace", 8, YANG_NAMESPACE)
855 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200856 break;
857 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200858 MOVE_INPUT(ctx, data, 1);
859 IF_KW_PREFIX("r", 1)
860 IF_KW("dered-by", 8, YANG_ORDERED_BY)
861 else IF_KW("ganization", 10, YANG_ORGANIZATION)
862 IF_KW_PREFIX_END
863 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200864 break;
865 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200866 MOVE_INPUT(ctx, data, 1);
867 IF_KW("ath", 3, YANG_PATH)
868 else IF_KW("attern", 6, YANG_PATTERN)
869 else IF_KW("osition", 7, YANG_POSITION)
870 else IF_KW_PREFIX("re", 2)
871 IF_KW("fix", 3, YANG_PREFIX)
872 else IF_KW("sence", 5, YANG_PRESENCE)
873 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200874 break;
875 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200876 MOVE_INPUT(ctx, data, 1);
877 IF_KW("ange", 4, YANG_RANGE)
878 else IF_KW_PREFIX("e", 1)
879 IF_KW_PREFIX("f", 1)
880 IF_KW("erence", 6, YANG_REFERENCE)
881 else IF_KW("ine", 3, YANG_REFINE)
882 IF_KW_PREFIX_END
883 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
884 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
885 else IF_KW("vision", 6, YANG_REVISION)
886 IF_KW_PREFIX_END
887 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200888 break;
889 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200890 MOVE_INPUT(ctx, data, 1);
891 IF_KW("tatus", 5, YANG_STATUS)
892 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200893 break;
894 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200895 MOVE_INPUT(ctx, data, 1);
896 IF_KW("ypedef", 6, YANG_TYPEDEF)
897 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200898 break;
899 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200900 MOVE_INPUT(ctx, data, 1);
901 IF_KW_PREFIX("ni", 2)
902 IF_KW("que", 3, YANG_UNIQUE)
903 else IF_KW("ts", 2, YANG_UNITS)
904 IF_KW_PREFIX_END
905 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200906 break;
907 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200908 MOVE_INPUT(ctx, data, 1);
909 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200910 break;
911 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200912 MOVE_INPUT(ctx, data, 1);
913 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200914 break;
915 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200916 MOVE_INPUT(ctx, data, 1);
917 IF_KW("ang-version", 11, YANG_YANG_VERSION)
918 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200919 break;
920 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200921 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200922 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200923 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200924 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200925 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200926 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200927 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200928 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200929 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200930 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200931 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200932 default:
933 break;
934 }
935
Radek Krejci0904c162019-01-02 15:03:59 +0100936#undef IF_KW
937#undef IF_KW_PREFIX
938#undef IF_KW_PREFIX_END
939
Michal Vasko7fbc8162018-09-17 10:35:16 +0200940 if (*kw != YANG_NONE) {
941 /* make sure we have the whole keyword */
942 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200943 case '\n':
944 ++ctx->line;
945 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200946 case ' ':
947 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200948 /* mandatory "sep" */
949 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200950 case ':':
951 /* keyword is not actually a keyword, but prefix of an extension.
952 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
953 * and we will be checking the keyword (extension instance) itself */
954 prefix = 1;
955 MOVE_INPUT(ctx, data, 1);
956 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200957 case '{':
958 /* allowed only for input and output statements which can be without arguments */
959 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
960 break;
961 }
962 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200963 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200964 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200965 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
966 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200967 return LY_EVALID;
968 }
969 } else {
970 /* still can be an extension */
971 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200972extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200973 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200974 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
975 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200976 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200977 /* check character validity */
978 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200979 }
980 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200981 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200982 return LY_EVALID;
983 }
984
985 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200986 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200987 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200988 return LY_EVALID;
989 }
990
991 *kw = YANG_CUSTOM;
992 }
Radek Krejci626df482018-10-11 15:06:31 +0200993success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200994 if (word_p) {
995 *word_p = (char *)word_start;
996 *word_len = *data - word_start;
997 }
998
999 return LY_SUCCESS;
1000}
1001
Michal Vaskoea5abea2018-09-18 13:10:54 +02001002/**
1003 * @brief Parse extension instance substatements.
1004 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001005 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001006 * @param[in,out] data Data to read from, always moved to currently handled character.
1007 * @param[in] word Extension instance substatement name (keyword).
1008 * @param[in] word_len Extension instance substatement name length.
1009 * @param[in,out] child Children of this extension instance to add to.
1010 *
1011 * @return LY_ERR values.
1012 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001013static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001014parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001015 struct lysp_stmt **child)
1016{
1017 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001018 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001019 enum yang_keyword kw;
1020 struct lysp_stmt *stmt, *par_child;
1021
1022 stmt = calloc(1, sizeof *stmt);
1023 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
1024
Radek Krejcibb9b1982019-04-08 14:24:59 +02001025 /* insert into parent statements */
1026 if (!*child) {
1027 *child = stmt;
1028 } else {
1029 for (par_child = *child; par_child->next; par_child = par_child->next);
1030 par_child->next = stmt;
1031 }
1032
Radek Krejci44ceedc2018-10-02 15:54:31 +02001033 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001034
1035 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001036 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001037
Radek Krejci0ae092d2018-09-20 16:43:19 +02001038 if (word) {
1039 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001040 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001041 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001042 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001043 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001044 }
1045
Radek Krejci6d6556c2018-11-08 09:37:45 +01001046 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001047 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001048 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001049 return ret;
1050}
1051
Michal Vaskoea5abea2018-09-18 13:10:54 +02001052/**
1053 * @brief Parse extension instance.
1054 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001055 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001056 * @param[in,out] data Data to read from, always moved to currently handled character.
1057 * @param[in] ext_name Extension instance substatement name (keyword).
1058 * @param[in] ext_name_len Extension instance substatement name length.
1059 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1060 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1061 * @param[in,out] exts Extension instances to add to.
1062 *
1063 * @return LY_ERR values.
1064 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001065static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001066parse_ext(struct ly_parser_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001067 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1068{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001069 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001070 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001071 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001072 struct lysp_ext_instance *e;
1073 enum yang_keyword kw;
1074
Radek Krejci2c4e7172018-10-19 15:56:26 +02001075 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001076
1077 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001078 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001079 e->insubstmt = insubstmt;
1080 e->insubstmt_index = insubstmt_index;
1081
1082 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001083 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001084
Radek Krejci0ae092d2018-09-20 16:43:19 +02001085 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001086 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001087 }
1088
Radek Krejci6d6556c2018-11-08 09:37:45 +01001089 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001090 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001091 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001092 return ret;
1093}
1094
Michal Vaskoea5abea2018-09-18 13:10:54 +02001095/**
1096 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1097 * description, etc...
1098 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001099 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001100 * @param[in,out] data Data to read from, always moved to currently handled character.
1101 * @param[in] substmt Type of this substatement.
1102 * @param[in] substmt_index Index of this substatement.
1103 * @param[in,out] value Place to store the parsed value.
1104 * @param[in] arg Type of the YANG keyword argument (of the value).
1105 * @param[in,out] exts Extension instances to add to.
1106 *
1107 * @return LY_ERR values.
1108 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001109static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001110parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001111 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1112{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001113 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001114 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001115 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001116 enum yang_keyword kw;
1117
1118 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001119 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001120 return LY_EVALID;
1121 }
1122
1123 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001124 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001125
1126 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001127 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001128
Radek Krejci6d6556c2018-11-08 09:37:45 +01001129 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001130 switch (kw) {
1131 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001132 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001133 break;
1134 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001135 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001136 return LY_EVALID;
1137 }
1138 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001139 return ret;
1140}
1141
Michal Vaskoea5abea2018-09-18 13:10:54 +02001142/**
1143 * @brief Parse the yang-version statement.
1144 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001145 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001146 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001147 * @param[out] version Storage for the parsed information.
1148 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001149 *
1150 * @return LY_ERR values.
1151 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001152static LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001153parse_yangversion(struct ly_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001154{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001155 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001156 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001157 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001158 enum yang_keyword kw;
1159
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001160 if (*version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001161 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001162 return LY_EVALID;
1163 }
1164
1165 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001166 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001167
1168 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001169 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001170 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001171 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001172 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001173 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001174 free(buf);
1175 return LY_EVALID;
1176 }
1177 free(buf);
1178
Radek Krejci6d6556c2018-11-08 09:37:45 +01001179 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001180 switch (kw) {
1181 case YANG_CUSTOM:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001182 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001183 break;
1184 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001185 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001186 return LY_EVALID;
1187 }
1188 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 return ret;
1190}
1191
Michal Vaskoea5abea2018-09-18 13:10:54 +02001192/**
1193 * @brief Parse the belongs-to statement.
1194 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001195 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001196 * @param[in,out] data Data to read from, always moved to currently handled character.
1197 * @param[in,out] belongsto Place to store the parsed value.
1198 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1199 * @param[in,out] exts Extension instances to add to.
1200 *
1201 * @return LY_ERR values.
1202 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001203static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001204parse_belongsto(struct ly_parser_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001205{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001206 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001207 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001208 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001209 enum yang_keyword kw;
1210
1211 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001212 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001213 return LY_EVALID;
1214 }
1215
1216 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001217 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001218
Radek Krejci44ceedc2018-10-02 15:54:31 +02001219 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001220 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001221 switch (kw) {
1222 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001223 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001224 break;
1225 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001226 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001227 break;
1228 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001229 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001230 return LY_EVALID;
1231 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001232 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001233 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001234checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001235 /* mandatory substatements */
1236 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001237 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001238 return LY_EVALID;
1239 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001240 return ret;
1241}
1242
Michal Vaskoea5abea2018-09-18 13:10:54 +02001243/**
1244 * @brief Parse the revision-date statement.
1245 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001246 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001247 * @param[in,out] data Data to read from, always moved to currently handled character.
1248 * @param[in,out] rev Array to store the parsed value in.
1249 * @param[in,out] exts Extension instances to add to.
1250 *
1251 * @return LY_ERR values.
1252 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001253static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001254parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001255{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001256 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001257 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001258 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001259 enum yang_keyword kw;
1260
1261 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001262 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001263 return LY_EVALID;
1264 }
1265
1266 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001267 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001268
1269 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001270 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001271 free(buf);
1272 return LY_EVALID;
1273 }
1274
1275 /* store value and spend buf if allocated */
1276 strncpy(rev, word, word_len);
1277 free(buf);
1278
Radek Krejci6d6556c2018-11-08 09:37:45 +01001279 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001280 switch (kw) {
1281 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001282 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001283 break;
1284 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001285 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001286 return LY_EVALID;
1287 }
1288 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001289 return ret;
1290}
1291
Michal Vaskoea5abea2018-09-18 13:10:54 +02001292/**
1293 * @brief Parse the include statement.
1294 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001295 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001296 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001297 * @param[in,out] data Data to read from, always moved to currently handled character.
1298 * @param[in,out] includes Parsed includes to add to.
1299 *
1300 * @return LY_ERR values.
1301 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001302static LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001303parse_include(struct ly_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001304{
Radek Krejcid33273d2018-10-25 14:55:52 +02001305 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001306 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001307 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001308 enum yang_keyword kw;
1309 struct lysp_include *inc;
1310
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001311 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001312
1313 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001314 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001315
Radek Krejci086c7132018-10-26 15:29:04 +02001316 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1317
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001318 /* submodules share the namespace with the module names, so there must not be
1319 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001320 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001321 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1322 return LY_EVALID;
1323 }
1324
Radek Krejci6d6556c2018-11-08 09:37:45 +01001325 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001326 switch (kw) {
1327 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001328 YANG_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001329 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 +02001330 break;
1331 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001332 YANG_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001333 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 +02001334 break;
1335 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001336 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001337 break;
1338 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001339 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001340 break;
1341 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001342 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001343 return LY_EVALID;
1344 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001345 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001346 return ret;
1347}
1348
Michal Vaskoea5abea2018-09-18 13:10:54 +02001349/**
1350 * @brief Parse the import statement.
1351 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001352 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001353 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001354 * @param[in,out] data Data to read from, always moved to currently handled character.
1355 * @param[in,out] imports Parsed imports to add to.
1356 *
1357 * @return LY_ERR values.
1358 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001359static LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001360parse_import(struct ly_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001361{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001362 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001363 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001364 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001365 enum yang_keyword kw;
1366 struct lysp_import *imp;
1367
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001368 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001369
1370 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001371 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001372 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001373
Radek Krejci6d6556c2018-11-08 09:37:45 +01001374 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001375 switch (kw) {
1376 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001377 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 +01001378 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001379 break;
1380 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001381 YANG_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001382 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 +02001383 break;
1384 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001385 YANG_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001386 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 +02001387 break;
1388 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001389 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001390 break;
1391 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001392 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001393 break;
1394 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001395 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001396 return LY_EVALID;
1397 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001398 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001399 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001400checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001401 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001402 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001403
1404 return ret;
1405}
1406
Michal Vaskoea5abea2018-09-18 13:10:54 +02001407/**
1408 * @brief Parse the revision statement.
1409 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001410 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001411 * @param[in,out] data Data to read from, always moved to currently handled character.
1412 * @param[in,out] revs Parsed revisions to add to.
1413 *
1414 * @return LY_ERR values.
1415 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001416static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001417parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001418{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001419 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001420 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001421 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001422 enum yang_keyword kw;
1423 struct lysp_revision *rev;
1424
Radek Krejci2c4e7172018-10-19 15:56:26 +02001425 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001426
1427 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001428 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001429
1430 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001431 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001432 return LY_EVALID;
1433 }
1434
Radek Krejcib7db73a2018-10-24 14:18:40 +02001435 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001436 free(buf);
1437
Radek Krejci6d6556c2018-11-08 09:37:45 +01001438 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001439 switch (kw) {
1440 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001441 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 +02001442 break;
1443 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001444 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 +02001445 break;
1446 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001447 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001448 break;
1449 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001450 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001451 return LY_EVALID;
1452 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001453 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001454 return ret;
1455}
1456
Michal Vaskoea5abea2018-09-18 13:10:54 +02001457/**
1458 * @brief Parse a generic text field that can have more instances such as base.
1459 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001460 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001461 * @param[in,out] data Data to read from, always moved to currently handled character.
1462 * @param[in] substmt Type of this substatement.
1463 * @param[in,out] texts Parsed values to add to.
1464 * @param[in] arg Type of the expected argument.
1465 * @param[in,out] exts Extension instances to add to.
1466 *
1467 * @return LY_ERR values.
1468 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001469static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001470parse_text_fields(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001471 struct lysp_ext_instance **exts)
1472{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001473 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001474 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001475 const char **item;
1476 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001477 enum yang_keyword kw;
1478
1479 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001480 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001481
1482 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001483 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001484
Radek Krejci151a5b72018-10-19 14:21:44 +02001485 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001486 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001487 switch (kw) {
1488 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001489 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001490 break;
1491 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001492 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001493 return LY_EVALID;
1494 }
1495 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001496 return ret;
1497}
1498
Michal Vaskoea5abea2018-09-18 13:10:54 +02001499/**
1500 * @brief Parse the config statement.
1501 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001502 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001503 * @param[in,out] data Data to read from, always moved to currently handled character.
1504 * @param[in,out] flags Flags to add to.
1505 * @param[in,out] exts Extension instances to add to.
1506 *
1507 * @return LY_ERR values.
1508 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001509static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001510parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001511{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001512 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001513 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001514 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001515 enum yang_keyword kw;
1516
1517 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001518 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001519 return LY_EVALID;
1520 }
1521
1522 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001523 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001524
1525 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1526 *flags |= LYS_CONFIG_W;
1527 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1528 *flags |= LYS_CONFIG_R;
1529 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001530 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001531 free(buf);
1532 return LY_EVALID;
1533 }
1534 free(buf);
1535
Radek Krejci6d6556c2018-11-08 09:37:45 +01001536 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001537 switch (kw) {
1538 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001539 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001540 break;
1541 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001542 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001543 return LY_EVALID;
1544 }
1545 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001546 return ret;
1547}
1548
Michal Vaskoea5abea2018-09-18 13:10:54 +02001549/**
1550 * @brief Parse the mandatory statement.
1551 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001552 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001553 * @param[in,out] data Data to read from, always moved to currently handled character.
1554 * @param[in,out] flags Flags to add to.
1555 * @param[in,out] exts Extension instances to add to.
1556 *
1557 * @return LY_ERR values.
1558 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001559static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001560parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001561{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001562 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001563 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001564 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001565 enum yang_keyword kw;
1566
1567 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001568 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001569 return LY_EVALID;
1570 }
1571
1572 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001573 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001574
1575 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1576 *flags |= LYS_MAND_TRUE;
1577 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1578 *flags |= LYS_MAND_FALSE;
1579 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001580 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001581 free(buf);
1582 return LY_EVALID;
1583 }
1584 free(buf);
1585
Radek Krejci6d6556c2018-11-08 09:37:45 +01001586 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001587 switch (kw) {
1588 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001589 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001590 break;
1591 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001592 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001593 return LY_EVALID;
1594 }
1595 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001596 return ret;
1597}
1598
Michal Vaskoea5abea2018-09-18 13:10:54 +02001599/**
1600 * @brief Parse a restriction such as range or length.
1601 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001602 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001603 * @param[in,out] data Data to read from, always moved to currently handled character.
1604 * @param[in] restr_kw Type of this particular restriction.
1605 * @param[in,out] exts Extension instances to add to.
1606 *
1607 * @return LY_ERR values.
1608 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001609static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001610parse_restr(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr *restr)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001611{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001612 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001613 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001614 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001615 enum yang_keyword kw;
1616
1617 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001618 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001619
Radek Krejci44ceedc2018-10-02 15:54:31 +02001620 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001621 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001622 switch (kw) {
1623 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001624 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 +02001625 break;
1626 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001627 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 +02001628 break;
1629 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001630 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 +02001631 break;
1632 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001633 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 +02001634 break;
1635 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001636 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001637 break;
1638 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001639 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001640 return LY_EVALID;
1641 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001642 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001643 return ret;
1644}
1645
Michal Vaskoea5abea2018-09-18 13:10:54 +02001646/**
1647 * @brief Parse a restriction that can have more instances such as must.
1648 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001649 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001650 * @param[in,out] data Data to read from, always moved to currently handled character.
1651 * @param[in] restr_kw Type of this particular restriction.
1652 * @param[in,out] restrs Restrictions to add to.
1653 *
1654 * @return LY_ERR values.
1655 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001656static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001657parse_restrs(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr **restrs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001658{
1659 struct lysp_restr *restr;
1660
Radek Krejci2c4e7172018-10-19 15:56:26 +02001661 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001662 return parse_restr(ctx, data, restr_kw, restr);
1663}
1664
Michal Vaskoea5abea2018-09-18 13:10:54 +02001665/**
1666 * @brief Parse the status statement.
1667 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001668 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001669 * @param[in,out] data Data to read from, always moved to currently handled character.
1670 * @param[in,out] flags Flags to add to.
1671 * @param[in,out] exts Extension instances to add to.
1672 *
1673 * @return LY_ERR values.
1674 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001675static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001676parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001677{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001678 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001679 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001680 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001681 enum yang_keyword kw;
1682
1683 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001684 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001685 return LY_EVALID;
1686 }
1687
1688 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001689 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001690
1691 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1692 *flags |= LYS_STATUS_CURR;
1693 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1694 *flags |= LYS_STATUS_DEPRC;
1695 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1696 *flags |= LYS_STATUS_OBSLT;
1697 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001698 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001699 free(buf);
1700 return LY_EVALID;
1701 }
1702 free(buf);
1703
Radek Krejci6d6556c2018-11-08 09:37:45 +01001704 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001705 switch (kw) {
1706 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001707 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001708 break;
1709 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001710 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001711 return LY_EVALID;
1712 }
1713 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001714 return ret;
1715}
1716
Michal Vaskoea5abea2018-09-18 13:10:54 +02001717/**
1718 * @brief Parse the when statement.
1719 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001720 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001721 * @param[in,out] data Data to read from, always moved to currently handled character.
1722 * @param[in,out] when_p When pointer to parse to.
1723 *
1724 * @return LY_ERR values.
1725 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001726static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001727parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001728{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001729 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001730 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001731 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001732 enum yang_keyword kw;
1733 struct lysp_when *when;
1734
1735 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001736 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001737 return LY_EVALID;
1738 }
1739
1740 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001741 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001742 *when_p = when;
1743
1744 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001745 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001746 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001747
Radek Krejci6d6556c2018-11-08 09:37:45 +01001748 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001749 switch (kw) {
1750 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001751 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 +02001752 break;
1753 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001754 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 +02001755 break;
1756 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001757 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001758 break;
1759 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001760 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001761 return LY_EVALID;
1762 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001763 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001764 return ret;
1765}
1766
Michal Vaskoea5abea2018-09-18 13:10:54 +02001767/**
1768 * @brief Parse the anydata or anyxml statement.
1769 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001770 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001771 * @param[in,out] data Data to read from, always moved to currently handled character.
1772 * @param[in] kw Type of this particular keyword.
1773 * @param[in,out] siblings Siblings to add to.
1774 *
1775 * @return LY_ERR values.
1776 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001777static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001778parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001779{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001780 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001781 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001782 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001783 struct lysp_node *iter;
1784 struct lysp_node_anydata *any;
1785
1786 /* create structure */
1787 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001788 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001789 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001790 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001791
1792 /* insert into siblings */
1793 if (!*siblings) {
1794 *siblings = (struct lysp_node *)any;
1795 } else {
1796 for (iter = *siblings; iter->next; iter = iter->next);
1797 iter->next = (struct lysp_node *)any;
1798 }
1799
1800 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001801 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001802 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001803
1804 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001805 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001806 switch (kw) {
1807 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001808 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001809 break;
1810 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001811 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 +02001812 break;
1813 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001814 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 +02001815 break;
1816 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001817 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001818 break;
1819 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001820 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001821 break;
1822 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001823 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 +02001824 break;
1825 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001826 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001827 break;
1828 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001829 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001830 break;
1831 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001832 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833 break;
1834 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001835 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001836 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001837 return LY_EVALID;
1838 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001839 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001840 return ret;
1841}
1842
Michal Vaskoea5abea2018-09-18 13:10:54 +02001843/**
1844 * @brief Parse the value or position statement. Substatement of type enum statement.
1845 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001846 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001847 * @param[in,out] data Data to read from, always moved to currently handled character.
1848 * @param[in] val_kw Type of this particular keyword.
1849 * @param[in,out] value Value to write to.
1850 * @param[in,out] flags Flags to write to.
1851 * @param[in,out] exts Extension instances to add to.
1852 *
1853 * @return LY_ERR values.
1854 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001855static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001856parse_type_enum_value_pos(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword val_kw, int64_t *value, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001857 struct lysp_ext_instance **exts)
1858{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001859 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001860 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001861 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001862 long int num;
1863 unsigned long int unum;
1864 enum yang_keyword kw;
1865
1866 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001867 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001868 return LY_EVALID;
1869 }
1870 *flags |= LYS_SET_VALUE;
1871
1872 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001873 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001874
1875 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 +02001876 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001877 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001878 }
1879
1880 errno = 0;
1881 if (val_kw == YANG_VALUE) {
1882 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001883 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
1884 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1885 goto error;
1886 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001887 } else {
1888 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001889 if (unum > UINT64_C(4294967295)) {
1890 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1891 goto error;
1892 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001893 }
1894 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001895 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001896 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001897 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001898 }
1899 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001900 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001901 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001902 }
1903 if (val_kw == YANG_VALUE) {
1904 *value = num;
1905 } else {
1906 *value = unum;
1907 }
1908 free(buf);
1909
Radek Krejci6d6556c2018-11-08 09:37:45 +01001910 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001911 switch (kw) {
1912 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001913 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 +02001914 break;
1915 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001916 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001917 return LY_EVALID;
1918 }
1919 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001920 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001921
1922error:
1923 free(buf);
1924 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001925}
1926
Michal Vaskoea5abea2018-09-18 13:10:54 +02001927/**
1928 * @brief Parse the enum or bit statement. Substatement of type statement.
1929 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001930 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001931 * @param[in,out] data Data to read from, always moved to currently handled character.
1932 * @param[in] enum_kw Type of this particular keyword.
1933 * @param[in,out] enums Enums or bits to add to.
1934 *
1935 * @return LY_ERR values.
1936 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001937static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001938parse_type_enum(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword enum_kw, struct lysp_type_enum **enums)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001939{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001940 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001941 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001942 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001943 enum yang_keyword kw;
1944 struct lysp_type_enum *enm;
1945
Radek Krejci2c4e7172018-10-19 15:56:26 +02001946 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001947
1948 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001949 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 +01001950 if (enum_kw == YANG_ENUM) {
1951 if (!word_len) {
1952 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
1953 free(buf);
1954 return LY_EVALID;
1955 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
1956 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
1957 word_len, word);
1958 free(buf);
1959 return LY_EVALID;
1960 } else {
1961 for (u = 0; u < word_len; ++u) {
1962 if (iscntrl(word[u])) {
1963 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1964 word_len, word, u + 1);
1965 break;
1966 }
1967 }
1968 }
1969 } else { /* YANG_BIT */
1970
1971 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001972 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001973 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1974
Radek Krejci6d6556c2018-11-08 09:37:45 +01001975 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001976 switch (kw) {
1977 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001978 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 +02001979 break;
1980 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001981 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001982 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 +02001983 break;
1984 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001985 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 +02001986 break;
1987 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001988 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001989 break;
1990 case YANG_VALUE:
1991 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001992 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001993 break;
1994 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001995 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001996 break;
1997 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001998 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001999 return LY_EVALID;
2000 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002001 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002002 return ret;
2003}
2004
Michal Vaskoea5abea2018-09-18 13:10:54 +02002005/**
2006 * @brief Parse the fraction-digits statement. Substatement of type statement.
2007 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002008 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002009 * @param[in,out] data Data to read from, always moved to currently handled character.
2010 * @param[in,out] fracdig Value to write to.
2011 * @param[in,out] exts Extension instances to add to.
2012 *
2013 * @return LY_ERR values.
2014 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002015static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002016parse_type_fracdigits(struct ly_parser_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002017{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002018 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002019 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002020 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002021 unsigned long int num;
2022 enum yang_keyword kw;
2023
2024 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002025 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002026 return LY_EVALID;
2027 }
2028
2029 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002030 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002031
2032 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002033 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002034 free(buf);
2035 return LY_EVALID;
2036 }
2037
2038 errno = 0;
2039 num = strtoul(word, &ptr, 10);
2040 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002041 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002042 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002043 free(buf);
2044 return LY_EVALID;
2045 }
2046 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002047 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002048 free(buf);
2049 return LY_EVALID;
2050 }
2051 *fracdig = num;
2052 free(buf);
2053
Radek Krejci6d6556c2018-11-08 09:37:45 +01002054 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002055 switch (kw) {
2056 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002057 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002058 break;
2059 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002060 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002061 return LY_EVALID;
2062 }
2063 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002064 return ret;
2065}
2066
Michal Vaskoea5abea2018-09-18 13:10:54 +02002067/**
2068 * @brief Parse the require-instance statement. Substatement of type statement.
2069 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002070 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002071 * @param[in,out] data Data to read from, always moved to currently handled character.
2072 * @param[in,out] reqinst Value to write to.
2073 * @param[in,out] flags Flags to write to.
2074 * @param[in,out] exts Extension instances to add to.
2075 *
2076 * @return LY_ERR values.
2077 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002078static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002079parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002080 struct lysp_ext_instance **exts)
2081{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002082 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002083 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002084 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002085 enum yang_keyword kw;
2086
2087 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002088 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002089 return LY_EVALID;
2090 }
2091 *flags |= LYS_SET_REQINST;
2092
2093 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002094 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002095
2096 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2097 *reqinst = 1;
2098 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002099 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002100 free(buf);
2101 return LY_EVALID;
2102 }
2103 free(buf);
2104
Radek Krejci6d6556c2018-11-08 09:37:45 +01002105 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002106 switch (kw) {
2107 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002108 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002109 break;
2110 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002111 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002112 return LY_EVALID;
2113 }
2114 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002115 return ret;
2116}
2117
Michal Vaskoea5abea2018-09-18 13:10:54 +02002118/**
2119 * @brief Parse the modifier statement. Substatement of type pattern statement.
2120 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002121 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002122 * @param[in,out] data Data to read from, always moved to currently handled character.
2123 * @param[in,out] pat Value to write to.
2124 * @param[in,out] exts Extension instances to add to.
2125 *
2126 * @return LY_ERR values.
2127 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002128static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002129parse_type_pattern_modifier(struct ly_parser_ctx *ctx, const char **data, const char **pat, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002130{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002131 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002132 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002133 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002134 enum yang_keyword kw;
2135
2136 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002137 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002138 return LY_EVALID;
2139 }
2140
2141 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002142 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002143
2144 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002145 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002146 free(buf);
2147 return LY_EVALID;
2148 }
2149 free(buf);
2150
2151 /* replace the value in the dictionary */
2152 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002153 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002154 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002155 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002156
2157 assert(buf[0] == 0x06);
2158 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002159 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002160
Radek Krejci6d6556c2018-11-08 09:37:45 +01002161 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002162 switch (kw) {
2163 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002164 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002165 break;
2166 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002167 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002168 return LY_EVALID;
2169 }
2170 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002171 return ret;
2172}
2173
Michal Vaskoea5abea2018-09-18 13:10:54 +02002174/**
2175 * @brief Parse the pattern statement. Substatement of type statement.
2176 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002177 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002178 * @param[in,out] data Data to read from, always moved to currently handled character.
2179 * @param[in,out] patterns Restrictions to add to.
2180 *
2181 * @return LY_ERR values.
2182 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002183static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002184parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002185{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002186 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002187 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002188 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189 enum yang_keyword kw;
2190 struct lysp_restr *restr;
2191
Radek Krejci2c4e7172018-10-19 15:56:26 +02002192 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002193
2194 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002195 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002196
2197 /* add special meaning first byte */
2198 if (buf) {
2199 buf = realloc(buf, word_len + 2);
2200 word = buf;
2201 } else {
2202 buf = malloc(word_len + 2);
2203 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002204 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002205 memmove(buf + 1, word, word_len);
2206 buf[0] = 0x06; /* pattern's default regular-match flag */
2207 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2208 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002209
Radek Krejci6d6556c2018-11-08 09:37:45 +01002210 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002211 switch (kw) {
2212 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002213 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 +02002214 break;
2215 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002216 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 +02002217 break;
2218 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002219 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 +02002220 break;
2221 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002222 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 +02002223 break;
2224 case YANG_MODIFIER:
Radek Krejciceaf2122019-01-02 15:03:26 +01002225 YANG_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002226 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002227 break;
2228 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002229 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002230 break;
2231 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002232 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002233 return LY_EVALID;
2234 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002235 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002236 return ret;
2237}
2238
Michal Vaskoea5abea2018-09-18 13:10:54 +02002239/**
2240 * @brief Parse the type statement.
2241 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002242 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002243 * @param[in,out] data Data to read from, always moved to currently handled character.
2244 * @param[in,out] type Type to wrote to.
2245 *
2246 * @return LY_ERR values.
2247 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002248static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002249parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002250{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002251 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002252 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002253 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002254 enum yang_keyword kw;
2255 struct lysp_type *nest_type;
2256
2257 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002258 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002259 return LY_EVALID;
2260 }
2261
2262 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002263 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002264 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265
Radek Krejci6d6556c2018-11-08 09:37:45 +01002266 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002267 switch (kw) {
2268 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002269 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 +01002270 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002271 break;
2272 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002273 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002274 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002275 break;
2276 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002277 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002278 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002279 break;
2280 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002281 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002282 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002283 break;
2284 case YANG_LENGTH:
2285 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002286 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002287 return LY_EVALID;
2288 }
2289 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002290 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002291
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002292 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002293 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002294 break;
2295 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002296 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 +01002297 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002298 break;
2299 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002300 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002301 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002302 break;
2303 case YANG_RANGE:
2304 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002305 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002306 return LY_EVALID;
2307 }
2308 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002309 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002310
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002311 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002312 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002313 break;
2314 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002315 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002316 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002317 break;
2318 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002319 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2320 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002321 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002322 break;
2323 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002324 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002325 break;
2326 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002327 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002328 return LY_EVALID;
2329 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002330 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002331 return ret;
2332}
2333
Michal Vaskoea5abea2018-09-18 13:10:54 +02002334/**
2335 * @brief Parse the leaf statement.
2336 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002337 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002338 * @param[in,out] data Data to read from, always moved to currently handled character.
2339 * @param[in,out] siblings Siblings to add to.
2340 *
2341 * @return LY_ERR values.
2342 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002343static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002344parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002345{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002346 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002347 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002348 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002349 enum yang_keyword kw;
2350 struct lysp_node *iter;
2351 struct lysp_node_leaf *leaf;
2352
2353 /* create structure */
2354 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002355 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002356 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002357 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002358
2359 /* insert into siblings */
2360 if (!*siblings) {
2361 *siblings = (struct lysp_node *)leaf;
2362 } else {
2363 for (iter = *siblings; iter->next; iter = iter->next);
2364 iter->next = (struct lysp_node *)leaf;
2365 }
2366
2367 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002368 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002369 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002370
2371 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002372 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002373 switch (kw) {
2374 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002375 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002376 break;
2377 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002378 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 +02002379 break;
2380 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002381 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 +02002382 break;
2383 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002384 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 +02002385 break;
2386 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002387 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002388 break;
2389 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002390 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002391 break;
2392 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002393 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 +02002394 break;
2395 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002396 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002397 break;
2398 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002399 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002400 break;
2401 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002402 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 +02002403 break;
2404 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002405 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002406 break;
2407 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002408 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002409 break;
2410 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002411 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002412 return LY_EVALID;
2413 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002414 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002415 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002416checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002417 /* mandatory substatements */
2418 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002419 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002420 return LY_EVALID;
2421 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002422 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
2423 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
2424 return LY_EVALID;
2425 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002426
2427 return ret;
2428}
2429
Michal Vaskoea5abea2018-09-18 13:10:54 +02002430/**
2431 * @brief Parse the max-elements statement.
2432 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002433 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002434 * @param[in,out] data Data to read from, always moved to currently handled character.
2435 * @param[in,out] max Value to write to.
2436 * @param[in,out] flags Flags to write to.
2437 * @param[in,out] exts Extension instances to add to.
2438 *
2439 * @return LY_ERR values.
2440 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002441static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002442parse_maxelements(struct ly_parser_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002443{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002444 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002445 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002446 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002447 unsigned long int num;
2448 enum yang_keyword kw;
2449
2450 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002451 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002452 return LY_EVALID;
2453 }
2454 *flags |= LYS_SET_MAX;
2455
2456 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002457 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002458
2459 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002460 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002461 free(buf);
2462 return LY_EVALID;
2463 }
2464
2465 if (strncmp(word, "unbounded", word_len)) {
2466 errno = 0;
2467 num = strtoul(word, &ptr, 10);
2468 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002469 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002470 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002471 free(buf);
2472 return LY_EVALID;
2473 }
2474 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002475 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002476 free(buf);
2477 return LY_EVALID;
2478 }
2479
2480 *max = num;
2481 }
2482 free(buf);
2483
Radek Krejci6d6556c2018-11-08 09:37:45 +01002484 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485 switch (kw) {
2486 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002487 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002488 break;
2489 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002490 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002491 return LY_EVALID;
2492 }
2493 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002494 return ret;
2495}
2496
Michal Vaskoea5abea2018-09-18 13:10:54 +02002497/**
2498 * @brief Parse the min-elements statement.
2499 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002500 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002501 * @param[in,out] data Data to read from, always moved to currently handled character.
2502 * @param[in,out] min Value to write to.
2503 * @param[in,out] flags Flags to write to.
2504 * @param[in,out] exts Extension instances to add to.
2505 *
2506 * @return LY_ERR values.
2507 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002508static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002509parse_minelements(struct ly_parser_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002510{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002511 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002512 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002513 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002514 unsigned long int num;
2515 enum yang_keyword kw;
2516
2517 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002518 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002519 return LY_EVALID;
2520 }
2521 *flags |= LYS_SET_MIN;
2522
2523 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002524 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002525
2526 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002527 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002528 free(buf);
2529 return LY_EVALID;
2530 }
2531
2532 errno = 0;
2533 num = strtoul(word, &ptr, 10);
2534 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002535 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002536 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002537 free(buf);
2538 return LY_EVALID;
2539 }
2540 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002541 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002542 free(buf);
2543 return LY_EVALID;
2544 }
2545 *min = num;
2546 free(buf);
2547
Radek Krejci6d6556c2018-11-08 09:37:45 +01002548 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002549 switch (kw) {
2550 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002551 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002552 break;
2553 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002554 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002555 return LY_EVALID;
2556 }
2557 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002558 return ret;
2559}
2560
Michal Vaskoea5abea2018-09-18 13:10:54 +02002561/**
2562 * @brief Parse the ordered-by statement.
2563 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002564 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002565 * @param[in,out] data Data to read from, always moved to currently handled character.
2566 * @param[in,out] flags Flags to write to.
2567 * @param[in,out] exts Extension instances to add to.
2568 *
2569 * @return LY_ERR values.
2570 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002571static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002572parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002573{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002574 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002575 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002576 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002577 enum yang_keyword kw;
2578
2579 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002580 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002581 return LY_EVALID;
2582 }
2583
2584 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002585 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002586
2587 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2588 *flags |= LYS_ORDBY_SYSTEM;
2589 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2590 *flags |= LYS_ORDBY_USER;
2591 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002592 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002593 free(buf);
2594 return LY_EVALID;
2595 }
2596 free(buf);
2597
Radek Krejci6d6556c2018-11-08 09:37:45 +01002598 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002599 switch (kw) {
2600 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002601 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002602 break;
2603 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002604 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002605 return LY_EVALID;
2606 }
2607 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002608 return ret;
2609}
2610
Michal Vaskoea5abea2018-09-18 13:10:54 +02002611/**
2612 * @brief Parse the leaf-list statement.
2613 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002614 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002615 * @param[in,out] data Data to read from, always moved to currently handled character.
2616 * @param[in,out] siblings Siblings to add to.
2617 *
2618 * @return LY_ERR values.
2619 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002620static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002621parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002622{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002623 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002624 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002625 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002626 enum yang_keyword kw;
2627 struct lysp_node *iter;
2628 struct lysp_node_leaflist *llist;
2629
2630 /* create structure */
2631 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002632 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002633 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002634 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002635
2636 /* insert into siblings */
2637 if (!*siblings) {
2638 *siblings = (struct lysp_node *)llist;
2639 } else {
2640 for (iter = *siblings; iter->next; iter = iter->next);
2641 iter->next = (struct lysp_node *)llist;
2642 }
2643
2644 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002645 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002646 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002647
2648 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002649 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002650 switch (kw) {
2651 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002652 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002653 break;
2654 case YANG_DEFAULT:
Radek Krejciceaf2122019-01-02 15:03:26 +01002655 YANG_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002656 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 +02002657 break;
2658 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002659 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 +02002660 break;
2661 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002662 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 +02002663 break;
2664 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002665 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002666 break;
2667 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002668 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002669 break;
2670 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002671 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002672 break;
2673 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002674 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002675 break;
2676 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002677 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 +02002678 break;
2679 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002680 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002681 break;
2682 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002683 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002684 break;
2685 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002686 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 +02002687 break;
2688 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002689 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002690 break;
2691 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002692 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002693 break;
2694 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002695 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002696 return LY_EVALID;
2697 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002698 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002699 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002700checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002701 /* mandatory substatements */
2702 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002703 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002704 return LY_EVALID;
2705 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002706 if ((llist->min) && (llist->dflts)) {
2707 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
2708 return LY_EVALID;
2709 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002710 if (llist->max && llist->min > llist->max) {
2711 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
2712 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2713 llist->min, llist->max);
2714 return LY_EVALID;
2715 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002716
2717 return ret;
2718}
2719
Michal Vaskoea5abea2018-09-18 13:10:54 +02002720/**
2721 * @brief Parse the refine statement.
2722 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002723 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002724 * @param[in,out] data Data to read from, always moved to currently handled character.
2725 * @param[in,out] refines Refines to add to.
2726 *
2727 * @return LY_ERR values.
2728 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002729static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002730parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002731{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002732 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002733 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002734 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002735 enum yang_keyword kw;
2736 struct lysp_refine *rf;
2737
Radek Krejci2c4e7172018-10-19 15:56:26 +02002738 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002739
2740 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002741 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002742 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002743
Radek Krejci6d6556c2018-11-08 09:37:45 +01002744 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002745 switch (kw) {
2746 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002747 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002748 break;
2749 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002750 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 +02002751 break;
2752 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002753 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 +02002754 break;
2755 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01002756 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002757 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 +02002758 break;
2759 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002760 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002761 break;
2762 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002763 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002764 break;
2765 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002766 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002767 break;
2768 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002769 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002770 break;
2771 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002772 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 +02002773 break;
2774 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002775 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 +02002776 break;
2777 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002778 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002779 break;
2780 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002781 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002782 return LY_EVALID;
2783 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002784 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002785 return ret;
2786}
2787
Michal Vaskoea5abea2018-09-18 13:10:54 +02002788/**
2789 * @brief Parse the typedef statement.
2790 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002791 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002792 * @param[in,out] data Data to read from, always moved to currently handled character.
2793 * @param[in,out] typedefs Typedefs to add to.
2794 *
2795 * @return LY_ERR values.
2796 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002797static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002798parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002799{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002800 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002801 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002802 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002803 enum yang_keyword kw;
2804 struct lysp_tpdf *tpdf;
2805
Radek Krejci2c4e7172018-10-19 15:56:26 +02002806 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002807
2808 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002809 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002810 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002811
2812 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002813 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002814 switch (kw) {
2815 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002816 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 +02002817 break;
2818 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002819 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 +02002820 break;
2821 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002822 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 +02002823 break;
2824 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002825 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002826 break;
2827 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002828 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002829 break;
2830 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002831 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 +02002832 break;
2833 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002834 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002835 break;
2836 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002837 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002838 return LY_EVALID;
2839 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002840 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002841 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002842checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002843 /* mandatory substatements */
2844 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002845 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846 return LY_EVALID;
2847 }
2848
Radek Krejcibbe09a92018-11-08 09:36:54 +01002849 /* store data for collision check */
2850 if (parent) {
2851 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2852 }
2853
Michal Vasko7fbc8162018-09-17 10:35:16 +02002854 return ret;
2855}
2856
Michal Vaskoea5abea2018-09-18 13:10:54 +02002857/**
2858 * @brief Parse the input or output statement.
2859 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002860 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002861 * @param[in,out] data Data to read from, always moved to currently handled character.
2862 * @param[in] kw Type of this particular keyword
2863 * @param[in,out] inout_p Input/output pointer to write to.
2864 *
2865 * @return LY_ERR values.
2866 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002867static LY_ERR
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002868parse_inout(struct ly_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 +02002869{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002870 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002871 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002872 size_t word_len;
Radek Krejci10113652018-11-14 16:56:50 +01002873 enum yang_keyword kw;
Radek Krejcie86bf772018-12-14 11:39:53 +01002874 unsigned int u;
2875 struct lysp_node *child;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002876
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002877 if (inout_p->nodetype) {
Radek Krejci10113652018-11-14 16:56:50 +01002878 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002879 return LY_EVALID;
2880 }
2881
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002882 /* initiate structure */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002883 inout_p->nodetype = &((struct lysp_action*)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002884 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002885
2886 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002887 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002888 switch (kw) {
2889 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002890 YANG_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002891 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002892 case YANG_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002893 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002894 break;
2895 case YANG_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002896 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002897 break;
2898 case YANG_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002899 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002900 break;
2901 case YANG_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002902 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002903 break;
2904 case YANG_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002905 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002906 break;
2907 case YANG_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002908 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002909 break;
2910 case YANG_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002911 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002912 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002913 case YANG_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002914 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002915 break;
2916 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002917 YANG_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002918 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002919 break;
2920 case YANG_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002921 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002922 break;
2923 case YANG_CUSTOM:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002924 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002925 break;
2926 default:
Radek Krejci10113652018-11-14 16:56:50 +01002927 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002928 return LY_EVALID;
2929 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002930 }
Radek Krejcie86bf772018-12-14 11:39:53 +01002931 /* finalize parent pointers to the reallocated items */
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002932 LY_ARRAY_FOR(inout_p->groupings, u) {
2933 LY_LIST_FOR(inout_p->groupings[u].data, child) {
2934 child->parent = (struct lysp_node*)&inout_p->groupings[u];
Radek Krejcie86bf772018-12-14 11:39:53 +01002935 }
2936 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002937 return ret;
2938}
2939
Michal Vaskoea5abea2018-09-18 13:10:54 +02002940/**
2941 * @brief Parse the action statement.
2942 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002943 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002944 * @param[in,out] data Data to read from, always moved to currently handled character.
2945 * @param[in,out] actions Actions to add to.
2946 *
2947 * @return LY_ERR values.
2948 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002949static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002950parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002951{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002952 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002953 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002954 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002955 enum yang_keyword kw;
2956 struct lysp_action *act;
Radek Krejcie86bf772018-12-14 11:39:53 +01002957 struct lysp_node *child;
2958 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002959
Radek Krejci2c4e7172018-10-19 15:56:26 +02002960 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002961
2962 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002963 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002964 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002965 act->nodetype = LYS_ACTION;
2966 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002967
Radek Krejci6d6556c2018-11-08 09:37:45 +01002968 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002969 switch (kw) {
2970 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002971 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 +02002972 break;
2973 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002974 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 +02002975 break;
2976 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002977 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 +02002978 break;
2979 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002980 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002981 break;
2982
2983 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002984 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002985 break;
2986 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002987 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002988 break;
2989
2990 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002991 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002992 break;
2993 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002994 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002995 break;
2996 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002997 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002998 break;
2999 default:
Radek Krejcif538ce52019-03-05 10:46:14 +01003000 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003001 return LY_EVALID;
3002 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003003 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003004 /* finalize parent pointers to the reallocated items */
3005 LY_ARRAY_FOR(act->groupings, u) {
3006 LY_LIST_FOR(act->groupings[u].data, child) {
3007 child->parent = (struct lysp_node*)&act->groupings[u];
3008 }
3009 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003010 return ret;
3011}
3012
Michal Vaskoea5abea2018-09-18 13:10:54 +02003013/**
3014 * @brief Parse the notification statement.
3015 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003016 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003017 * @param[in,out] data Data to read from, always moved to currently handled character.
3018 * @param[in,out] notifs Notifications to add to.
3019 *
3020 * @return LY_ERR values.
3021 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003022static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003023parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003024{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003025 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003026 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003027 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003028 enum yang_keyword kw;
3029 struct lysp_notif *notif;
Radek Krejcie86bf772018-12-14 11:39:53 +01003030 struct lysp_node *child;
3031 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032
Radek Krejci2c4e7172018-10-19 15:56:26 +02003033 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003034
3035 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003036 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003037 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003038 notif->nodetype = LYS_NOTIF;
3039 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003040
Radek Krejci6d6556c2018-11-08 09:37:45 +01003041 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003042 switch (kw) {
3043 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003044 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 +02003045 break;
3046 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003047 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 +02003048 break;
3049 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003050 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 +02003051 break;
3052 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003053 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003054 break;
3055
3056 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003057 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01003058 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003059 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003060 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003061 break;
3062 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003063 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003064 break;
3065 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003066 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003067 break;
3068 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003069 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003070 break;
3071 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003072 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003073 break;
3074 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003075 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076 break;
3077 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003078 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079 break;
3080
3081 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01003082 YANG_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003083 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003084 break;
3085 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003086 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003087 break;
3088 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003089 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003090 break;
3091 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003092 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003093 break;
3094 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003095 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003096 return LY_EVALID;
3097 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003098 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003099 /* finalize parent pointers to the reallocated items */
3100 LY_ARRAY_FOR(notif->groupings, u) {
3101 LY_LIST_FOR(notif->groupings[u].data, child) {
3102 child->parent = (struct lysp_node*)&notif->groupings[u];
3103 }
3104 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003105 return ret;
3106}
3107
Michal Vaskoea5abea2018-09-18 13:10:54 +02003108/**
3109 * @brief Parse the grouping statement.
3110 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003111 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003112 * @param[in,out] data Data to read from, always moved to currently handled character.
3113 * @param[in,out] groupings Groupings to add to.
3114 *
3115 * @return LY_ERR values.
3116 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003117static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003118parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003119{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003120 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003121 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003122 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003123 enum yang_keyword kw;
3124 struct lysp_grp *grp;
Radek Krejcie86bf772018-12-14 11:39:53 +01003125 struct lysp_node *child;
3126 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003127
Radek Krejci2c4e7172018-10-19 15:56:26 +02003128 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003129
3130 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003131 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003132 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003133 grp->nodetype = LYS_GROUPING;
3134 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135
Radek Krejci6d6556c2018-11-08 09:37:45 +01003136 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003137 switch (kw) {
3138 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003139 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 +02003140 break;
3141 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003142 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 +02003143 break;
3144 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003145 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003146 break;
3147
3148 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003149 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01003150 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003151 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003152 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003153 break;
3154 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003155 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003156 break;
3157 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003158 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003159 break;
3160 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003161 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003162 break;
3163 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003164 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003165 break;
3166 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003167 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003168 break;
3169 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003170 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003171 break;
3172
3173 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003174 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003175 break;
3176 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003177 YANG_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003178 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003179 break;
3180 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003181 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003182 break;
3183 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003184 YANG_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003185 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003186 break;
3187 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003188 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003189 break;
3190 default:
Radek Krejci10113652018-11-14 16:56:50 +01003191 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003192 return LY_EVALID;
3193 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003194 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003195 /* finalize parent pointers to the reallocated items */
3196 LY_ARRAY_FOR(grp->groupings, u) {
3197 LY_LIST_FOR(grp->groupings[u].data, child) {
3198 child->parent = (struct lysp_node*)&grp->groupings[u];
3199 }
3200 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003201 return ret;
3202}
3203
Michal Vaskoea5abea2018-09-18 13:10:54 +02003204/**
3205 * @brief Parse the refine statement.
3206 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003207 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003208 * @param[in,out] data Data to read from, always moved to currently handled character.
3209 * @param[in,out] augments Augments to add to.
3210 *
3211 * @return LY_ERR values.
3212 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003213static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003214parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003215{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003216 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003217 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003218 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003219 enum yang_keyword kw;
3220 struct lysp_augment *aug;
3221
Radek Krejci2c4e7172018-10-19 15:56:26 +02003222 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003223
3224 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003225 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003226 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003227 aug->nodetype = LYS_AUGMENT;
3228 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003229
Radek Krejci6d6556c2018-11-08 09:37:45 +01003230 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003231 switch (kw) {
3232 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003233 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 +02003234 break;
3235 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003236 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 +02003237 break;
3238 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003239 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 +02003240 break;
3241 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003242 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003243 break;
3244 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003245 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003246 break;
3247
3248 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003249 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01003250 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003251 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003252 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003253 break;
3254 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003255 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003256 break;
3257 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003258 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003259 break;
3260 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003261 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003262 break;
3263 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003264 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003265 break;
3266 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003267 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003268 break;
3269 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003270 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003271 break;
3272 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003273 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003274 break;
3275
3276 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003277 YANG_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003278 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003279 break;
3280 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003281 YANG_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003282 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003283 break;
3284 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003285 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003286 break;
3287 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003288 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003289 return LY_EVALID;
3290 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003291 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003292 return ret;
3293}
3294
Michal Vaskoea5abea2018-09-18 13:10:54 +02003295/**
3296 * @brief Parse the uses statement.
3297 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003298 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003299 * @param[in,out] data Data to read from, always moved to currently handled character.
3300 * @param[in,out] siblings Siblings to add to.
3301 *
3302 * @return LY_ERR values.
3303 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003304static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003305parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003306{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003307 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003308 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003309 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003310 enum yang_keyword kw;
3311 struct lysp_node *iter;
3312 struct lysp_node_uses *uses;
3313
3314 /* create structure */
3315 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003316 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003317 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003318 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003319
3320 /* insert into siblings */
3321 if (!*siblings) {
3322 *siblings = (struct lysp_node *)uses;
3323 } else {
3324 for (iter = *siblings; iter->next; iter = iter->next);
3325 iter->next = (struct lysp_node *)uses;
3326 }
3327
3328 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003329 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003330 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003331
3332 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003333 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003334 switch (kw) {
3335 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003336 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 +02003337 break;
3338 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003339 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 +02003340 break;
3341 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003342 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 +02003343 break;
3344 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003345 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003346 break;
3347 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003348 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003349 break;
3350
3351 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003352 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003353 break;
3354 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003355 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003356 break;
3357 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003358 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003359 break;
3360 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003361 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003362 return LY_EVALID;
3363 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003364 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003365 return ret;
3366}
3367
Michal Vaskoea5abea2018-09-18 13:10:54 +02003368/**
3369 * @brief Parse the case statement.
3370 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003371 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003372 * @param[in,out] data Data to read from, always moved to currently handled character.
3373 * @param[in,out] siblings Siblings to add to.
3374 *
3375 * @return LY_ERR values.
3376 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003377static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003378parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003379{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003380 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003381 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003382 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003383 enum yang_keyword kw;
3384 struct lysp_node *iter;
3385 struct lysp_node_case *cas;
3386
3387 /* create structure */
3388 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003389 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003390 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003391 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003392
3393 /* insert into siblings */
3394 if (!*siblings) {
3395 *siblings = (struct lysp_node *)cas;
3396 } else {
3397 for (iter = *siblings; iter->next; iter = iter->next);
3398 iter->next = (struct lysp_node *)cas;
3399 }
3400
3401 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003402 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003403 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003404
3405 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003406 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003407 switch (kw) {
3408 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003409 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 +02003410 break;
3411 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003412 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 +02003413 break;
3414 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003415 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 +02003416 break;
3417 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003418 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003419 break;
3420 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003421 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422 break;
3423
3424 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003425 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003426 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003427 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003428 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003429 break;
3430 case YANG_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003431 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003432 break;
3433 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003434 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003435 break;
3436 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003437 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003438 break;
3439 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003440 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003441 break;
3442 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003443 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003444 break;
3445 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003446 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003447 break;
3448 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003449 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003450 break;
3451 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003452 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003453 return LY_EVALID;
3454 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003455 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003456 return ret;
3457}
3458
Michal Vaskoea5abea2018-09-18 13:10:54 +02003459/**
3460 * @brief Parse the choice statement.
3461 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003462 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003463 * @param[in,out] data Data to read from, always moved to currently handled character.
3464 * @param[in,out] siblings Siblings to add to.
3465 *
3466 * @return LY_ERR values.
3467 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003468static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003469parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003470{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003471 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003472 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003473 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003474 enum yang_keyword kw;
3475 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003476 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003477
3478 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003479 choice = calloc(1, sizeof *choice);
3480 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3481 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003482 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483
3484 /* insert into siblings */
3485 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003486 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003487 } else {
3488 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003489 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003490 }
3491
3492 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003493 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003494 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003495
3496 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003497 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003498 switch (kw) {
3499 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003500 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003501 break;
3502 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003503 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 +02003504 break;
3505 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003506 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 +02003507 break;
3508 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003509 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003510 break;
3511 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003512 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 +02003513 break;
3514 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003515 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003516 break;
3517 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003518 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003519 break;
3520 case YANG_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003521 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 +02003522 break;
3523
3524 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003525 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003526 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003527 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003528 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003529 break;
3530 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003531 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003532 break;
3533 case YANG_CHOICE:
Radek Krejciceaf2122019-01-02 15:03:26 +01003534 YANG_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003535 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536 break;
3537 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003538 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003539 break;
3540 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003541 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003542 break;
3543 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003544 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003545 break;
3546 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003547 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003548 break;
3549 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003550 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003551 break;
3552 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003553 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003554 return LY_EVALID;
3555 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003556 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003557 LY_CHECK_RET(ret);
3558checks:
3559 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
3560 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
3561 return LY_EVALID;
3562 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563 return ret;
3564}
3565
Michal Vaskoea5abea2018-09-18 13:10:54 +02003566/**
3567 * @brief Parse the container statement.
3568 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003569 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003570 * @param[in,out] data Data to read from, always moved to currently handled character.
3571 * @param[in,out] siblings Siblings to add to.
3572 *
3573 * @return LY_ERR values.
3574 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003575static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003576parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003577{
3578 LY_ERR ret = 0;
3579 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003580 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003581 enum yang_keyword kw;
3582 struct lysp_node *iter;
3583 struct lysp_node_container *cont;
Radek Krejcie86bf772018-12-14 11:39:53 +01003584 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003585
3586 /* create structure */
3587 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003588 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003589 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003590 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003591
3592 /* insert into siblings */
3593 if (!*siblings) {
3594 *siblings = (struct lysp_node *)cont;
3595 } else {
3596 for (iter = *siblings; iter->next; iter = iter->next);
3597 iter->next = (struct lysp_node *)cont;
3598 }
3599
3600 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003601 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003602 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003603
3604 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003605 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003606 switch (kw) {
3607 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003608 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003609 break;
3610 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003611 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 +02003612 break;
3613 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003614 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 +02003615 break;
3616 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003617 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 +02003618 break;
3619 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003620 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003621 break;
3622 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003623 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003624 break;
3625 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003626 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 +02003627 break;
3628
3629 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003630 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003631 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003632 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003633 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003634 break;
3635 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003636 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003637 break;
3638 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003639 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003640 break;
3641 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003642 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643 break;
3644 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003645 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003646 break;
3647 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003648 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003649 break;
3650 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003651 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003652 break;
3653
3654 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003655 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003656 break;
3657 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003658 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003659 break;
3660 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003661 YANG_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003662 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003663 break;
3664 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003665 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003666 break;
3667 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003668 YANG_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003669 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003670 break;
3671 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003672 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003673 break;
3674 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003675 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003676 return LY_EVALID;
3677 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003678 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003679 /* finalize parent pointers to the reallocated items */
3680 LY_ARRAY_FOR(cont->groupings, u) {
3681 LY_LIST_FOR(cont->groupings[u].data, iter) {
3682 iter->parent = (struct lysp_node*)&cont->groupings[u];
3683 }
3684 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003685 return ret;
3686}
3687
Michal Vaskoea5abea2018-09-18 13:10:54 +02003688/**
3689 * @brief Parse the list statement.
3690 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003691 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003692 * @param[in,out] data Data to read from, always moved to currently handled character.
3693 * @param[in,out] siblings Siblings to add to.
3694 *
3695 * @return LY_ERR values.
3696 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003697static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003698parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003699{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003700 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003701 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003702 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003703 enum yang_keyword kw;
3704 struct lysp_node *iter;
3705 struct lysp_node_list *list;
Radek Krejcie86bf772018-12-14 11:39:53 +01003706 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003707
3708 /* create structure */
3709 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003710 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003711 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003712 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003713
3714 /* insert into siblings */
3715 if (!*siblings) {
3716 *siblings = (struct lysp_node *)list;
3717 } else {
3718 for (iter = *siblings; iter->next; iter = iter->next);
3719 iter->next = (struct lysp_node *)list;
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, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725
3726 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003727 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, &list->flags, &list->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, &list->dsc, Y_STR_ARG, &list->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, &list->iffeatures, Y_STR_ARG, &list->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, &list->ref, Y_STR_ARG, &list->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, &list->flags, &list->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, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746 break;
3747 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003748 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 +02003749 break;
3750 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003751 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003752 break;
3753 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003754 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003755 break;
3756 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003757 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003758 break;
3759 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003760 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 +02003761 break;
3762
3763 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003764 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003765 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003766 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003767 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003768 break;
3769 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003770 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003771 break;
3772 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003773 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003774 break;
3775 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003776 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003777 break;
3778 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003779 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003780 break;
3781 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003782 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003783 break;
3784 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003785 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003786 break;
3787
3788 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003789 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003790 break;
3791 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003792 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003793 break;
3794 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003795 YANG_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003796 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003797 break;
3798 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003799 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003800 break;
3801 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003802 YANG_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003803 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003804 break;
3805 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003806 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003807 break;
3808 default:
Radek Krejci10113652018-11-14 16:56:50 +01003809 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003810 return LY_EVALID;
3811 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003812 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003813 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01003814 /* finalize parent pointers to the reallocated items */
3815 LY_ARRAY_FOR(list->groupings, u) {
3816 LY_LIST_FOR(list->groupings[u].data, iter) {
3817 iter->parent = (struct lysp_node*)&list->groupings[u];
3818 }
3819 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003820checks:
3821 if (list->max && list->min > list->max) {
3822 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
3823 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3824 list->min, list->max);
3825 return LY_EVALID;
3826 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003827
3828 return ret;
3829}
3830
Michal Vaskoea5abea2018-09-18 13:10:54 +02003831/**
3832 * @brief Parse the yin-element statement.
3833 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003834 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003835 * @param[in,out] data Data to read from, always moved to currently handled character.
3836 * @param[in,out] flags Flags to write to.
3837 * @param[in,out] exts Extension instances to add to.
3838 *
3839 * @return LY_ERR values.
3840 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003841static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003842parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003843{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003844 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003845 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003846 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003847 enum yang_keyword kw;
3848
3849 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003850 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003851 return LY_EVALID;
3852 }
3853
3854 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003855 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003856
3857 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3858 *flags |= LYS_YINELEM_TRUE;
3859 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3860 *flags |= LYS_YINELEM_FALSE;
3861 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003862 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003863 free(buf);
3864 return LY_EVALID;
3865 }
3866 free(buf);
3867
Radek Krejci6d6556c2018-11-08 09:37:45 +01003868 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003869 switch (kw) {
3870 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003871 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3872 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003873 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003874 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875 return LY_EVALID;
3876 }
3877 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003878 return ret;
3879}
3880
Michal Vaskoea5abea2018-09-18 13:10:54 +02003881/**
3882 * @brief Parse the yin-element statement.
3883 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003884 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003885 * @param[in,out] data Data to read from, always moved to currently handled character.
3886 * @param[in,out] argument Value to write to.
3887 * @param[in,out] flags Flags to write to.
3888 * @param[in,out] exts Extension instances to add to.
3889 *
3890 * @return LY_ERR values.
3891 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003892static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003893parse_argument(struct ly_parser_ctx *ctx, const char **data, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003894{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003895 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003896 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003897 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003898 enum yang_keyword kw;
3899
3900 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003901 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003902 return LY_EVALID;
3903 }
3904
3905 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003906 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003907 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908
Radek Krejci6d6556c2018-11-08 09:37:45 +01003909 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003910 switch (kw) {
3911 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003912 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003913 break;
3914 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003915 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003916 break;
3917 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003918 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003919 return LY_EVALID;
3920 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003921 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 return ret;
3923}
3924
Michal Vaskoea5abea2018-09-18 13:10:54 +02003925/**
3926 * @brief Parse the extension statement.
3927 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003928 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003929 * @param[in,out] data Data to read from, always moved to currently handled character.
3930 * @param[in,out] extensions Extensions to add to.
3931 *
3932 * @return LY_ERR values.
3933 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003934static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003935parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003936{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003937 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003938 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003939 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003940 enum yang_keyword kw;
3941 struct lysp_ext *ex;
3942
Radek Krejci2c4e7172018-10-19 15:56:26 +02003943 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003944
3945 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003946 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003947 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003948
Radek Krejci6d6556c2018-11-08 09:37:45 +01003949 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003950 switch (kw) {
3951 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003952 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 +02003953 break;
3954 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003955 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 +02003956 break;
3957 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003958 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003959 break;
3960 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003961 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003962 break;
3963 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003964 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003965 break;
3966 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003967 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003968 return LY_EVALID;
3969 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003970 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003971 return ret;
3972}
3973
Michal Vaskoea5abea2018-09-18 13:10:54 +02003974/**
3975 * @brief Parse the deviate statement.
3976 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003977 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003978 * @param[in,out] data Data to read from, always moved to currently handled character.
3979 * @param[in,out] deviates Deviates to add to.
3980 *
3981 * @return LY_ERR values.
3982 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003983static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003984parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003985{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003986 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003987 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003988 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003989 enum yang_keyword kw;
3990 struct lysp_deviate *iter, *d;
3991 struct lysp_deviate_add *d_add = NULL;
3992 struct lysp_deviate_rpl *d_rpl = NULL;
3993 struct lysp_deviate_del *d_del = NULL;
3994 const char **d_units, ***d_uniques, ***d_dflts;
3995 struct lysp_restr **d_musts;
3996 uint16_t *d_flags;
3997 uint32_t *d_min, *d_max;
3998
3999 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004000 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004001
4002 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4003 dev_mod = LYS_DEV_NOT_SUPPORTED;
4004 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4005 dev_mod = LYS_DEV_ADD;
4006 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4007 dev_mod = LYS_DEV_REPLACE;
4008 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4009 dev_mod = LYS_DEV_DELETE;
4010 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004011 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004012 free(buf);
4013 return LY_EVALID;
4014 }
4015 free(buf);
4016
4017 /* create structure */
4018 switch (dev_mod) {
4019 case LYS_DEV_NOT_SUPPORTED:
4020 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004021 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004022 break;
4023 case LYS_DEV_ADD:
4024 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004025 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004026 d = (struct lysp_deviate *)d_add;
4027 d_units = &d_add->units;
4028 d_uniques = &d_add->uniques;
4029 d_dflts = &d_add->dflts;
4030 d_musts = &d_add->musts;
4031 d_flags = &d_add->flags;
4032 d_min = &d_add->min;
4033 d_max = &d_add->max;
4034 break;
4035 case LYS_DEV_REPLACE:
4036 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004037 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004038 d = (struct lysp_deviate *)d_rpl;
4039 d_units = &d_rpl->units;
4040 d_flags = &d_rpl->flags;
4041 d_min = &d_rpl->min;
4042 d_max = &d_rpl->max;
4043 break;
4044 case LYS_DEV_DELETE:
4045 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004046 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004047 d = (struct lysp_deviate *)d_del;
4048 d_units = &d_del->units;
4049 d_uniques = &d_del->uniques;
4050 d_dflts = &d_del->dflts;
4051 d_musts = &d_del->musts;
4052 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004053 break;
4054 default:
4055 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004056 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004057 }
4058 d->mod = dev_mod;
4059
4060 /* insert into siblings */
4061 if (!*deviates) {
4062 *deviates = d;
4063 } else {
4064 for (iter = *deviates; iter->next; iter = iter->next);
4065 iter->next = d;
4066 }
4067
Radek Krejci6d6556c2018-11-08 09:37:45 +01004068 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004069 switch (kw) {
4070 case YANG_CONFIG:
4071 switch (dev_mod) {
4072 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004073 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004074 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004075 return LY_EVALID;
4076 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004077 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004078 break;
4079 }
4080 break;
4081 case YANG_DEFAULT:
4082 switch (dev_mod) {
4083 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004084 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004085 return LY_EVALID;
4086 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004087 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 +02004088 break;
4089 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004090 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 +02004091 break;
4092 }
4093 break;
4094 case YANG_MANDATORY:
4095 switch (dev_mod) {
4096 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004097 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004098 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004099 return LY_EVALID;
4100 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004101 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004102 break;
4103 }
4104 break;
4105 case YANG_MAX_ELEMENTS:
4106 switch (dev_mod) {
4107 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004108 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004109 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004110 return LY_EVALID;
4111 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004112 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004113 break;
4114 }
4115 break;
4116 case YANG_MIN_ELEMENTS:
4117 switch (dev_mod) {
4118 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004119 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004120 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004121 return LY_EVALID;
4122 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004123 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004124 break;
4125 }
4126 break;
4127 case YANG_MUST:
4128 switch (dev_mod) {
4129 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004130 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004131 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004132 return LY_EVALID;
4133 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004134 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004135 break;
4136 }
4137 break;
4138 case YANG_TYPE:
4139 switch (dev_mod) {
4140 case LYS_DEV_NOT_SUPPORTED:
4141 case LYS_DEV_ADD:
4142 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004143 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004144 return LY_EVALID;
4145 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004146 if (d_rpl->type) {
4147 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4148 return LY_EVALID;
4149 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004150 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004151 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004152 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004153 break;
4154 }
4155 break;
4156 case YANG_UNIQUE:
4157 switch (dev_mod) {
4158 case LYS_DEV_NOT_SUPPORTED:
4159 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004160 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004161 return LY_EVALID;
4162 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004163 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 +02004164 break;
4165 }
4166 break;
4167 case YANG_UNITS:
4168 switch (dev_mod) {
4169 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004170 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004171 return LY_EVALID;
4172 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004173 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 +02004174 break;
4175 }
4176 break;
4177 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004178 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179 break;
4180 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004181 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004182 return LY_EVALID;
4183 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004184 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004185 return ret;
4186}
4187
Michal Vaskoea5abea2018-09-18 13:10:54 +02004188/**
4189 * @brief Parse the deviation statement.
4190 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004191 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004192 * @param[in,out] data Data to read from, always moved to currently handled character.
4193 * @param[in,out] deviations Deviations to add to.
4194 *
4195 * @return LY_ERR values.
4196 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004197static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004198parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004199{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004200 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004201 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004202 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004203 enum yang_keyword kw;
4204 struct lysp_deviation *dev;
4205
Radek Krejci2c4e7172018-10-19 15:56:26 +02004206 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004207
4208 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004209 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004210 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004211
Radek Krejci6d6556c2018-11-08 09:37:45 +01004212 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004213 switch (kw) {
4214 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004215 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 +02004216 break;
4217 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004218 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004219 break;
4220 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004221 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 +02004222 break;
4223 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004224 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004225 break;
4226 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004227 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004228 return LY_EVALID;
4229 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004230 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004231 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004232checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004233 /* mandatory substatements */
4234 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004235 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236 return LY_EVALID;
4237 }
4238
4239 return ret;
4240}
4241
Michal Vaskoea5abea2018-09-18 13:10:54 +02004242/**
4243 * @brief Parse the feature statement.
4244 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004245 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004246 * @param[in,out] data Data to read from, always moved to currently handled character.
4247 * @param[in,out] features Features to add to.
4248 *
4249 * @return LY_ERR values.
4250 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004251static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004252parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004253{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004254 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004255 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004256 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004257 enum yang_keyword kw;
4258 struct lysp_feature *feat;
4259
Radek Krejci2c4e7172018-10-19 15:56:26 +02004260 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004261
4262 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004263 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004264 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004265
Radek Krejci6d6556c2018-11-08 09:37:45 +01004266 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004267 switch (kw) {
4268 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004269 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 +02004270 break;
4271 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004272 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 +02004273 break;
4274 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004275 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 +02004276 break;
4277 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004278 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004279 break;
4280 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004281 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004282 break;
4283 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004284 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004285 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004286 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004287 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004288 return ret;
4289}
4290
Michal Vaskoea5abea2018-09-18 13:10:54 +02004291/**
4292 * @brief Parse the identity statement.
4293 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004294 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004295 * @param[in,out] data Data to read from, always moved to currently handled character.
4296 * @param[in,out] identities Identities to add to.
4297 *
4298 * @return LY_ERR values.
4299 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004300static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004301parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004302{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004303 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004304 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004305 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004306 enum yang_keyword kw;
4307 struct lysp_ident *ident;
4308
Radek Krejci2c4e7172018-10-19 15:56:26 +02004309 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004310
4311 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004312 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004313 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004314
Radek Krejci6d6556c2018-11-08 09:37:45 +01004315 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316 switch (kw) {
4317 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004318 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 +02004319 break;
4320 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01004321 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004322 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 +02004323 break;
4324 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004325 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 +02004326 break;
4327 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004328 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004329 break;
4330 case YANG_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004331 if (ident->bases && ctx->mod_version < 2) {
Radek Krejci10113652018-11-14 16:56:50 +01004332 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4333 return LY_EVALID;
4334 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004335 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 +02004336 break;
4337 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004338 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004339 break;
4340 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004341 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004342 return LY_EVALID;
4343 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004344 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004345 return ret;
4346}
4347
Michal Vaskoea5abea2018-09-18 13:10:54 +02004348/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004349 * @brief Finalize some of the (sub)module structure after parsing.
4350 *
4351 * Update parent pointers in the nodes inside grouping/RPC/Notification, which could be reallocated.
4352 *
4353 * @param[in] mod Parsed module to be updated.
4354 * @return LY_ERR value (currently only LY_SUCCESS, but it can change in future).
4355 */
4356static LY_ERR
4357parse_sub_module_finalize(struct lysp_module *mod)
4358{
4359 unsigned int u;
4360 struct lysp_node *child;
4361
4362 /* finalize parent pointers to the reallocated items */
4363 LY_ARRAY_FOR(mod->groupings, u) {
4364 LY_LIST_FOR(mod->groupings[u].data, child) {
4365 child->parent = (struct lysp_node*)&mod->groupings[u];
4366 }
4367 }
4368
4369 /* TODO the same finalization for rpcs and notifications, do also in the relevant nodes */
4370
4371 return LY_SUCCESS;
4372}
4373
4374/**
4375 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004376 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004377 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004378 * @param[in,out] data Data to read from, always moved to currently handled character.
4379 * @param[in,out] mod Module to write to.
4380 *
4381 * @return LY_ERR values.
4382 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004383static LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004384parse_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004385{
4386 LY_ERR ret = 0;
4387 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004388 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004389 enum yang_keyword kw, prev_kw = 0;
4390 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004391 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004392
4393 /* (sub)module name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004394 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004395 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004396
Radek Krejci6d6556c2018-11-08 09:37:45 +01004397 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004398
Radek Krejcie3846472018-10-15 15:24:51 +02004399#define CHECK_ORDER(SECTION) \
4400 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4401
Michal Vasko7fbc8162018-09-17 10:35:16 +02004402 switch (kw) {
4403 /* module header */
4404 case YANG_NAMESPACE:
4405 case YANG_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004406 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4407 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004408 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004409 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004410 break;
4411 /* linkage */
4412 case YANG_INCLUDE:
4413 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004414 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004415 break;
4416 /* meta */
4417 case YANG_ORGANIZATION:
4418 case YANG_CONTACT:
4419 case YANG_DESCRIPTION:
4420 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004421 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422 break;
4423
4424 /* revision */
4425 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004426 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004427 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428 /* body */
4429 case YANG_ANYDATA:
4430 case YANG_ANYXML:
4431 case YANG_AUGMENT:
4432 case YANG_CHOICE:
4433 case YANG_CONTAINER:
4434 case YANG_DEVIATION:
4435 case YANG_EXTENSION:
4436 case YANG_FEATURE:
4437 case YANG_GROUPING:
4438 case YANG_IDENTITY:
4439 case YANG_LEAF:
4440 case YANG_LEAF_LIST:
4441 case YANG_LIST:
4442 case YANG_NOTIFICATION:
4443 case YANG_RPC:
4444 case YANG_TYPEDEF:
4445 case YANG_USES:
4446 case YANG_CUSTOM:
4447 mod_stmt = Y_MOD_BODY;
4448 break;
4449 default:
4450 /* error handled in the next switch */
4451 break;
4452 }
Radek Krejcie3846472018-10-15 15:24:51 +02004453#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004454
Radek Krejcie3846472018-10-15 15:24:51 +02004455 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004456 switch (kw) {
4457 /* module header */
4458 case YANG_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004459 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4460 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004461 break;
4462 case YANG_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004463 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 +02004464 break;
4465 case YANG_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004466 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 +02004467 break;
4468
4469 /* linkage */
4470 case YANG_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004471 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004472 break;
4473 case YANG_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004474 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004475 break;
4476
4477 /* meta */
4478 case YANG_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004479 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 +02004480 break;
4481 case YANG_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004482 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 +02004483 break;
4484 case YANG_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004485 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 +02004486 break;
4487 case YANG_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004488 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 +02004489 break;
4490
4491 /* revision */
4492 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004493 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004494 break;
4495
4496 /* body */
4497 case YANG_ANYDATA:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004498 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004499 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004500 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004501 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004502 break;
4503 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004504 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004505 break;
4506 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004507 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004508 break;
4509 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004510 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004511 break;
4512 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004513 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004514 break;
4515 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004516 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004517 break;
4518 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004519 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004520 break;
4521
4522 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004523 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004524 break;
4525 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004526 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004527 break;
4528 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004529 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004530 break;
4531 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004532 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004533 break;
4534 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004535 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004536 break;
4537 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004538 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004539 break;
4540 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004541 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004542 break;
4543 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004544 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004545 break;
4546 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004547 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004548 break;
4549 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004550 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004551 break;
4552
4553 default:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004554 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004555 return LY_EVALID;
4556 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004557 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004558 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004559
Radek Krejci6d6556c2018-11-08 09:37:45 +01004560checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004561 /* finalize parent pointers to the reallocated items */
4562 LY_CHECK_RET(parse_sub_module_finalize(mod));
4563
Michal Vasko7fbc8162018-09-17 10:35:16 +02004564 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004565 if (!mod->mod->ns) {
4566 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
4567 return LY_EVALID;
4568 } else if (!mod->mod->prefix) {
4569 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
4570 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004571 }
4572
Radek Krejcie9e987e2018-10-31 12:50:27 +01004573 /* submodules share the namespace with the module names, so there must not be
4574 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004575 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4576 if (dup) {
4577 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
4578 return LY_EVALID;
4579 }
4580
4581 return ret;
4582}
4583
4584/**
4585 * @brief Parse submodule substatements.
4586 *
4587 * @param[in] ctx yang parser context for logging.
4588 * @param[in,out] data Data to read from, always moved to currently handled character.
4589 * @param[out] submod Parsed submodule structure.
4590 *
4591 * @return LY_ERR values.
4592 */
4593static LY_ERR
4594parse_submodule(struct ly_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
4595{
4596 LY_ERR ret = 0;
4597 char *buf, *word;
4598 size_t word_len;
4599 enum yang_keyword kw, prev_kw = 0;
4600 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4601 struct lysp_submodule *dup;
4602
4603 /* submodule name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004604 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004605 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4606
4607 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4608
4609#define CHECK_ORDER(SECTION) \
4610 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4611
4612 switch (kw) {
4613 /* module header */
4614 case YANG_BELONGS_TO:
4615 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4616 break;
4617 case YANG_YANG_VERSION:
4618 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4619 break;
4620 /* linkage */
4621 case YANG_INCLUDE:
4622 case YANG_IMPORT:
4623 CHECK_ORDER(Y_MOD_LINKAGE);
4624 break;
4625 /* meta */
4626 case YANG_ORGANIZATION:
4627 case YANG_CONTACT:
4628 case YANG_DESCRIPTION:
4629 case YANG_REFERENCE:
4630 CHECK_ORDER(Y_MOD_META);
4631 break;
4632
4633 /* revision */
4634 case YANG_REVISION:
4635 CHECK_ORDER(Y_MOD_REVISION);
4636 break;
4637 /* body */
4638 case YANG_ANYDATA:
4639 case YANG_ANYXML:
4640 case YANG_AUGMENT:
4641 case YANG_CHOICE:
4642 case YANG_CONTAINER:
4643 case YANG_DEVIATION:
4644 case YANG_EXTENSION:
4645 case YANG_FEATURE:
4646 case YANG_GROUPING:
4647 case YANG_IDENTITY:
4648 case YANG_LEAF:
4649 case YANG_LEAF_LIST:
4650 case YANG_LIST:
4651 case YANG_NOTIFICATION:
4652 case YANG_RPC:
4653 case YANG_TYPEDEF:
4654 case YANG_USES:
4655 case YANG_CUSTOM:
4656 mod_stmt = Y_MOD_BODY;
4657 break;
4658 default:
4659 /* error handled in the next switch */
4660 break;
4661 }
4662#undef CHECK_ORDER
4663
4664 prev_kw = kw;
4665 switch (kw) {
4666 /* module header */
4667 case YANG_YANG_VERSION:
4668 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4669 ctx->mod_version = submod->version;
4670 break;
4671 case YANG_BELONGS_TO:
4672 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4673 break;
4674
4675 /* linkage */
4676 case YANG_INCLUDE:
4677 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4678 break;
4679 case YANG_IMPORT:
4680 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4681 break;
4682
4683 /* meta */
4684 case YANG_ORGANIZATION:
4685 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4686 break;
4687 case YANG_CONTACT:
4688 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4689 break;
4690 case YANG_DESCRIPTION:
4691 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4692 break;
4693 case YANG_REFERENCE:
4694 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4695 break;
4696
4697 /* revision */
4698 case YANG_REVISION:
4699 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4700 break;
4701
4702 /* body */
4703 case YANG_ANYDATA:
4704 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
4705 /* fall through */
4706 case YANG_ANYXML:
4707 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4708 break;
4709 case YANG_CHOICE:
4710 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4711 break;
4712 case YANG_CONTAINER:
4713 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4714 break;
4715 case YANG_LEAF:
4716 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4717 break;
4718 case YANG_LEAF_LIST:
4719 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4720 break;
4721 case YANG_LIST:
4722 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4723 break;
4724 case YANG_USES:
4725 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4726 break;
4727
4728 case YANG_AUGMENT:
4729 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4730 break;
4731 case YANG_DEVIATION:
4732 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4733 break;
4734 case YANG_EXTENSION:
4735 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4736 break;
4737 case YANG_FEATURE:
4738 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4739 break;
4740 case YANG_GROUPING:
4741 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4742 break;
4743 case YANG_IDENTITY:
4744 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4745 break;
4746 case YANG_NOTIFICATION:
4747 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4748 break;
4749 case YANG_RPC:
4750 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4751 break;
4752 case YANG_TYPEDEF:
4753 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4754 break;
4755 case YANG_CUSTOM:
4756 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4757 break;
4758
4759 default:
4760 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
4761 return LY_EVALID;
4762 }
4763 }
4764 LY_CHECK_RET(ret);
4765
4766checks:
4767 /* finalize parent pointers to the reallocated items */
4768 LY_CHECK_RET(parse_sub_module_finalize((struct lysp_module*)submod));
4769
4770 /* mandatory substatements */
4771 if (!submod->belongsto) {
4772 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
4773 return LY_EVALID;
4774 }
4775
4776 /* submodules share the namespace with the module names, so there must not be
4777 * a submodule of the same name in the context, no need for revision matching */
4778 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4779 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
4780 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004781 return LY_EVALID;
4782 }
4783
Michal Vasko7fbc8162018-09-17 10:35:16 +02004784 return ret;
4785}
4786
Radek Krejcid4557c62018-09-17 11:42:09 +02004787LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004788yang_parse_submodule(struct ly_parser_ctx *context, const char *data, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004789{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004790 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004791 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004792 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004793 enum yang_keyword kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004794 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004795
4796 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004797 ret = get_keyword(context, &data, &kw, &word, &word_len);
4798 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004799
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004800 if (kw == YANG_MODULE) {
4801 LOGERR(context->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
4802 ret = LY_EINVAL;
4803 goto cleanup;
4804 } else if (kw != YANG_SUBMODULE) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004805 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004806 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004807 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004808 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004809 }
4810
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004811 mod_p = calloc(1, sizeof *mod_p);
4812 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4813 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004814
4815 /* substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004816 ret = parse_submodule(context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004817 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004818
4819 /* read some trailing spaces or new lines */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004820 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004821 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004822
4823 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004824 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004825 word_len, word);
4826 free(buf);
Radek Krejci40544fa2019-01-11 09:38:37 +01004827 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004828 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004829 }
4830 assert(!buf);
4831
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004832 mod_p->parsing = 0;
4833 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004834
Radek Krejcibbe09a92018-11-08 09:36:54 +01004835cleanup:
4836 if (ret) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004837 lysp_submodule_free(context->ctx, mod_p);
4838 }
4839
4840 return ret;
4841}
4842
4843LY_ERR
4844yang_parse_module(struct ly_parser_ctx *context, const char *data, struct lys_module *mod)
4845{
4846 LY_ERR ret = LY_SUCCESS;
4847 char *word, *buf;
4848 size_t word_len;
4849 enum yang_keyword kw;
4850 struct lysp_module *mod_p = NULL;
4851
4852 /* "module"/"submodule" */
4853 ret = get_keyword(context, &data, &kw, &word, &word_len);
4854 LY_CHECK_GOTO(ret, cleanup);
4855
4856 if (kw == YANG_SUBMODULE) {
4857 LOGERR(context->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
4858 ret = LY_EINVAL;
4859 goto cleanup;
4860 } else if (kw != YANG_MODULE) {
4861 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
4862 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004863 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004864 goto cleanup;
4865 }
4866
4867 mod_p = calloc(1, sizeof *mod_p);
4868 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4869 mod_p->mod = mod;
4870 mod_p->parsing = 1;
4871
4872 /* substatements */
4873 ret = parse_module(context, &data, mod_p);
4874 LY_CHECK_GOTO(ret, cleanup);
4875
4876 /* read some trailing spaces or new lines */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004877 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004878 LY_CHECK_GOTO(ret, cleanup);
4879
4880 if (word) {
4881 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
4882 word_len, word);
4883 free(buf);
Radek Krejci40544fa2019-01-11 09:38:37 +01004884 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004885 goto cleanup;
4886 }
4887 assert(!buf);
4888
4889 mod_p->parsing = 0;
4890 mod->parsed = mod_p;
4891
4892cleanup:
4893 if (ret) {
4894 lysp_module_free(mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004895 }
4896
Michal Vasko7fbc8162018-09-17 10:35:16 +02004897 return ret;
4898}