blob: 10155935b6fa6f2cc2b918136ebcbb28320466fb [file] [log] [blame]
Michal Vasko7fbc8162018-09-17 10:35:16 +02001/**
2 * @file parser_yang.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YANG parser
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
Michal Vasko7fbc8162018-09-17 10:35:16 +020014
15#include "common.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020016
17#include <assert.h>
18#include <ctype.h>
19#include <errno.h>
20#include <stdint.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
Michal Vasko7fbc8162018-09-17 10:35:16 +020025#include "context.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020026#include "dict.h"
27#include "extensions.h"
28#include "log.h"
29#include "set.h"
30#include "tree.h"
31#include "tree_schema.h"
Radek Krejci70853c52018-10-15 14:46:16 +020032#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020033
34/* Macro to check YANG's yang-char grammar rule */
35#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
36 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
37 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
38 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
39 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
40 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
41 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
42 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
43 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
44 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
45
Radek Krejciceaf2122019-01-02 15:03:26 +010046/**
47 * @brief Try to find object with MEMBER string matching the IDENT in the given ARRAY.
48 * Macro logs an error message and returns LY_EVALID in case of existence of a matching object.
49 *
50 * @param[in] CTX yang parser context for logging.
51 * @param[in] ARRAY [sized array](@ref sizedarrays) of a generic objects with member named MEMBER to search.
52 * @param[in] MEMBER Name of the member of the objects in the ARRAY to compare.
53 * @param[in] STMT Name of the compared YANG statements for logging.
54 * @param[in] IDENT String trying to find in the ARRAY's objects inside the MEMBER member.
55 */
Radek Krejcifaa1eac2018-10-30 14:34:55 +010056#define CHECK_UNIQUENESS(CTX, ARRAY, MEMBER, STMT, IDENT) \
57 if (ARRAY) { \
58 for (unsigned int u = 0; u < LY_ARRAY_SIZE(ARRAY) - 1; ++u) { \
59 if (!strcmp((ARRAY)[u].MEMBER, IDENT)) { \
60 LOGVAL_YANG(CTX, LY_VCODE_DUPIDENT, IDENT, STMT); \
61 return LY_EVALID; \
62 } \
63 } \
64 }
65
Radek Krejciceaf2122019-01-02 15:03:26 +010066/**
67 * @brief Insert WORD into the libyang context's dictionary and store as TARGET.
68 * @param[in] CTX yang parser context to access libyang context.
69 * @param[in] BUF buffer in case the word is not a constant and can be inserted directly (zero-copy)
70 * @param[out] TARGET variable where to store the pointer to the inserted value.
71 * @param[in] WORD string to store.
72 * @param[in] LEN length of the string in WORD to store.
73 */
Radek Krejci9fcacc12018-10-11 15:59:11 +020074#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
75 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
76 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020077
Radek Krejciceaf2122019-01-02 15:03:26 +010078/**
79 * @brief Move the DATA pointer by COUNT items. Also updates the indent value in yang parser context
80 * @param[in] CTX yang parser context to update its indent value.
81 * @param[in,out] DATA pointer to move
82 * @param[in] COUNT number of items for which the DATA pointer is supposed to move on.
83 */
Radek Krejci2b610482019-01-02 13:36:09 +010084#define MOVE_INPUT(CTX, DATA, COUNT) (*(DATA))+=COUNT;(CTX)->indent+=COUNT
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020085
Michal Vaskoea5abea2018-09-18 13:10:54 +020086/**
87 * @brief Loop through all substatements providing, return if there are none.
88 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020089 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020090 * @param[in] DATA Raw data to read from.
91 * @param[out] KW YANG keyword read.
92 * @param[out] WORD Pointer to the keyword itself.
93 * @param[out] WORD_LEN Length of the keyword.
94 * @param[out] ERR Variable for error storing.
95 *
96 * @return In case there are no substatements or a fatal error encountered.
97 */
Radek Krejci6d6556c2018-11-08 09:37:45 +010098#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010099 LY_CHECK_RET(get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +0200100 if (KW == YANG_SEMICOLON) { \
Radek Krejci6d6556c2018-11-08 09:37:45 +0100101 CHECKGOTO; \
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100102 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +0200103 } \
104 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +0200105 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +0200106 return LY_EVALID; \
107 } \
108 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
109 !ERR && (KW != YANG_RIGHT_BRACE); \
110 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
111
Radek Krejciceaf2122019-01-02 15:03:26 +0100112/**
113 * @brief Check module version is at least 2 (YANG 1.1) because of the keyword presence.
114 * Logs error message and returns LY_EVALID in case of module in YANG version 1.0.
115 * @param[in] CTX yang parser context to get current module and for logging.
116 * @param[in] KW keyword allowed only in YANG version 1.1 (or later) - for logging.
117 * @param[in] PARENT parent statement where the KW is present - for logging.
118 */
119#define YANG_CHECK_STMTVER2_RET(CTX, KW, PARENT) \
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100120 if ((CTX)->mod_version < 2) {LOGVAL_YANG((CTX), LY_VCODE_INCHILDSTMT2, KW, PARENT); return LY_EVALID;}
Radek Krejci10113652018-11-14 16:56:50 +0100121
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200122LY_ERR parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
123LY_ERR parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
124LY_ERR parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
125LY_ERR parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
126LY_ERR parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
127LY_ERR parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200128
Radek Krejci7fc68292019-06-12 13:51:09 +0200129static LY_ERR parse_finalize_reallocated(struct lys_parser_ctx *ctx, struct lysp_grp *groupings, struct lysp_augment *augments,
130 struct lysp_action *actions, struct lysp_notif *notifs);
131
Michal Vaskoea5abea2018-09-18 13:10:54 +0200132/**
133 * @brief Add another character to dynamic buffer, a low-level function.
134 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200135 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200136 *
Radek Krejci404251e2018-10-09 12:06:44 +0200137 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200138 * @param[in, out] input Input string to process.
139 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200140 * @param[in,out] buf Buffer to use, can be moved by realloc().
141 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200142 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200143 *
144 * @return LY_ERR values.
145 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200146LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200147buf_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 +0200148{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200149 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200150 *buf_len += 16;
151 *buf = ly_realloc(*buf, *buf_len);
152 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
153 }
Radek Krejcic0917392019-04-10 13:04:04 +0200154 if (*buf_used) {
155 memcpy(&(*buf)[*buf_used], *input, len);
156 } else {
157 memcpy(*buf, *input, len);
158 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200159
Radek Krejci44ceedc2018-10-02 15:54:31 +0200160 (*buf_used) += len;
161 (*input) += len;
162
Michal Vasko7fbc8162018-09-17 10:35:16 +0200163 return LY_SUCCESS;
164}
165
Michal Vaskoea5abea2018-09-18 13:10:54 +0200166/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200167 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200168 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200169 * @param[in] ctx yang parser context for logging.
170 * @param[in] c UTF8 code point of a character to check.
171 * @return LY_ERR values.
172 */
173static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200174check_stringchar(struct lys_parser_ctx *ctx, unsigned int c)
Radek Krejci44ceedc2018-10-02 15:54:31 +0200175{
176 if (!is_yangutf8char(c)) {
177 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
178 return LY_EVALID;
179 }
180 return LY_SUCCESS;
181}
182
183/**
184 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
185 *
186 * @param[in] ctx yang parser context for logging.
187 * @param[in] c UTF8 code point of a character to check.
188 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200189 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
190 * 0 - colon not yet found (no prefix)
191 * 1 - \p c is the colon character
192 * 2 - prefix already processed, now processing the identifier
193 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200194 * If the identifier cannot be prefixed, NULL is expected.
195 * @return LY_ERR values.
196 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200197LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200198check_identifierchar(struct lys_parser_ctx *ctx, unsigned int c, int first, int *prefix)
Radek Krejci44ceedc2018-10-02 15:54:31 +0200199{
200 if (first || (prefix && (*prefix) == 1)) {
201 if (!is_yangidentstartchar(c)) {
202 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
203 return LY_EVALID;
204 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200205 if (prefix) {
206 if (first) {
207 (*prefix) = 0;
208 } else {
209 (*prefix) = 2;
210 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200211 }
212 } else if (c == ':' && prefix && (*prefix) == 0) {
213 (*prefix) = 1;
214 } else if (!is_yangidentchar(c)) {
215 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
216 return LY_EVALID;
217 }
218
219 return LY_SUCCESS;
220}
221
222/**
223 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
224 *
225 * @param[in] ctx yang parser context for logging.
226 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
227 * when function returns.
228 * @param[in] arg Type of the input string to select method of checking character validity.
229 * @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 +0200230 * 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 +0200231 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
232 * @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 +0200233 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200234 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200235 *
236 * @return LY_ERR values.
237 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200238LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200239buf_store_char(struct lys_parser_ctx *ctx, const char **input, enum yang_arg arg,
Radek Krejci44ceedc2018-10-02 15:54:31 +0200240 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200241{
Radek Krejci404251e2018-10-09 12:06:44 +0200242 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200243 unsigned int c;
244 size_t len;
245
Radek Krejcif29b7c32019-04-09 16:17:49 +0200246 /* check valid combination of input paremeters - if need_buf specified, word_b must be provided */
247 assert(!need_buf || (need_buf && word_b));
248
Radek Krejci44ceedc2018-10-02 15:54:31 +0200249 /* get UTF8 code point (and number of bytes coding the character) */
250 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
251 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
252 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200253 if (c == '\n') {
254 ctx->indent = 0;
255 } else {
256 /* note - even the multibyte character is count as 1 */
257 ++ctx->indent;
258 }
259
Radek Krejci44ceedc2018-10-02 15:54:31 +0200260 /* check character validity */
261 switch (arg) {
262 case Y_IDENTIF_ARG:
263 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
264 break;
265 case Y_PREF_IDENTIF_ARG:
266 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
267 break;
268 case Y_STR_ARG:
269 case Y_MAYBE_STR_ARG:
270 LY_CHECK_RET(check_stringchar(ctx, c));
271 break;
272 }
273
Michal Vasko7fbc8162018-09-17 10:35:16 +0200274 if (word_b && *word_b) {
275 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200276 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200277 return LY_EMEM;
278 }
279
280 /* in case of realloc */
281 *word_p = *word_b;
Radek Krejcif29b7c32019-04-09 16:17:49 +0200282 } else if (word_b && need_buf) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200283 /* first time we need a buffer, copy everything read up to now */
284 if (*word_len) {
285 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200286 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200287 *buf_len = *word_len;
288 memcpy(*word_b, *word_p, *word_len);
289 }
290
291 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200292 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200293 return LY_EMEM;
294 }
295
296 /* in case of realloc */
297 *word_p = *word_b;
298 } else {
299 /* just remember the first character pointer */
300 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200301 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200302 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200303 /* ... and update the word's length */
304 (*word_len) += len;
305 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200306 }
307
308 return LY_SUCCESS;
309}
310
Michal Vaskoea5abea2018-09-18 13:10:54 +0200311/**
312 * @brief Skip YANG comment in data.
313 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200314 * @param[in] ctx yang parser context for logging.
315 * @param[in,out] data Data to read from, automatically moved after the comment.
316 * @param[in] comment Type of the comment to process:
317 * 1 for a one-line comment,
318 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200319 *
320 * @return LY_ERR values.
321 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200322LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200323skip_comment(struct lys_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200324{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200325 /* internal statuses: 0 - comment ended,
326 * 1 - in line comment,
327 * 2 - in block comment,
328 * 3 - in block comment with last read character '*'
329 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200330 while (**data && comment) {
331 switch (comment) {
332 case 1:
333 if (**data == '\n') {
334 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200335 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200336 }
337 break;
338 case 2:
339 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200340 comment = 3;
341 } else if (**data == '\n') {
342 ++ctx->line;
343 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200344 break;
345 case 3:
346 if (**data == '/') {
347 comment = 0;
Radek Krejci5b930492019-06-11 14:54:08 +0200348 } else if (**data != '*') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200349 if (**data == '\n') {
350 ++ctx->line;
351 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200352 comment = 2;
353 }
354 break;
355 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200356 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200357 }
358
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200359 if (**data == '\n') {
360 ctx->indent = 0;
361 } else {
362 ++ctx->indent;
363 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200364 ++(*data);
365 }
366
367 if (!**data && (comment > 1)) {
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200368 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-input, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200369 return LY_EVALID;
370 }
371
372 return LY_SUCCESS;
373}
374
Michal Vaskoea5abea2018-09-18 13:10:54 +0200375/**
376 * @brief Read a quoted string from data.
377 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200378 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200379 * @param[in,out] data Data to read from, always moved to currently handled character.
380 * @param[in] arg Type of YANG keyword argument expected.
381 * @param[out] word_p Pointer to the read quoted string.
382 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
383 * set to NULL. Otherwise equal to \p word_p.
384 * @param[out] word_len Length of the read quoted string.
385 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
386 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
387 * indenation in the final quoted string.
388 *
389 * @return LY_ERR values.
390 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200391static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200392read_qstring(struct lys_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len,
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200393 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200394{
395 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
396 * 4 - string finished, now skipping whitespaces looking for +,
397 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200398 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200399 const char *c;
400
401 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200402 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200403 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200404 } else {
405 assert(**data == '\'');
406 string = 1;
407 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200408 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200409
410 while (**data && string) {
411 switch (string) {
412 case 1:
413 switch (**data) {
414 case '\'':
415 /* string may be finished, but check for + */
416 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200417 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200418 break;
419 default:
420 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200421 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 +0200422 break;
423 }
424 break;
425 case 2:
426 switch (**data) {
427 case '\"':
428 /* string may be finished, but check for + */
429 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200430 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200431 break;
432 case '\\':
433 /* special character following */
434 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200435 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200436 break;
437 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200438 if (current_indent < block_indent) {
439 ++current_indent;
440 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200441 } else {
442 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200443 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 +0200444 }
445 break;
446 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200447 if (current_indent < block_indent) {
448 assert(need_buf);
449 current_indent += 8;
450 ctx->indent += 8;
451 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
452 /* store leftover spaces from the tab */
453 c = " ";
454 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 +0200455 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200456 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200457 } else {
458 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200459 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 +0200460 /* additional characters for indentation - only 1 was count in buf_store_char */
461 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200462 }
463 break;
464 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200465 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200466 /* we will be removing the indents so we need our own buffer */
467 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200468
469 /* remove trailing tabs and spaces */
470 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
471 --(*word_len);
472 }
473
474 /* start indentation */
475 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200476 }
477
478 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200479 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
480
481 /* maintain line number */
482 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200483
484 /* reset context indentation counter for possible string after this one */
485 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200486 break;
487 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200488 /* first non-whitespace character, stop eating indentation */
489 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200490
491 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200492 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 +0200493 break;
494 }
495 break;
496 case 3:
497 /* string encoded characters */
498 switch (**data) {
499 case 'n':
500 c = "\n";
501 break;
502 case 't':
503 c = "\t";
504 break;
505 case '\"':
506 c = *data;
507 break;
508 case '\\':
509 c = *data;
510 break;
511 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200512 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200513 return LY_EVALID;
514 }
515
516 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200517 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 +0200518
519 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200520 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200521 break;
522 case 4:
523 switch (**data) {
524 case '+':
525 /* string continues */
526 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200527 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200528 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200529 case '\n':
530 ++ctx->line;
531 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200532 case ' ':
533 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200534 /* just skip */
535 break;
536 default:
537 /* string is finished */
538 goto string_end;
539 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200540 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200541 break;
542 case 5:
543 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200544 case '\n':
545 ++ctx->line;
546 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200547 case ' ':
548 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200549 /* skip */
550 break;
551 case '\'':
552 string = 1;
553 break;
554 case '\"':
555 string = 2;
556 break;
557 default:
558 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200559 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200560 return LY_EVALID;
561 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200562 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200563 break;
564 default:
565 return LY_EINT;
566 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200567 }
568
569string_end:
Radek Krejci4e199f52019-05-28 09:09:28 +0200570 if (arg <= Y_PREF_IDENTIF_ARG && !(*word_len)) {
571 /* empty identifier */
572 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Statement argument is required.");
573 return LY_EVALID;
574 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200575 return LY_SUCCESS;
576}
577
Michal Vaskoea5abea2018-09-18 13:10:54 +0200578/**
579 * @brief Get another YANG string from the raw data.
580 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200581 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200582 * @param[in,out] data Data to read from, always moved to currently handled character.
583 * @param[in] arg Type of YANG keyword argument expected.
Radek Krejcid3ca0632019-04-16 16:54:54 +0200584 * @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 +0200585 * @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 +0200586 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
587 * set to NULL. Otherwise equal to \p word_p.
588 * @param[out] word_len Length of the read string.
589 *
590 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200591 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200592LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200593get_argument(struct lys_parser_ctx *ctx, const char **data, enum yang_arg arg,
Radek Krejcid3ca0632019-04-16 16:54:54 +0200594 uint16_t *flags, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200595{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200596 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200597
598 /* word buffer - dynamically allocated */
599 *word_b = NULL;
600
601 /* word pointer - just a pointer to data */
602 *word_p = NULL;
603
604 *word_len = 0;
605 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200606 switch (**data) {
607 case '\'':
608 case '\"':
609 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200610 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
611 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
612 "unquoted string character, optsep, semicolon or opening brace");
613 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200614 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200615 if (flags) {
616 (*flags) |= (**data) == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
617 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100618 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200619 goto str_end;
620 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200621 if ((*data)[1] == '/') {
622 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200623 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100624 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200625 } else if ((*data)[1] == '*') {
626 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200627 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100628 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200629 } else {
630 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100631 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 +0200632 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200633 break;
634 case ' ':
635 if (*word_len) {
636 /* word is finished */
637 goto str_end;
638 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200639 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200640 break;
641 case '\t':
642 if (*word_len) {
643 /* word is finished */
644 goto str_end;
645 }
646 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200647 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200648
649 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200650 break;
651 case '\n':
652 if (*word_len) {
653 /* word is finished */
654 goto str_end;
655 }
656 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200657 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200658
659 /* track line numbers */
660 ++ctx->line;
661
662 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200663 break;
664 case ';':
665 case '{':
666 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
667 /* word is finished */
668 goto str_end;
669 }
670
Radek Krejci44ceedc2018-10-02 15:54:31 +0200671 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200672 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200673 case '}':
674 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
675 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
676 "unquoted string character, optsep, semicolon or opening brace");
677 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200678 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200679 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 +0200680 break;
681 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200682 }
683
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200684 /* unexpected end of loop */
685 LOGVAL_YANG(ctx, LY_VCODE_EOF);
686 return LY_EVALID;
687
Michal Vasko7fbc8162018-09-17 10:35:16 +0200688str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200689 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200690 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200691 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
692 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
693 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200694 *word_p = *word_b;
695 }
696
697 return LY_SUCCESS;
698}
699
Michal Vaskoea5abea2018-09-18 13:10:54 +0200700/**
701 * @brief Get another YANG keyword from the raw data.
702 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200703 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200704 * @param[in,out] data Data to read from, always moved to currently handled character.
705 * @param[out] kw YANG keyword read.
706 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
707 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
708 *
709 * @return LY_ERR values.
710 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200711LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200712get_keyword(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200713{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200714 int prefix;
715 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200716 unsigned int c;
717 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200718
719 if (word_p) {
720 *word_p = NULL;
721 *word_len = 0;
722 }
723
724 /* first skip "optsep", comments */
725 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200726 switch (**data) {
727 case '/':
728 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200729 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200730 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100731 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200732 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200733 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200734 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100735 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200736 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200737 /* error - not a comment after all, keyword cannot start with slash */
738 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
739 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200740 }
Radek Krejci13028282019-06-11 14:56:48 +0200741 continue;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200742 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200743 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200744 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200745 ctx->indent = 0;
746 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200747 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200748 /* skip whitespaces (optsep) */
749 ++ctx->indent;
750 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200751 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200752 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200753 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200754 break;
755 default:
756 /* either a keyword start or an invalid character */
757 goto keyword_start;
758 }
759
760 ++(*data);
761 }
762
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200763#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
764#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
765#define IF_KW_PREFIX_END }
766
Michal Vasko7fbc8162018-09-17 10:35:16 +0200767keyword_start:
768 word_start = *data;
769 *kw = YANG_NONE;
770
771 /* read the keyword itself */
772 switch (**data) {
773 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200774 MOVE_INPUT(ctx, data, 1);
775 IF_KW("rgument", 7, YANG_ARGUMENT)
776 else IF_KW("ugment", 6, YANG_AUGMENT)
777 else IF_KW("ction", 5, YANG_ACTION)
778 else IF_KW_PREFIX("ny", 2)
779 IF_KW("data", 4, YANG_ANYDATA)
780 else IF_KW("xml", 3, YANG_ANYXML)
781 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200782 break;
783 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200784 MOVE_INPUT(ctx, data, 1);
785 IF_KW("ase", 3, YANG_BASE)
786 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
787 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200788 break;
789 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200790 MOVE_INPUT(ctx, data, 1);
791 IF_KW("ase", 3, YANG_CASE)
792 else IF_KW("hoice", 5, YANG_CHOICE)
793 else IF_KW_PREFIX("on", 2)
794 IF_KW("fig", 3, YANG_CONFIG)
795 else IF_KW_PREFIX("ta", 2)
796 IF_KW("ct", 2, YANG_CONTACT)
797 else IF_KW("iner", 4, YANG_CONTAINER)
798 IF_KW_PREFIX_END
799 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200800 break;
801 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200802 MOVE_INPUT(ctx, data, 1);
803 IF_KW_PREFIX("e", 1)
804 IF_KW("fault", 5, YANG_DEFAULT)
805 else IF_KW("scription", 9, YANG_DESCRIPTION)
806 else IF_KW_PREFIX("viat", 4)
807 IF_KW("e", 1, YANG_DEVIATE)
808 else IF_KW("ion", 3, YANG_DEVIATION)
809 IF_KW_PREFIX_END
810 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200811 break;
812 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200813 MOVE_INPUT(ctx, data, 1);
814 IF_KW("num", 3, YANG_ENUM)
815 else IF_KW_PREFIX("rror-", 5)
816 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
817 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
818 IF_KW_PREFIX_END
819 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200820 break;
821 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200822 MOVE_INPUT(ctx, data, 1);
823 IF_KW("eature", 6, YANG_FEATURE)
824 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200825 break;
826 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200827 MOVE_INPUT(ctx, data, 1);
828 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200829 break;
830 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200831 MOVE_INPUT(ctx, data, 1);
832 IF_KW("dentity", 7, YANG_IDENTITY)
833 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
834 else IF_KW("mport", 5, YANG_IMPORT)
835 else IF_KW_PREFIX("n", 1)
836 IF_KW("clude", 5, YANG_INCLUDE)
837 else IF_KW("put", 3, YANG_INPUT)
838 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200839 break;
840 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200841 MOVE_INPUT(ctx, data, 1);
842 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200843 break;
844 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200845 MOVE_INPUT(ctx, data, 1);
846 IF_KW_PREFIX("e", 1)
847 IF_KW("af-list", 7, YANG_LEAF_LIST)
848 else IF_KW("af", 2, YANG_LEAF)
849 else IF_KW("ngth", 4, YANG_LENGTH)
850 IF_KW_PREFIX_END
851 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200852 break;
853 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200854 MOVE_INPUT(ctx, data, 1);
855 IF_KW_PREFIX("a", 1)
856 IF_KW("ndatory", 7, YANG_MANDATORY)
857 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
858 IF_KW_PREFIX_END
859 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
860 else IF_KW("ust", 3, YANG_MUST)
861 else IF_KW_PREFIX("od", 2)
862 IF_KW("ule", 3, YANG_MODULE)
863 else IF_KW("ifier", 5, YANG_MODIFIER)
864 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200865 break;
866 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200867 MOVE_INPUT(ctx, data, 1);
868 IF_KW("amespace", 8, YANG_NAMESPACE)
869 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200870 break;
871 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200872 MOVE_INPUT(ctx, data, 1);
873 IF_KW_PREFIX("r", 1)
874 IF_KW("dered-by", 8, YANG_ORDERED_BY)
875 else IF_KW("ganization", 10, YANG_ORGANIZATION)
876 IF_KW_PREFIX_END
877 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200878 break;
879 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200880 MOVE_INPUT(ctx, data, 1);
881 IF_KW("ath", 3, YANG_PATH)
882 else IF_KW("attern", 6, YANG_PATTERN)
883 else IF_KW("osition", 7, YANG_POSITION)
884 else IF_KW_PREFIX("re", 2)
885 IF_KW("fix", 3, YANG_PREFIX)
886 else IF_KW("sence", 5, YANG_PRESENCE)
887 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200888 break;
889 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200890 MOVE_INPUT(ctx, data, 1);
891 IF_KW("ange", 4, YANG_RANGE)
892 else IF_KW_PREFIX("e", 1)
893 IF_KW_PREFIX("f", 1)
894 IF_KW("erence", 6, YANG_REFERENCE)
895 else IF_KW("ine", 3, YANG_REFINE)
896 IF_KW_PREFIX_END
897 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
898 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
899 else IF_KW("vision", 6, YANG_REVISION)
900 IF_KW_PREFIX_END
901 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200902 break;
903 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200904 MOVE_INPUT(ctx, data, 1);
905 IF_KW("tatus", 5, YANG_STATUS)
906 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200907 break;
908 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200909 MOVE_INPUT(ctx, data, 1);
910 IF_KW("ypedef", 6, YANG_TYPEDEF)
911 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200912 break;
913 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200914 MOVE_INPUT(ctx, data, 1);
915 IF_KW_PREFIX("ni", 2)
916 IF_KW("que", 3, YANG_UNIQUE)
917 else IF_KW("ts", 2, YANG_UNITS)
918 IF_KW_PREFIX_END
919 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200920 break;
921 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200922 MOVE_INPUT(ctx, data, 1);
923 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200924 break;
925 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200926 MOVE_INPUT(ctx, data, 1);
927 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200928 break;
929 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200930 MOVE_INPUT(ctx, data, 1);
931 IF_KW("ang-version", 11, YANG_YANG_VERSION)
932 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200933 break;
934 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200935 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200936 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200937 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200938 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200939 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200940 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200941 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200942 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200943 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200944 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200945 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200946 default:
947 break;
948 }
949
Radek Krejci0904c162019-01-02 15:03:59 +0100950#undef IF_KW
951#undef IF_KW_PREFIX
952#undef IF_KW_PREFIX_END
953
Michal Vasko7fbc8162018-09-17 10:35:16 +0200954 if (*kw != YANG_NONE) {
955 /* make sure we have the whole keyword */
956 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200957 case '\n':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200958 case '\t':
Radek Krejciabdd8062019-06-11 16:44:19 +0200959 case ' ':
960 /* mandatory "sep" is just checked, not eaten so nothing in the context is updated */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200961 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200962 case ':':
963 /* keyword is not actually a keyword, but prefix of an extension.
964 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
965 * and we will be checking the keyword (extension instance) itself */
966 prefix = 1;
967 MOVE_INPUT(ctx, data, 1);
968 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200969 case '{':
970 /* allowed only for input and output statements which can be without arguments */
971 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
972 break;
973 }
974 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200975 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200976 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200977 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
978 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200979 return LY_EVALID;
980 }
981 } else {
982 /* still can be an extension */
983 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200984extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200985 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200986 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
987 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200988 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200989 /* check character validity */
990 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200991 }
992 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200993 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200994 return LY_EVALID;
995 }
996
997 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200998 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200999 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001000 return LY_EVALID;
1001 }
1002
1003 *kw = YANG_CUSTOM;
1004 }
Radek Krejci626df482018-10-11 15:06:31 +02001005success:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001006 if (word_p) {
1007 *word_p = (char *)word_start;
1008 *word_len = *data - word_start;
1009 }
1010
1011 return LY_SUCCESS;
1012}
1013
Michal Vaskoea5abea2018-09-18 13:10:54 +02001014/**
1015 * @brief Parse extension instance substatements.
1016 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001017 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001018 * @param[in,out] data Data to read from, always moved to currently handled character.
1019 * @param[in] word Extension instance substatement name (keyword).
1020 * @param[in] word_len Extension instance substatement name length.
1021 * @param[in,out] child Children of this extension instance to add to.
1022 *
1023 * @return LY_ERR values.
1024 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001025static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001026parse_ext_substmt(struct lys_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001027 struct lysp_stmt **child)
1028{
1029 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001030 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001031 enum yang_keyword kw;
1032 struct lysp_stmt *stmt, *par_child;
1033
1034 stmt = calloc(1, sizeof *stmt);
1035 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
1036
Radek Krejcibb9b1982019-04-08 14:24:59 +02001037 /* insert into parent statements */
1038 if (!*child) {
1039 *child = stmt;
1040 } else {
1041 for (par_child = *child; par_child->next; par_child = par_child->next);
1042 par_child->next = stmt;
1043 }
1044
Radek Krejci44ceedc2018-10-02 15:54:31 +02001045 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001046
1047 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001048 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001049
Radek Krejci0ae092d2018-09-20 16:43:19 +02001050 if (word) {
1051 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001052 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001053 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001054 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001055 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001056 }
1057
Radek Krejci6d6556c2018-11-08 09:37:45 +01001058 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001059 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001060 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001061 return ret;
1062}
1063
Michal Vaskoea5abea2018-09-18 13:10:54 +02001064/**
1065 * @brief Parse extension instance.
1066 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001067 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001068 * @param[in,out] data Data to read from, always moved to currently handled character.
1069 * @param[in] ext_name Extension instance substatement name (keyword).
1070 * @param[in] ext_name_len Extension instance substatement name length.
1071 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1072 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1073 * @param[in,out] exts Extension instances to add to.
1074 *
1075 * @return LY_ERR values.
1076 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001077static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001078parse_ext(struct lys_parser_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001079 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1080{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001081 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001082 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001083 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001084 struct lysp_ext_instance *e;
1085 enum yang_keyword kw;
1086
Radek Krejci2c4e7172018-10-19 15:56:26 +02001087 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001088
1089 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001090 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001091 e->insubstmt = insubstmt;
1092 e->insubstmt_index = insubstmt_index;
1093
1094 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001095 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001096
Radek Krejci0ae092d2018-09-20 16:43:19 +02001097 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001098 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001099 }
1100
Radek Krejci6d6556c2018-11-08 09:37:45 +01001101 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001102 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001103 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001104 return ret;
1105}
1106
Michal Vaskoea5abea2018-09-18 13:10:54 +02001107/**
1108 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1109 * description, etc...
1110 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001111 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001112 * @param[in,out] data Data to read from, always moved to currently handled character.
1113 * @param[in] substmt Type of this substatement.
1114 * @param[in] substmt_index Index of this substatement.
1115 * @param[in,out] value Place to store the parsed value.
1116 * @param[in] arg Type of the YANG keyword argument (of the value).
1117 * @param[in,out] exts Extension instances to add to.
1118 *
1119 * @return LY_ERR values.
1120 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001121static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001122parse_text_field(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001123 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1124{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001125 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001126 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001127 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001128 enum yang_keyword kw;
1129
1130 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001131 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001132 return LY_EVALID;
1133 }
1134
1135 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001136 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001137
Radek Krejci9006a4e2019-06-11 14:56:56 +02001138 if (!word_len) {
1139 /* empty value */
1140 word = "";
1141 }
1142
Michal Vasko7fbc8162018-09-17 10:35:16 +02001143 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001144 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001145
Radek Krejci6d6556c2018-11-08 09:37:45 +01001146 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001147 switch (kw) {
1148 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001149 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001150 break;
1151 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001152 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001153 return LY_EVALID;
1154 }
1155 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001156 return ret;
1157}
1158
Michal Vaskoea5abea2018-09-18 13:10:54 +02001159/**
1160 * @brief Parse the yang-version statement.
1161 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001162 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001163 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001164 * @param[out] version Storage for the parsed information.
1165 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001166 *
1167 * @return LY_ERR values.
1168 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001169static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001170parse_yangversion(struct lys_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001171{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001172 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001173 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001174 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175 enum yang_keyword kw;
1176
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001177 if (*version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001178 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001179 return LY_EVALID;
1180 }
1181
1182 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001183 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184
1185 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001186 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001187 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001188 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001190 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001191 free(buf);
1192 return LY_EVALID;
1193 }
1194 free(buf);
1195
Radek Krejci6d6556c2018-11-08 09:37:45 +01001196 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001197 switch (kw) {
1198 case YANG_CUSTOM:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001199 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001200 break;
1201 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001202 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001203 return LY_EVALID;
1204 }
1205 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001206 return ret;
1207}
1208
Michal Vaskoea5abea2018-09-18 13:10:54 +02001209/**
1210 * @brief Parse the belongs-to statement.
1211 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001212 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001213 * @param[in,out] data Data to read from, always moved to currently handled character.
1214 * @param[in,out] belongsto Place to store the parsed value.
1215 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1216 * @param[in,out] exts Extension instances to add to.
1217 *
1218 * @return LY_ERR values.
1219 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001220static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001221parse_belongsto(struct lys_parser_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001222{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001223 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001224 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001225 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001226 enum yang_keyword kw;
1227
1228 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001229 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001230 return LY_EVALID;
1231 }
1232
1233 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001234 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001235
Radek Krejci44ceedc2018-10-02 15:54:31 +02001236 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001237 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001238 switch (kw) {
1239 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001240 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001241 break;
1242 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001243 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001244 break;
1245 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001246 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001247 return LY_EVALID;
1248 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001249 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001250 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001251checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001252 /* mandatory substatements */
1253 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001254 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001255 return LY_EVALID;
1256 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001257 return ret;
1258}
1259
Michal Vaskoea5abea2018-09-18 13:10:54 +02001260/**
1261 * @brief Parse the revision-date statement.
1262 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001263 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001264 * @param[in,out] data Data to read from, always moved to currently handled character.
1265 * @param[in,out] rev Array to store the parsed value in.
1266 * @param[in,out] exts Extension instances to add to.
1267 *
1268 * @return LY_ERR values.
1269 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001270static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001271parse_revisiondate(struct lys_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001272{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001273 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001274 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001275 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001276 enum yang_keyword kw;
1277
1278 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001279 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001280 return LY_EVALID;
1281 }
1282
1283 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001284 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001285
1286 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001287 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001288 free(buf);
1289 return LY_EVALID;
1290 }
1291
1292 /* store value and spend buf if allocated */
1293 strncpy(rev, word, word_len);
1294 free(buf);
1295
Radek Krejci6d6556c2018-11-08 09:37:45 +01001296 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001297 switch (kw) {
1298 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001299 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001300 break;
1301 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001302 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001303 return LY_EVALID;
1304 }
1305 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001306 return ret;
1307}
1308
Michal Vaskoea5abea2018-09-18 13:10:54 +02001309/**
1310 * @brief Parse the include statement.
1311 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001312 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001313 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001314 * @param[in,out] data Data to read from, always moved to currently handled character.
1315 * @param[in,out] includes Parsed includes to add to.
1316 *
1317 * @return LY_ERR values.
1318 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001319static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001320parse_include(struct lys_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001321{
Radek Krejcid33273d2018-10-25 14:55:52 +02001322 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001323 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001324 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001325 enum yang_keyword kw;
1326 struct lysp_include *inc;
1327
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001328 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001329
1330 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001331 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001332
Radek Krejci086c7132018-10-26 15:29:04 +02001333 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1334
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001335 /* submodules share the namespace with the module names, so there must not be
1336 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001337 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001338 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1339 return LY_EVALID;
1340 }
1341
Radek Krejci6d6556c2018-11-08 09:37:45 +01001342 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001343 switch (kw) {
1344 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001345 YANG_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001346 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 +02001347 break;
1348 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001349 YANG_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001350 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 +02001351 break;
1352 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001353 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001354 break;
1355 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001356 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001357 break;
1358 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001359 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001360 return LY_EVALID;
1361 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001362 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001363 return ret;
1364}
1365
Michal Vaskoea5abea2018-09-18 13:10:54 +02001366/**
1367 * @brief Parse the import statement.
1368 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001369 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001370 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001371 * @param[in,out] data Data to read from, always moved to currently handled character.
1372 * @param[in,out] imports Parsed imports to add to.
1373 *
1374 * @return LY_ERR values.
1375 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001376static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001377parse_import(struct lys_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001378{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001379 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001380 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001381 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001382 enum yang_keyword kw;
1383 struct lysp_import *imp;
1384
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001385 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001386
1387 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001388 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001389 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001390
Radek Krejci6d6556c2018-11-08 09:37:45 +01001391 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001392 switch (kw) {
1393 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001394 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 +01001395 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001396 break;
1397 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001398 YANG_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001399 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 +02001400 break;
1401 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001402 YANG_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001403 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 +02001404 break;
1405 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001406 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001407 break;
1408 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001409 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001410 break;
1411 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001412 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001413 return LY_EVALID;
1414 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001415 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001416 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001417checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001418 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001419 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001420
1421 return ret;
1422}
1423
Michal Vaskoea5abea2018-09-18 13:10:54 +02001424/**
1425 * @brief Parse the revision statement.
1426 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001427 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001428 * @param[in,out] data Data to read from, always moved to currently handled character.
1429 * @param[in,out] revs Parsed revisions to add to.
1430 *
1431 * @return LY_ERR values.
1432 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001433static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001434parse_revision(struct lys_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001435{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001436 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001437 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001438 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001439 enum yang_keyword kw;
1440 struct lysp_revision *rev;
1441
Radek Krejci2c4e7172018-10-19 15:56:26 +02001442 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001443
1444 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001445 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001446
1447 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001448 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001449 return LY_EVALID;
1450 }
1451
Radek Krejcib7db73a2018-10-24 14:18:40 +02001452 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001453 free(buf);
1454
Radek Krejci6d6556c2018-11-08 09:37:45 +01001455 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001456 switch (kw) {
1457 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001458 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 +02001459 break;
1460 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001461 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 +02001462 break;
1463 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001464 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001465 break;
1466 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001467 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001468 return LY_EVALID;
1469 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001470 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001471 return ret;
1472}
1473
Michal Vaskoea5abea2018-09-18 13:10:54 +02001474/**
1475 * @brief Parse a generic text field that can have more instances such as base.
1476 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001477 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001478 * @param[in,out] data Data to read from, always moved to currently handled character.
1479 * @param[in] substmt Type of this substatement.
1480 * @param[in,out] texts Parsed values to add to.
1481 * @param[in] arg Type of the expected argument.
1482 * @param[in,out] exts Extension instances to add to.
1483 *
1484 * @return LY_ERR values.
1485 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001486static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001487parse_text_fields(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001488 struct lysp_ext_instance **exts)
1489{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001490 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001491 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001492 const char **item;
1493 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001494 enum yang_keyword kw;
1495
1496 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001497 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001498
1499 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001500 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001501
Radek Krejci151a5b72018-10-19 14:21:44 +02001502 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001503 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001504 switch (kw) {
1505 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001506 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001507 break;
1508 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001509 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001510 return LY_EVALID;
1511 }
1512 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001513 return ret;
1514}
1515
Michal Vaskoea5abea2018-09-18 13:10:54 +02001516/**
1517 * @brief Parse the config statement.
1518 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001519 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001520 * @param[in,out] data Data to read from, always moved to currently handled character.
1521 * @param[in,out] flags Flags to add to.
1522 * @param[in,out] exts Extension instances to add to.
1523 *
1524 * @return LY_ERR values.
1525 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001526static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001527parse_config(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001528{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001529 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001530 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001531 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001532 enum yang_keyword kw;
1533
1534 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001535 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001536 return LY_EVALID;
1537 }
1538
1539 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001540 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001541
1542 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1543 *flags |= LYS_CONFIG_W;
1544 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1545 *flags |= LYS_CONFIG_R;
1546 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001547 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001548 free(buf);
1549 return LY_EVALID;
1550 }
1551 free(buf);
1552
Radek Krejci6d6556c2018-11-08 09:37:45 +01001553 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001554 switch (kw) {
1555 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001556 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001557 break;
1558 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001559 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001560 return LY_EVALID;
1561 }
1562 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001563 return ret;
1564}
1565
Michal Vaskoea5abea2018-09-18 13:10:54 +02001566/**
1567 * @brief Parse the mandatory statement.
1568 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001569 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001570 * @param[in,out] data Data to read from, always moved to currently handled character.
1571 * @param[in,out] flags Flags to add to.
1572 * @param[in,out] exts Extension instances to add to.
1573 *
1574 * @return LY_ERR values.
1575 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001576static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001577parse_mandatory(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001578{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001579 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001580 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001581 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001582 enum yang_keyword kw;
1583
1584 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001585 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001586 return LY_EVALID;
1587 }
1588
1589 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001590 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001591
1592 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1593 *flags |= LYS_MAND_TRUE;
1594 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1595 *flags |= LYS_MAND_FALSE;
1596 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001597 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001598 free(buf);
1599 return LY_EVALID;
1600 }
1601 free(buf);
1602
Radek Krejci6d6556c2018-11-08 09:37:45 +01001603 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001604 switch (kw) {
1605 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001606 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001607 break;
1608 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001609 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001610 return LY_EVALID;
1611 }
1612 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001613 return ret;
1614}
1615
Michal Vaskoea5abea2018-09-18 13:10:54 +02001616/**
1617 * @brief Parse a restriction such as range or length.
1618 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001619 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001620 * @param[in,out] data Data to read from, always moved to currently handled character.
1621 * @param[in] restr_kw Type of this particular restriction.
1622 * @param[in,out] exts Extension instances to add to.
1623 *
1624 * @return LY_ERR values.
1625 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001626static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001627parse_restr(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr *restr)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001628{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001629 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001630 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001631 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001632 enum yang_keyword kw;
1633
1634 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001635 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001636
Radek Krejci44ceedc2018-10-02 15:54:31 +02001637 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001638 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001639 switch (kw) {
1640 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001641 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 +02001642 break;
1643 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001644 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 +02001645 break;
1646 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001647 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 +02001648 break;
1649 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001650 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 +02001651 break;
1652 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001653 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001654 break;
1655 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001656 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001657 return LY_EVALID;
1658 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001659 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001660 return ret;
1661}
1662
Michal Vaskoea5abea2018-09-18 13:10:54 +02001663/**
1664 * @brief Parse a restriction that can have more instances such as must.
1665 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001666 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001667 * @param[in,out] data Data to read from, always moved to currently handled character.
1668 * @param[in] restr_kw Type of this particular restriction.
1669 * @param[in,out] restrs Restrictions to add to.
1670 *
1671 * @return LY_ERR values.
1672 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001673static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001674parse_restrs(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr **restrs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001675{
1676 struct lysp_restr *restr;
1677
Radek Krejci2c4e7172018-10-19 15:56:26 +02001678 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001679 return parse_restr(ctx, data, restr_kw, restr);
1680}
1681
Michal Vaskoea5abea2018-09-18 13:10:54 +02001682/**
1683 * @brief Parse the status statement.
1684 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001685 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001686 * @param[in,out] data Data to read from, always moved to currently handled character.
1687 * @param[in,out] flags Flags to add to.
1688 * @param[in,out] exts Extension instances to add to.
1689 *
1690 * @return LY_ERR values.
1691 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001692static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001693parse_status(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001694{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001695 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001696 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001697 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001698 enum yang_keyword kw;
1699
1700 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001701 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001702 return LY_EVALID;
1703 }
1704
1705 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001706 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001707
1708 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1709 *flags |= LYS_STATUS_CURR;
1710 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1711 *flags |= LYS_STATUS_DEPRC;
1712 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1713 *flags |= LYS_STATUS_OBSLT;
1714 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001715 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001716 free(buf);
1717 return LY_EVALID;
1718 }
1719 free(buf);
1720
Radek Krejci6d6556c2018-11-08 09:37:45 +01001721 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001722 switch (kw) {
1723 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001724 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001725 break;
1726 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001727 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001728 return LY_EVALID;
1729 }
1730 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001731 return ret;
1732}
1733
Michal Vaskoea5abea2018-09-18 13:10:54 +02001734/**
1735 * @brief Parse the when statement.
1736 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001737 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001738 * @param[in,out] data Data to read from, always moved to currently handled character.
1739 * @param[in,out] when_p When pointer to parse to.
1740 *
1741 * @return LY_ERR values.
1742 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001743static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001744parse_when(struct lys_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001745{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001746 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001747 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001748 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001749 enum yang_keyword kw;
1750 struct lysp_when *when;
1751
1752 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001753 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001754 return LY_EVALID;
1755 }
1756
1757 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001758 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001759 *when_p = when;
1760
1761 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001762 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001763 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001764
Radek Krejci6d6556c2018-11-08 09:37:45 +01001765 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001766 switch (kw) {
1767 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001768 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 +02001769 break;
1770 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001771 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001772 break;
1773 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001774 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001775 break;
1776 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001777 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001778 return LY_EVALID;
1779 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001780 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001781 return ret;
1782}
1783
Michal Vaskoea5abea2018-09-18 13:10:54 +02001784/**
1785 * @brief Parse the anydata or anyxml statement.
1786 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001787 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001788 * @param[in,out] data Data to read from, always moved to currently handled character.
1789 * @param[in] kw Type of this particular keyword.
1790 * @param[in,out] siblings Siblings to add to.
1791 *
1792 * @return LY_ERR values.
1793 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001794LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001795parse_any(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001796{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001797 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001798 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001799 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001800 struct lysp_node *iter;
1801 struct lysp_node_anydata *any;
1802
1803 /* create structure */
1804 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001805 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001806 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001807 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001808
1809 /* insert into siblings */
1810 if (!*siblings) {
1811 *siblings = (struct lysp_node *)any;
1812 } else {
1813 for (iter = *siblings; iter->next; iter = iter->next);
1814 iter->next = (struct lysp_node *)any;
1815 }
1816
1817 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001818 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001819 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001820
1821 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001822 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001823 switch (kw) {
1824 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001825 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001826 break;
1827 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001828 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 +02001829 break;
1830 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001831 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 +02001832 break;
1833 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001834 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001835 break;
1836 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001837 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001838 break;
1839 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001840 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 +02001841 break;
1842 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001843 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001844 break;
1845 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001846 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001847 break;
1848 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001849 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001850 break;
1851 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001852 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001853 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001854 return LY_EVALID;
1855 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001856 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001857 return ret;
1858}
1859
Michal Vaskoea5abea2018-09-18 13:10:54 +02001860/**
1861 * @brief Parse the value or position statement. Substatement of type enum statement.
1862 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001863 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001864 * @param[in,out] data Data to read from, always moved to currently handled character.
1865 * @param[in] val_kw Type of this particular keyword.
1866 * @param[in,out] value Value to write to.
1867 * @param[in,out] flags Flags to write to.
1868 * @param[in,out] exts Extension instances to add to.
1869 *
1870 * @return LY_ERR values.
1871 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001872static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001873parse_type_enum_value_pos(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword val_kw, int64_t *value, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001874 struct lysp_ext_instance **exts)
1875{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001876 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001877 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001878 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001879 long int num;
1880 unsigned long int unum;
1881 enum yang_keyword kw;
1882
1883 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001884 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001885 return LY_EVALID;
1886 }
1887 *flags |= LYS_SET_VALUE;
1888
1889 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001890 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001891
1892 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 +02001893 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001894 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001895 }
1896
1897 errno = 0;
1898 if (val_kw == YANG_VALUE) {
1899 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001900 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
1901 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1902 goto error;
1903 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001904 } else {
1905 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001906 if (unum > UINT64_C(4294967295)) {
1907 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1908 goto error;
1909 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001910 }
1911 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001912 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001913 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001914 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001915 }
1916 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001917 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001918 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001919 }
1920 if (val_kw == YANG_VALUE) {
1921 *value = num;
1922 } else {
1923 *value = unum;
1924 }
1925 free(buf);
1926
Radek Krejci6d6556c2018-11-08 09:37:45 +01001927 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001928 switch (kw) {
1929 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001930 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 +02001931 break;
1932 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001933 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001934 return LY_EVALID;
1935 }
1936 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001937 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001938
1939error:
1940 free(buf);
1941 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001942}
1943
Michal Vaskoea5abea2018-09-18 13:10:54 +02001944/**
1945 * @brief Parse the enum or bit statement. Substatement of type statement.
1946 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001947 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001948 * @param[in,out] data Data to read from, always moved to currently handled character.
1949 * @param[in] enum_kw Type of this particular keyword.
1950 * @param[in,out] enums Enums or bits to add to.
1951 *
1952 * @return LY_ERR values.
1953 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001954static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001955parse_type_enum(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword enum_kw, struct lysp_type_enum **enums)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001956{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001957 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001958 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001959 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001960 enum yang_keyword kw;
1961 struct lysp_type_enum *enm;
1962
Radek Krejci2c4e7172018-10-19 15:56:26 +02001963 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001964
1965 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001966 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 +01001967 if (enum_kw == YANG_ENUM) {
1968 if (!word_len) {
1969 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
1970 free(buf);
1971 return LY_EVALID;
1972 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
1973 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
1974 word_len, word);
1975 free(buf);
1976 return LY_EVALID;
1977 } else {
1978 for (u = 0; u < word_len; ++u) {
1979 if (iscntrl(word[u])) {
1980 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1981 word_len, word, u + 1);
1982 break;
1983 }
1984 }
1985 }
1986 } else { /* YANG_BIT */
1987
1988 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001989 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001990 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1991
Radek Krejci6d6556c2018-11-08 09:37:45 +01001992 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001993 switch (kw) {
1994 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001995 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 +02001996 break;
1997 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001998 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001999 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 +02002000 break;
2001 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002002 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 +02002003 break;
2004 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002005 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002006 break;
2007 case YANG_VALUE:
2008 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002009 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002010 break;
2011 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002012 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002013 break;
2014 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002015 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002016 return LY_EVALID;
2017 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002018 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002019 return ret;
2020}
2021
Michal Vaskoea5abea2018-09-18 13:10:54 +02002022/**
2023 * @brief Parse the fraction-digits statement. Substatement of type statement.
2024 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002025 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002026 * @param[in,out] data Data to read from, always moved to currently handled character.
2027 * @param[in,out] fracdig Value to write to.
2028 * @param[in,out] exts Extension instances to add to.
2029 *
2030 * @return LY_ERR values.
2031 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002032static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002033parse_type_fracdigits(struct lys_parser_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002034{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002035 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002036 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002037 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002038 unsigned long int num;
2039 enum yang_keyword kw;
2040
2041 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002042 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002043 return LY_EVALID;
2044 }
2045
2046 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002047 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002048
2049 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002050 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002051 free(buf);
2052 return LY_EVALID;
2053 }
2054
2055 errno = 0;
2056 num = strtoul(word, &ptr, 10);
2057 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002058 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002059 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002060 free(buf);
2061 return LY_EVALID;
2062 }
2063 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002064 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002065 free(buf);
2066 return LY_EVALID;
2067 }
2068 *fracdig = num;
2069 free(buf);
2070
Radek Krejci6d6556c2018-11-08 09:37:45 +01002071 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002072 switch (kw) {
2073 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002074 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075 break;
2076 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002077 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002078 return LY_EVALID;
2079 }
2080 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002081 return ret;
2082}
2083
Michal Vaskoea5abea2018-09-18 13:10:54 +02002084/**
2085 * @brief Parse the require-instance statement. Substatement of type statement.
2086 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002087 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002088 * @param[in,out] data Data to read from, always moved to currently handled character.
2089 * @param[in,out] reqinst Value to write to.
2090 * @param[in,out] flags Flags to write to.
2091 * @param[in,out] exts Extension instances to add to.
2092 *
2093 * @return LY_ERR values.
2094 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002095static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002096parse_type_reqinstance(struct lys_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002097 struct lysp_ext_instance **exts)
2098{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002099 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002100 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002101 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002102 enum yang_keyword kw;
2103
2104 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002105 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002106 return LY_EVALID;
2107 }
2108 *flags |= LYS_SET_REQINST;
2109
2110 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002111 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002112
2113 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2114 *reqinst = 1;
2115 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002116 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002117 free(buf);
2118 return LY_EVALID;
2119 }
2120 free(buf);
2121
Radek Krejci6d6556c2018-11-08 09:37:45 +01002122 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002123 switch (kw) {
2124 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002125 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002126 break;
2127 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002128 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002129 return LY_EVALID;
2130 }
2131 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002132 return ret;
2133}
2134
Michal Vaskoea5abea2018-09-18 13:10:54 +02002135/**
2136 * @brief Parse the modifier statement. Substatement of type pattern statement.
2137 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002138 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002139 * @param[in,out] data Data to read from, always moved to currently handled character.
2140 * @param[in,out] pat Value to write to.
2141 * @param[in,out] exts Extension instances to add to.
2142 *
2143 * @return LY_ERR values.
2144 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002145static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002146parse_type_pattern_modifier(struct lys_parser_ctx *ctx, const char **data, const char **pat, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002147{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002148 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002149 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002150 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002151 enum yang_keyword kw;
2152
2153 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002154 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002155 return LY_EVALID;
2156 }
2157
2158 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002159 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002160
2161 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002162 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002163 free(buf);
2164 return LY_EVALID;
2165 }
2166 free(buf);
2167
2168 /* replace the value in the dictionary */
2169 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002170 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002171 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002172 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002173
2174 assert(buf[0] == 0x06);
2175 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002176 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002177
Radek Krejci6d6556c2018-11-08 09:37:45 +01002178 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002179 switch (kw) {
2180 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002181 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002182 break;
2183 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002184 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002185 return LY_EVALID;
2186 }
2187 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002188 return ret;
2189}
2190
Michal Vaskoea5abea2018-09-18 13:10:54 +02002191/**
2192 * @brief Parse the pattern statement. Substatement of type statement.
2193 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002194 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002195 * @param[in,out] data Data to read from, always moved to currently handled character.
2196 * @param[in,out] patterns Restrictions to add to.
2197 *
2198 * @return LY_ERR values.
2199 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002200static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002201parse_type_pattern(struct lys_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002202{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002203 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002204 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002205 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002206 enum yang_keyword kw;
2207 struct lysp_restr *restr;
2208
Radek Krejci2c4e7172018-10-19 15:56:26 +02002209 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002210
2211 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002212 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002213
2214 /* add special meaning first byte */
2215 if (buf) {
2216 buf = realloc(buf, word_len + 2);
2217 word = buf;
2218 } else {
2219 buf = malloc(word_len + 2);
2220 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002221 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002222 memmove(buf + 1, word, word_len);
2223 buf[0] = 0x06; /* pattern's default regular-match flag */
2224 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2225 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002226
Radek Krejci6d6556c2018-11-08 09:37:45 +01002227 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002228 switch (kw) {
2229 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002230 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 +02002231 break;
2232 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002233 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 +02002234 break;
2235 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002236 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 +02002237 break;
2238 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002239 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 +02002240 break;
2241 case YANG_MODIFIER:
Radek Krejciceaf2122019-01-02 15:03:26 +01002242 YANG_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002243 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002244 break;
2245 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002246 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002247 break;
2248 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002249 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002250 return LY_EVALID;
2251 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002252 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002253 return ret;
2254}
2255
Michal Vaskoea5abea2018-09-18 13:10:54 +02002256/**
2257 * @brief Parse the type statement.
2258 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002259 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002260 * @param[in,out] data Data to read from, always moved to currently handled character.
2261 * @param[in,out] type Type to wrote to.
2262 *
2263 * @return LY_ERR values.
2264 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002266parse_type(struct lys_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002267{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002268 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002269 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002270 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002271 enum yang_keyword kw;
2272 struct lysp_type *nest_type;
2273
2274 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002275 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002276 return LY_EVALID;
2277 }
2278
2279 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002280 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002281 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002282
Radek Krejci6d6556c2018-11-08 09:37:45 +01002283 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002284 switch (kw) {
2285 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002286 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 +01002287 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002288 break;
2289 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002290 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002291 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002292 break;
2293 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002294 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002295 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002296 break;
2297 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002298 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002299 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002300 break;
2301 case YANG_LENGTH:
2302 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002303 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002304 return LY_EVALID;
2305 }
2306 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002307 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002308
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002309 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002310 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002311 break;
2312 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002313 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 +01002314 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002315 break;
2316 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002317 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002318 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002319 break;
2320 case YANG_RANGE:
2321 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002322 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002323 return LY_EVALID;
2324 }
2325 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002326 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002327
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002328 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002329 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002330 break;
2331 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002332 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002333 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002334 break;
2335 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002336 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2337 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002338 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002339 break;
2340 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002341 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002342 break;
2343 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002344 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002345 return LY_EVALID;
2346 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002347 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002348 return ret;
2349}
2350
Michal Vaskoea5abea2018-09-18 13:10:54 +02002351/**
2352 * @brief Parse the leaf statement.
2353 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002354 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002355 * @param[in,out] data Data to read from, always moved to currently handled character.
2356 * @param[in,out] siblings Siblings to add to.
2357 *
2358 * @return LY_ERR values.
2359 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002360LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002361parse_leaf(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002362{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002363 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002364 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002365 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002366 enum yang_keyword kw;
2367 struct lysp_node *iter;
2368 struct lysp_node_leaf *leaf;
2369
2370 /* create structure */
2371 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002372 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002373 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002374 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002375
2376 /* insert into siblings */
2377 if (!*siblings) {
2378 *siblings = (struct lysp_node *)leaf;
2379 } else {
2380 for (iter = *siblings; iter->next; iter = iter->next);
2381 iter->next = (struct lysp_node *)leaf;
2382 }
2383
2384 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002385 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002386 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002387
2388 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002389 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002390 switch (kw) {
2391 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002392 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002393 break;
2394 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002395 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 +02002396 break;
2397 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002398 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 +02002399 break;
2400 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002401 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 +02002402 break;
2403 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002404 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002405 break;
2406 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002407 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002408 break;
2409 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002410 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 +02002411 break;
2412 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002413 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002414 break;
2415 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002416 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002417 break;
2418 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002419 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 +02002420 break;
2421 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002422 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002423 break;
2424 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002425 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002426 break;
2427 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002428 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002429 return LY_EVALID;
2430 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002431 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002432 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002433checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002434 /* mandatory substatements */
2435 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002436 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002437 return LY_EVALID;
2438 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002439 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
2440 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
2441 return LY_EVALID;
2442 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002443
2444 return ret;
2445}
2446
Michal Vaskoea5abea2018-09-18 13:10:54 +02002447/**
2448 * @brief Parse the max-elements statement.
2449 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002450 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002451 * @param[in,out] data Data to read from, always moved to currently handled character.
2452 * @param[in,out] max Value to write to.
2453 * @param[in,out] flags Flags to write to.
2454 * @param[in,out] exts Extension instances to add to.
2455 *
2456 * @return LY_ERR values.
2457 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002458LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002459parse_maxelements(struct lys_parser_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002460{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002461 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002462 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002463 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002464 unsigned long int num;
2465 enum yang_keyword kw;
2466
2467 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002468 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002469 return LY_EVALID;
2470 }
2471 *flags |= LYS_SET_MAX;
2472
2473 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002474 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002475
2476 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002477 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002478 free(buf);
2479 return LY_EVALID;
2480 }
2481
2482 if (strncmp(word, "unbounded", word_len)) {
2483 errno = 0;
2484 num = strtoul(word, &ptr, 10);
2485 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002486 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002487 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002488 free(buf);
2489 return LY_EVALID;
2490 }
2491 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002492 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002493 free(buf);
2494 return LY_EVALID;
2495 }
2496
2497 *max = num;
2498 }
2499 free(buf);
2500
Radek Krejci6d6556c2018-11-08 09:37:45 +01002501 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002502 switch (kw) {
2503 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002504 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002505 break;
2506 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002507 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002508 return LY_EVALID;
2509 }
2510 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002511 return ret;
2512}
2513
Michal Vaskoea5abea2018-09-18 13:10:54 +02002514/**
2515 * @brief Parse the min-elements statement.
2516 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002517 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002518 * @param[in,out] data Data to read from, always moved to currently handled character.
2519 * @param[in,out] min Value to write to.
2520 * @param[in,out] flags Flags to write to.
2521 * @param[in,out] exts Extension instances to add to.
2522 *
2523 * @return LY_ERR values.
2524 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002525LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002526parse_minelements(struct lys_parser_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002527{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002528 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002529 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002530 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002531 unsigned long int num;
2532 enum yang_keyword kw;
2533
2534 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002535 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002536 return LY_EVALID;
2537 }
2538 *flags |= LYS_SET_MIN;
2539
2540 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002541 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002542
2543 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002544 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002545 free(buf);
2546 return LY_EVALID;
2547 }
2548
2549 errno = 0;
2550 num = strtoul(word, &ptr, 10);
2551 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002552 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002553 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002554 free(buf);
2555 return LY_EVALID;
2556 }
2557 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002558 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002559 free(buf);
2560 return LY_EVALID;
2561 }
2562 *min = num;
2563 free(buf);
2564
Radek Krejci6d6556c2018-11-08 09:37:45 +01002565 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002566 switch (kw) {
2567 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002568 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002569 break;
2570 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002571 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002572 return LY_EVALID;
2573 }
2574 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002575 return ret;
2576}
2577
Michal Vaskoea5abea2018-09-18 13:10:54 +02002578/**
2579 * @brief Parse the ordered-by statement.
2580 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002581 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002582 * @param[in,out] data Data to read from, always moved to currently handled character.
2583 * @param[in,out] flags Flags to write to.
2584 * @param[in,out] exts Extension instances to add to.
2585 *
2586 * @return LY_ERR values.
2587 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002588static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002589parse_orderedby(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002590{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002591 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002592 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002593 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002594 enum yang_keyword kw;
2595
2596 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002597 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002598 return LY_EVALID;
2599 }
2600
2601 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002602 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002603
2604 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2605 *flags |= LYS_ORDBY_SYSTEM;
2606 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2607 *flags |= LYS_ORDBY_USER;
2608 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002609 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002610 free(buf);
2611 return LY_EVALID;
2612 }
2613 free(buf);
2614
Radek Krejci6d6556c2018-11-08 09:37:45 +01002615 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002616 switch (kw) {
2617 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002618 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619 break;
2620 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002621 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002622 return LY_EVALID;
2623 }
2624 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002625 return ret;
2626}
2627
Michal Vaskoea5abea2018-09-18 13:10:54 +02002628/**
2629 * @brief Parse the leaf-list statement.
2630 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002631 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002632 * @param[in,out] data Data to read from, always moved to currently handled character.
2633 * @param[in,out] siblings Siblings to add to.
2634 *
2635 * @return LY_ERR values.
2636 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002637LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002638parse_leaflist(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002639{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002640 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002641 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002642 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002643 enum yang_keyword kw;
2644 struct lysp_node *iter;
2645 struct lysp_node_leaflist *llist;
2646
2647 /* create structure */
2648 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002649 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002650 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002651 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002652
2653 /* insert into siblings */
2654 if (!*siblings) {
2655 *siblings = (struct lysp_node *)llist;
2656 } else {
2657 for (iter = *siblings; iter->next; iter = iter->next);
2658 iter->next = (struct lysp_node *)llist;
2659 }
2660
2661 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002662 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002663 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002664
2665 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002666 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002667 switch (kw) {
2668 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002669 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002670 break;
2671 case YANG_DEFAULT:
Radek Krejciceaf2122019-01-02 15:03:26 +01002672 YANG_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002673 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 +02002674 break;
2675 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002676 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 +02002677 break;
2678 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002679 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 +02002680 break;
2681 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002682 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002683 break;
2684 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002685 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002686 break;
2687 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002688 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002689 break;
2690 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002691 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002692 break;
2693 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002694 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 +02002695 break;
2696 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002697 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002698 break;
2699 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002700 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002701 break;
2702 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002703 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 +02002704 break;
2705 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002706 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002707 break;
2708 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002709 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002710 break;
2711 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002712 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002713 return LY_EVALID;
2714 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002715 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002716 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002717checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002718 /* mandatory substatements */
2719 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002720 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002721 return LY_EVALID;
2722 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002723 if ((llist->min) && (llist->dflts)) {
2724 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
2725 return LY_EVALID;
2726 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002727 if (llist->max && llist->min > llist->max) {
2728 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
2729 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2730 llist->min, llist->max);
2731 return LY_EVALID;
2732 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002733
2734 return ret;
2735}
2736
Michal Vaskoea5abea2018-09-18 13:10:54 +02002737/**
2738 * @brief Parse the refine statement.
2739 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002740 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002741 * @param[in,out] data Data to read from, always moved to currently handled character.
2742 * @param[in,out] refines Refines to add to.
2743 *
2744 * @return LY_ERR values.
2745 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002746static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002747parse_refine(struct lys_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002748{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002749 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002750 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002751 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002752 enum yang_keyword kw;
2753 struct lysp_refine *rf;
2754
Radek Krejci2c4e7172018-10-19 15:56:26 +02002755 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002756
2757 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002758 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002759 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002760
Radek Krejci6d6556c2018-11-08 09:37:45 +01002761 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002762 switch (kw) {
2763 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002764 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765 break;
2766 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002767 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 +02002768 break;
2769 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002770 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 +02002771 break;
2772 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01002773 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002774 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 +02002775 break;
2776 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002777 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002778 break;
2779 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002780 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002781 break;
2782 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002783 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002784 break;
2785 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002786 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002787 break;
2788 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002789 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 +02002790 break;
2791 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002792 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 +02002793 break;
2794 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002795 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 break;
2797 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002798 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002799 return LY_EVALID;
2800 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002801 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002802 return ret;
2803}
2804
Michal Vaskoea5abea2018-09-18 13:10:54 +02002805/**
2806 * @brief Parse the typedef statement.
2807 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002808 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002809 * @param[in,out] data Data to read from, always moved to currently handled character.
2810 * @param[in,out] typedefs Typedefs to add to.
2811 *
2812 * @return LY_ERR values.
2813 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002814static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002815parse_typedef(struct lys_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002816{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002817 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002818 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002819 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002820 enum yang_keyword kw;
2821 struct lysp_tpdf *tpdf;
2822
Radek Krejci2c4e7172018-10-19 15:56:26 +02002823 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002824
2825 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002826 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002827 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002828
2829 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002830 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002831 switch (kw) {
2832 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002833 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 +02002834 break;
2835 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002836 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 +02002837 break;
2838 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002839 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 +02002840 break;
2841 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002842 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002843 break;
2844 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002845 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846 break;
2847 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002848 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 +02002849 break;
2850 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002851 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002852 break;
2853 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002854 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002855 return LY_EVALID;
2856 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002858 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002859checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 /* mandatory substatements */
2861 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002862 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863 return LY_EVALID;
2864 }
2865
Radek Krejcibbe09a92018-11-08 09:36:54 +01002866 /* store data for collision check */
Radek Krejci7fc68292019-06-12 13:51:09 +02002867 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01002868 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2869 }
2870
Michal Vasko7fbc8162018-09-17 10:35:16 +02002871 return ret;
2872}
2873
Michal Vaskoea5abea2018-09-18 13:10:54 +02002874/**
2875 * @brief Parse the input or output statement.
2876 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002877 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002878 * @param[in,out] data Data to read from, always moved to currently handled character.
2879 * @param[in] kw Type of this particular keyword
2880 * @param[in,out] inout_p Input/output pointer to write to.
2881 *
2882 * @return LY_ERR values.
2883 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002884static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002885parse_inout(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword inout_kw, struct lysp_node *parent, struct lysp_action_inout *inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002886{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002887 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002888 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002889 size_t word_len;
Radek Krejci10113652018-11-14 16:56:50 +01002890 enum yang_keyword kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002892 if (inout_p->nodetype) {
Radek Krejci10113652018-11-14 16:56:50 +01002893 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002894 return LY_EVALID;
2895 }
2896
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002897 /* initiate structure */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002898 inout_p->nodetype = &((struct lysp_action*)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002899 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002900
2901 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02002902 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002903 switch (kw) {
2904 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002905 YANG_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002906 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002907 case YANG_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002908 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002909 break;
2910 case YANG_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002911 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002912 break;
2913 case YANG_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002914 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002915 break;
2916 case YANG_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002917 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918 break;
2919 case YANG_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002920 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002921 break;
2922 case YANG_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002923 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002924 break;
2925 case YANG_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002926 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002927 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002928 case YANG_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002929 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002930 break;
2931 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002932 YANG_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002933 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002934 break;
2935 case YANG_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002936 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002937 break;
2938 case YANG_CUSTOM:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002939 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002940 break;
2941 default:
Radek Krejci10113652018-11-14 16:56:50 +01002942 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002943 return LY_EVALID;
2944 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002945 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002946 LY_CHECK_RET(ret);
2947checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002948 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02002949 LY_CHECK_RET(parse_finalize_reallocated(ctx, inout_p->groupings, NULL, NULL, NULL));
2950
Michal Vasko7fbc8162018-09-17 10:35:16 +02002951 return ret;
2952}
2953
Michal Vaskoea5abea2018-09-18 13:10:54 +02002954/**
2955 * @brief Parse the action statement.
2956 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002957 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002958 * @param[in,out] data Data to read from, always moved to currently handled character.
2959 * @param[in,out] actions Actions to add to.
2960 *
2961 * @return LY_ERR values.
2962 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002963LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002964parse_action(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002965{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002966 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002967 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002968 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002969 enum yang_keyword kw;
2970 struct lysp_action *act;
2971
Radek Krejci2c4e7172018-10-19 15:56:26 +02002972 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002973
2974 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002975 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002976 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002977 act->nodetype = LYS_ACTION;
2978 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002979
Radek Krejci7fc68292019-06-12 13:51:09 +02002980 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002981 switch (kw) {
2982 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002983 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 +02002984 break;
2985 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002986 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 +02002987 break;
2988 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002989 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 +02002990 break;
2991 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002992 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002993 break;
2994
2995 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002996 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002997 break;
2998 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002999 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003000 break;
3001
3002 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003003 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003004 break;
3005 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003006 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003007 break;
3008 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003009 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003010 break;
3011 default:
Radek Krejcif538ce52019-03-05 10:46:14 +01003012 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003013 return LY_EVALID;
3014 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003015 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003016 LY_CHECK_RET(ret);
3017checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003018 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02003019 LY_CHECK_RET(parse_finalize_reallocated(ctx, act->groupings, NULL, NULL, NULL));
3020
Michal Vasko7fbc8162018-09-17 10:35:16 +02003021 return ret;
3022}
3023
Michal Vaskoea5abea2018-09-18 13:10:54 +02003024/**
3025 * @brief Parse the notification statement.
3026 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003027 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003028 * @param[in,out] data Data to read from, always moved to currently handled character.
3029 * @param[in,out] notifs Notifications to add to.
3030 *
3031 * @return LY_ERR values.
3032 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003033LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003034parse_notif(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003035{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003036 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003037 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003038 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003039 enum yang_keyword kw;
3040 struct lysp_notif *notif;
3041
Radek Krejci2c4e7172018-10-19 15:56:26 +02003042 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003043
3044 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003045 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003046 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003047 notif->nodetype = LYS_NOTIF;
3048 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003049
Radek Krejci7fc68292019-06-12 13:51:09 +02003050 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003051 switch (kw) {
3052 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003053 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 +02003054 break;
3055 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003056 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 +02003057 break;
3058 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003059 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 +02003060 break;
3061 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003062 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003063 break;
3064
3065 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003066 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01003067 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003068 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003069 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003070 break;
3071 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003072 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003073 break;
3074 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003075 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076 break;
3077 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003078 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079 break;
3080 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003081 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003082 break;
3083 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003084 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003085 break;
3086 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003087 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003088 break;
3089
3090 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01003091 YANG_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003092 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003093 break;
3094 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003095 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003096 break;
3097 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003098 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003099 break;
3100 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003101 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003102 break;
3103 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003104 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003105 return LY_EVALID;
3106 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003107 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003108 LY_CHECK_RET(ret);
3109checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003110 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02003111 LY_CHECK_RET(parse_finalize_reallocated(ctx, notif->groupings, NULL, NULL, NULL));
3112
Michal Vasko7fbc8162018-09-17 10:35:16 +02003113 return ret;
3114}
3115
Michal Vaskoea5abea2018-09-18 13:10:54 +02003116/**
3117 * @brief Parse the grouping statement.
3118 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003119 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003120 * @param[in,out] data Data to read from, always moved to currently handled character.
3121 * @param[in,out] groupings Groupings to add to.
3122 *
3123 * @return LY_ERR values.
3124 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003125LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003126parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003127{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003128 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003129 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003130 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003131 enum yang_keyword kw;
3132 struct lysp_grp *grp;
3133
Radek Krejci2c4e7172018-10-19 15:56:26 +02003134 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135
3136 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003137 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003138 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003139 grp->nodetype = LYS_GROUPING;
3140 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003141
Radek Krejci7fc68292019-06-12 13:51:09 +02003142 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003143 switch (kw) {
3144 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003145 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 +02003146 break;
3147 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003148 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 +02003149 break;
3150 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003151 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003152 break;
3153
3154 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003155 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01003156 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003157 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003158 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003159 break;
3160 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003161 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003162 break;
3163 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003164 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003165 break;
3166 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003167 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003168 break;
3169 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003170 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003171 break;
3172 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003174 break;
3175 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003176 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003177 break;
3178
3179 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003180 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003181 break;
3182 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003183 YANG_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003184 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003185 break;
3186 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003187 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003188 break;
3189 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003190 YANG_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003191 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003192 break;
3193 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003194 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003195 break;
3196 default:
Radek Krejci10113652018-11-14 16:56:50 +01003197 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003198 return LY_EVALID;
3199 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003200 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003201 LY_CHECK_RET(ret);
3202checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003203 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02003204 LY_CHECK_RET(parse_finalize_reallocated(ctx, grp->groupings, NULL, grp->actions, grp->notifs));
3205
Michal Vasko7fbc8162018-09-17 10:35:16 +02003206 return ret;
3207}
3208
Michal Vaskoea5abea2018-09-18 13:10:54 +02003209/**
3210 * @brief Parse the refine statement.
3211 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003212 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003213 * @param[in,out] data Data to read from, always moved to currently handled character.
3214 * @param[in,out] augments Augments to add to.
3215 *
3216 * @return LY_ERR values.
3217 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003218LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003219parse_augment(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003220{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003221 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003222 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003223 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224 enum yang_keyword kw;
3225 struct lysp_augment *aug;
3226
Radek Krejci2c4e7172018-10-19 15:56:26 +02003227 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003228
3229 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003230 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003231 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003232 aug->nodetype = LYS_AUGMENT;
3233 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003234
Radek Krejci7fc68292019-06-12 13:51:09 +02003235 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003236 switch (kw) {
3237 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003238 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 +02003239 break;
3240 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003241 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 +02003242 break;
3243 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003244 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 +02003245 break;
3246 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003247 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003248 break;
3249 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003250 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003251 break;
3252
3253 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003254 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01003255 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003256 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003257 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003258 break;
3259 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003260 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003261 break;
3262 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003263 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003264 break;
3265 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003266 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003267 break;
3268 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003269 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003270 break;
3271 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003272 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003273 break;
3274 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003275 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003276 break;
3277 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003278 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003279 break;
3280
3281 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003282 YANG_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003283 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003284 break;
3285 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003286 YANG_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003287 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003288 break;
3289 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003290 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003291 break;
3292 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003293 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003294 return LY_EVALID;
3295 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003296 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003297 LY_CHECK_RET(ret);
3298checks:
3299 /* finalize parent pointers to the reallocated items */
3300 LY_CHECK_RET(parse_finalize_reallocated(ctx, NULL, NULL, aug->actions, aug->notifs));
3301
Michal Vasko7fbc8162018-09-17 10:35:16 +02003302 return ret;
3303}
3304
Michal Vaskoea5abea2018-09-18 13:10:54 +02003305/**
Radek Krejci7fc68292019-06-12 13:51:09 +02003306 * @brief Finalize some of the structures in case they are stored in sized array,
3307 * which can be possibly reallocated and some other data may point to them.
3308 *
3309 * Update parent pointers in the nodes inside grouping/augment/RPC/Notification, which could be reallocated.
3310 *
3311 * @param[in] mod Parsed module to be updated.
3312 * @return LY_ERR value (currently only LY_SUCCESS, but it can change in future).
3313 */
3314static LY_ERR
3315parse_finalize_reallocated(struct lys_parser_ctx *ctx, struct lysp_grp *groupings, struct lysp_augment *augments,
3316 struct lysp_action *actions, struct lysp_notif *notifs)
3317{
3318 unsigned int u, v;
3319 struct lysp_node *child;
3320
3321 /* finalize parent pointers to the reallocated items */
3322
3323 /* gropings */
3324 LY_ARRAY_FOR(groupings, u) {
3325 LY_LIST_FOR(groupings[u].data, child) {
3326 child->parent = (struct lysp_node*)&groupings[u];
3327 }
3328 LY_ARRAY_FOR(groupings[u].actions, v) {
3329 groupings[u].actions[v].parent = (struct lysp_node*)&groupings[u];
3330 }
3331 LY_ARRAY_FOR(groupings[u].notifs, v) {
3332 groupings[u].notifs[v].parent = (struct lysp_node*)&groupings[u];
3333 }
3334 LY_ARRAY_FOR(groupings[u].groupings, v) {
3335 groupings[u].groupings[v].parent = (struct lysp_node*)&groupings[u];
3336 }
3337 if (groupings[u].typedefs) {
3338 ly_set_add(&ctx->tpdfs_nodes, &groupings[u], 0);
3339 }
3340 }
3341
3342 /* augments */
3343 LY_ARRAY_FOR(augments, u) {
3344 LY_LIST_FOR(augments[u].child, child) {
3345 child->parent = (struct lysp_node*)&augments[u];
3346 }
3347 LY_ARRAY_FOR(augments[u].actions, v) {
3348 augments[u].actions[v].parent = (struct lysp_node*)&augments[u];
3349 }
3350 LY_ARRAY_FOR(augments[u].notifs, v) {
3351 augments[u].notifs[v].parent = (struct lysp_node*)&augments[u];
3352 }
3353 }
3354
3355 /* actions */
3356 LY_ARRAY_FOR(actions, u) {
3357 if (actions[u].input.parent) {
3358 actions[u].input.parent = (struct lysp_node*)&actions[u];
3359 LY_LIST_FOR(actions[u].input.data, child) {
3360 child->parent = (struct lysp_node*)&actions[u].input;
3361 }
3362 LY_ARRAY_FOR(actions[u].input.groupings, v) {
3363 actions[u].input.groupings[v].parent = (struct lysp_node*)&actions[u].input;
3364 }
3365 if (actions[u].input.typedefs) {
3366 ly_set_add(&ctx->tpdfs_nodes, &actions[u].input, 0);
3367 }
3368 }
3369 if (actions[u].output.parent) {
3370 actions[u].output.parent = (struct lysp_node*)&actions[u];
3371 LY_LIST_FOR(actions[u].output.data, child) {
3372 child->parent = (struct lysp_node*)&actions[u].output;
3373 }
3374 LY_ARRAY_FOR(actions[u].output.groupings, v) {
3375 actions[u].output.groupings[v].parent = (struct lysp_node*)&actions[u].output;
3376 }
3377 if (actions[u].output.typedefs) {
3378 ly_set_add(&ctx->tpdfs_nodes, &actions[u].output, 0);
3379 }
3380 }
3381 LY_ARRAY_FOR(actions[u].groupings, v) {
3382 actions[u].groupings[v].parent = (struct lysp_node*)&actions[u];
3383 }
3384 if (actions[u].typedefs) {
3385 ly_set_add(&ctx->tpdfs_nodes, &actions[u], 0);
3386 }
3387 }
3388
3389 /* notifications */
3390 LY_ARRAY_FOR(notifs, u) {
3391 LY_LIST_FOR(notifs[u].data, child) {
3392 child->parent = (struct lysp_node*)&notifs[u];
3393 }
3394 LY_ARRAY_FOR(notifs[u].groupings, v) {
3395 notifs[u].groupings[v].parent = (struct lysp_node*)&notifs[u];
3396 }
3397 if (notifs[u].typedefs) {
3398 ly_set_add(&ctx->tpdfs_nodes, &notifs[u], 0);
3399 }
3400 }
3401
3402 return LY_SUCCESS;
3403}
3404
3405/**
Michal Vaskoea5abea2018-09-18 13:10:54 +02003406 * @brief Parse the uses statement.
3407 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003408 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003409 * @param[in,out] data Data to read from, always moved to currently handled character.
3410 * @param[in,out] siblings Siblings to add to.
3411 *
3412 * @return LY_ERR values.
3413 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003414LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003415parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003416{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003417 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003418 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003419 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003420 enum yang_keyword kw;
3421 struct lysp_node *iter;
3422 struct lysp_node_uses *uses;
3423
3424 /* create structure */
3425 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003426 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003427 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003428 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003429
3430 /* insert into siblings */
3431 if (!*siblings) {
3432 *siblings = (struct lysp_node *)uses;
3433 } else {
3434 for (iter = *siblings; iter->next; iter = iter->next);
3435 iter->next = (struct lysp_node *)uses;
3436 }
3437
3438 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003439 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003440 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003441
3442 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003443 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003444 switch (kw) {
3445 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003446 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 +02003447 break;
3448 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003449 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 +02003450 break;
3451 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003452 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 +02003453 break;
3454 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003455 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003456 break;
3457 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003458 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003459 break;
3460
3461 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003462 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003463 break;
3464 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003465 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003466 break;
3467 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003468 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003469 break;
3470 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003471 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003472 return LY_EVALID;
3473 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003474 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003475checks:
3476 /* finalize parent pointers to the reallocated items */
3477 LY_CHECK_RET(parse_finalize_reallocated(ctx, NULL, uses->augments, NULL, NULL));
3478
Michal Vasko7fbc8162018-09-17 10:35:16 +02003479 return ret;
3480}
3481
Michal Vaskoea5abea2018-09-18 13:10:54 +02003482/**
3483 * @brief Parse the case statement.
3484 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003485 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003486 * @param[in,out] data Data to read from, always moved to currently handled character.
3487 * @param[in,out] siblings Siblings to add to.
3488 *
3489 * @return LY_ERR values.
3490 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003491LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003492parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003493{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003494 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003495 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003496 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003497 enum yang_keyword kw;
3498 struct lysp_node *iter;
3499 struct lysp_node_case *cas;
3500
3501 /* create structure */
3502 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003503 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003504 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003505 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003506
3507 /* insert into siblings */
3508 if (!*siblings) {
3509 *siblings = (struct lysp_node *)cas;
3510 } else {
3511 for (iter = *siblings; iter->next; iter = iter->next);
3512 iter->next = (struct lysp_node *)cas;
3513 }
3514
3515 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003516 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003517 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003518
3519 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003520 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003521 switch (kw) {
3522 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003523 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 +02003524 break;
3525 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003526 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 +02003527 break;
3528 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003529 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 +02003530 break;
3531 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003532 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003533 break;
3534 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003535 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536 break;
3537
3538 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003539 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003540 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003541 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003542 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 break;
3544 case YANG_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003545 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003546 break;
3547 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003548 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003549 break;
3550 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003551 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003552 break;
3553 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003554 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003555 break;
3556 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003557 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 break;
3559 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003560 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561 break;
3562 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003563 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003564 break;
3565 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003566 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567 return LY_EVALID;
3568 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003570 return ret;
3571}
3572
Michal Vaskoea5abea2018-09-18 13:10:54 +02003573/**
3574 * @brief Parse the choice statement.
3575 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003576 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003577 * @param[in,out] data Data to read from, always moved to currently handled character.
3578 * @param[in,out] siblings Siblings to add to.
3579 *
3580 * @return LY_ERR values.
3581 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003582LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003583parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003585 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003586 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003587 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003588 enum yang_keyword kw;
3589 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003590 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003591
3592 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003593 choice = calloc(1, sizeof *choice);
3594 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3595 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003596 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003597
3598 /* insert into siblings */
3599 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003600 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003601 } else {
3602 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003603 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604 }
3605
3606 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003607 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003608 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003609
3610 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003611 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003612 switch (kw) {
3613 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003614 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003615 break;
3616 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003617 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 +02003618 break;
3619 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003620 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 +02003621 break;
3622 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003623 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003624 break;
3625 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003626 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 +02003627 break;
3628 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003629 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003630 break;
3631 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003632 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003633 break;
3634 case YANG_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003635 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 +02003636 break;
3637
3638 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003639 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003640 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003641 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003642 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643 break;
3644 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003645 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003646 break;
3647 case YANG_CHOICE:
Radek Krejciceaf2122019-01-02 15:03:26 +01003648 YANG_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003649 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003650 break;
3651 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003652 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003653 break;
3654 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003655 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003656 break;
3657 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003658 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003659 break;
3660 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003661 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003662 break;
3663 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003664 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003665 break;
3666 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003667 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003668 return LY_EVALID;
3669 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003670 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003671 LY_CHECK_RET(ret);
3672checks:
3673 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
3674 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
3675 return LY_EVALID;
3676 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003677 return ret;
3678}
3679
Michal Vaskoea5abea2018-09-18 13:10:54 +02003680/**
3681 * @brief Parse the container statement.
3682 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003683 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003684 * @param[in,out] data Data to read from, always moved to currently handled character.
3685 * @param[in,out] siblings Siblings to add to.
3686 *
3687 * @return LY_ERR values.
3688 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003689LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003690parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003691{
3692 LY_ERR ret = 0;
3693 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003694 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003695 enum yang_keyword kw;
3696 struct lysp_node *iter;
3697 struct lysp_node_container *cont;
3698
3699 /* create structure */
3700 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003701 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003702 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003703 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003704
3705 /* insert into siblings */
3706 if (!*siblings) {
3707 *siblings = (struct lysp_node *)cont;
3708 } else {
3709 for (iter = *siblings; iter->next; iter = iter->next);
3710 iter->next = (struct lysp_node *)cont;
3711 }
3712
3713 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003714 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003715 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003716
3717 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003718 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003719 switch (kw) {
3720 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003721 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003722 break;
3723 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003724 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 +02003725 break;
3726 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003727 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 +02003728 break;
3729 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003730 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 +02003731 break;
3732 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003733 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003734 break;
3735 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003736 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003737 break;
3738 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003739 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 +02003740 break;
3741
3742 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003743 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003744 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003745 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003746 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003747 break;
3748 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003749 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003750 break;
3751 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003752 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003753 break;
3754 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003755 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003756 break;
3757 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003758 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003759 break;
3760 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003761 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003762 break;
3763 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003764 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003765 break;
3766
3767 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003768 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003769 break;
3770 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003771 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003772 break;
3773 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003774 YANG_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003775 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003776 break;
3777 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003778 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003779 break;
3780 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003781 YANG_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003782 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003783 break;
3784 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003785 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003786 break;
3787 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003788 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003789 return LY_EVALID;
3790 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003791 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003792checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003793 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02003794 LY_CHECK_RET(parse_finalize_reallocated(ctx, cont->groupings, NULL, cont->actions, cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003795 return ret;
3796}
3797
Michal Vaskoea5abea2018-09-18 13:10:54 +02003798/**
3799 * @brief Parse the list statement.
3800 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003801 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003802 * @param[in,out] data Data to read from, always moved to currently handled character.
3803 * @param[in,out] siblings Siblings to add to.
3804 *
3805 * @return LY_ERR values.
3806 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003807LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003808parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003809{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003810 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003811 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003812 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003813 enum yang_keyword kw;
3814 struct lysp_node *iter;
3815 struct lysp_node_list *list;
3816
3817 /* create structure */
3818 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003819 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003820 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003821 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003822
3823 /* insert into siblings */
3824 if (!*siblings) {
3825 *siblings = (struct lysp_node *)list;
3826 } else {
3827 for (iter = *siblings; iter->next; iter = iter->next);
3828 iter->next = (struct lysp_node *)list;
3829 }
3830
3831 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003832 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003833 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003834
3835 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003836 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003837 switch (kw) {
3838 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003839 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003840 break;
3841 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003842 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 +02003843 break;
3844 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003845 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 +02003846 break;
3847 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003848 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 +02003849 break;
3850 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003851 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003852 break;
3853 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003854 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003855 break;
3856 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003857 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 +02003858 break;
3859 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003860 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003861 break;
3862 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003863 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003864 break;
3865 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003866 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003867 break;
3868 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003869 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 +02003870 break;
3871
3872 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003873 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003874 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003876 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003877 break;
3878 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003879 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003880 break;
3881 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003882 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003883 break;
3884 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003885 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003886 break;
3887 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003888 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003889 break;
3890 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003891 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003892 break;
3893 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003894 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003895 break;
3896
3897 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003898 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003899 break;
3900 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003901 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003902 break;
3903 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003904 YANG_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003905 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003906 break;
3907 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003908 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003909 break;
3910 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003911 YANG_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003912 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
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_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003916 break;
3917 default:
Radek Krejci10113652018-11-14 16:56:50 +01003918 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003919 return LY_EVALID;
3920 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003921 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003922 LY_CHECK_RET(ret);
3923checks:
Radek Krejci7fc68292019-06-12 13:51:09 +02003924 /* finalize parent pointers to the reallocated items */
3925 LY_CHECK_RET(parse_finalize_reallocated(ctx, list->groupings, NULL, list->actions, list->notifs));
3926
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003927 if (list->max && list->min > list->max) {
3928 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
3929 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3930 list->min, list->max);
3931 return LY_EVALID;
3932 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003933
3934 return ret;
3935}
3936
Michal Vaskoea5abea2018-09-18 13:10:54 +02003937/**
3938 * @brief Parse the yin-element statement.
3939 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003940 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003941 * @param[in,out] data Data to read from, always moved to currently handled character.
3942 * @param[in,out] flags Flags to write to.
3943 * @param[in,out] exts Extension instances to add to.
3944 *
3945 * @return LY_ERR values.
3946 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003947static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003948parse_yinelement(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003949{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003950 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003951 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003952 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003953 enum yang_keyword kw;
3954
3955 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003956 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003957 return LY_EVALID;
3958 }
3959
3960 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003961 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003962
3963 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3964 *flags |= LYS_YINELEM_TRUE;
3965 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3966 *flags |= LYS_YINELEM_FALSE;
3967 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003968 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003969 free(buf);
3970 return LY_EVALID;
3971 }
3972 free(buf);
3973
Radek Krejci6d6556c2018-11-08 09:37:45 +01003974 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003975 switch (kw) {
3976 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003977 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3978 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003979 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003980 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003981 return LY_EVALID;
3982 }
3983 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003984 return ret;
3985}
3986
Michal Vaskoea5abea2018-09-18 13:10:54 +02003987/**
3988 * @brief Parse the yin-element statement.
3989 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003990 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003991 * @param[in,out] data Data to read from, always moved to currently handled character.
3992 * @param[in,out] argument Value to write to.
3993 * @param[in,out] flags Flags to write to.
3994 * @param[in,out] exts Extension instances to add to.
3995 *
3996 * @return LY_ERR values.
3997 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003998static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003999parse_argument(struct lys_parser_ctx *ctx, const char **data, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004000{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004001 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004002 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004003 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004004 enum yang_keyword kw;
4005
4006 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004007 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004008 return LY_EVALID;
4009 }
4010
4011 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004012 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004013 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004014
Radek Krejci6d6556c2018-11-08 09:37:45 +01004015 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004016 switch (kw) {
4017 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004018 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004019 break;
4020 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004021 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004022 break;
4023 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004024 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004025 return LY_EVALID;
4026 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004027 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004028 return ret;
4029}
4030
Michal Vaskoea5abea2018-09-18 13:10:54 +02004031/**
4032 * @brief Parse the extension statement.
4033 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004034 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004035 * @param[in,out] data Data to read from, always moved to currently handled character.
4036 * @param[in,out] extensions Extensions to add to.
4037 *
4038 * @return LY_ERR values.
4039 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004040static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004041parse_extension(struct lys_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004042{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004043 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004044 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004045 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004046 enum yang_keyword kw;
4047 struct lysp_ext *ex;
4048
Radek Krejci2c4e7172018-10-19 15:56:26 +02004049 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004050
4051 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004052 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004053 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004054
Radek Krejci6d6556c2018-11-08 09:37:45 +01004055 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004056 switch (kw) {
4057 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004058 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 +02004059 break;
4060 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004061 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 +02004062 break;
4063 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004064 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004065 break;
4066 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004067 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004068 break;
4069 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004070 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004071 break;
4072 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004073 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004074 return LY_EVALID;
4075 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004076 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004077 return ret;
4078}
4079
Michal Vaskoea5abea2018-09-18 13:10:54 +02004080/**
4081 * @brief Parse the deviate statement.
4082 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004083 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004084 * @param[in,out] data Data to read from, always moved to currently handled character.
4085 * @param[in,out] deviates Deviates to add to.
4086 *
4087 * @return LY_ERR values.
4088 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004089LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004090parse_deviate(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004091{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004092 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004093 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004094 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004095 enum yang_keyword kw;
4096 struct lysp_deviate *iter, *d;
4097 struct lysp_deviate_add *d_add = NULL;
4098 struct lysp_deviate_rpl *d_rpl = NULL;
4099 struct lysp_deviate_del *d_del = NULL;
4100 const char **d_units, ***d_uniques, ***d_dflts;
4101 struct lysp_restr **d_musts;
4102 uint16_t *d_flags;
4103 uint32_t *d_min, *d_max;
4104
4105 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004106 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004107
4108 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4109 dev_mod = LYS_DEV_NOT_SUPPORTED;
4110 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4111 dev_mod = LYS_DEV_ADD;
4112 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4113 dev_mod = LYS_DEV_REPLACE;
4114 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4115 dev_mod = LYS_DEV_DELETE;
4116 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004117 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004118 free(buf);
4119 return LY_EVALID;
4120 }
4121 free(buf);
4122
4123 /* create structure */
4124 switch (dev_mod) {
4125 case LYS_DEV_NOT_SUPPORTED:
4126 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004127 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004128 break;
4129 case LYS_DEV_ADD:
4130 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004131 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004132 d = (struct lysp_deviate *)d_add;
4133 d_units = &d_add->units;
4134 d_uniques = &d_add->uniques;
4135 d_dflts = &d_add->dflts;
4136 d_musts = &d_add->musts;
4137 d_flags = &d_add->flags;
4138 d_min = &d_add->min;
4139 d_max = &d_add->max;
4140 break;
4141 case LYS_DEV_REPLACE:
4142 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004143 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004144 d = (struct lysp_deviate *)d_rpl;
4145 d_units = &d_rpl->units;
4146 d_flags = &d_rpl->flags;
4147 d_min = &d_rpl->min;
4148 d_max = &d_rpl->max;
4149 break;
4150 case LYS_DEV_DELETE:
4151 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004152 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004153 d = (struct lysp_deviate *)d_del;
4154 d_units = &d_del->units;
4155 d_uniques = &d_del->uniques;
4156 d_dflts = &d_del->dflts;
4157 d_musts = &d_del->musts;
4158 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004159 break;
4160 default:
4161 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004162 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004163 }
4164 d->mod = dev_mod;
4165
4166 /* insert into siblings */
4167 if (!*deviates) {
4168 *deviates = d;
4169 } else {
4170 for (iter = *deviates; iter->next; iter = iter->next);
4171 iter->next = d;
4172 }
4173
Radek Krejci6d6556c2018-11-08 09:37:45 +01004174 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004175 switch (kw) {
4176 case YANG_CONFIG:
4177 switch (dev_mod) {
4178 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004179 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004180 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004181 return LY_EVALID;
4182 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004183 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004184 break;
4185 }
4186 break;
4187 case YANG_DEFAULT:
4188 switch (dev_mod) {
4189 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004190 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004191 return LY_EVALID;
4192 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004193 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 +02004194 break;
4195 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004196 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 +02004197 break;
4198 }
4199 break;
4200 case YANG_MANDATORY:
4201 switch (dev_mod) {
4202 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004203 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004204 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004205 return LY_EVALID;
4206 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004207 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004208 break;
4209 }
4210 break;
4211 case YANG_MAX_ELEMENTS:
4212 switch (dev_mod) {
4213 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004214 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004215 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004216 return LY_EVALID;
4217 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004218 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004219 break;
4220 }
4221 break;
4222 case YANG_MIN_ELEMENTS:
4223 switch (dev_mod) {
4224 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004225 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004226 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004227 return LY_EVALID;
4228 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004229 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004230 break;
4231 }
4232 break;
4233 case YANG_MUST:
4234 switch (dev_mod) {
4235 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004236 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004237 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004238 return LY_EVALID;
4239 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004240 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004241 break;
4242 }
4243 break;
4244 case YANG_TYPE:
4245 switch (dev_mod) {
4246 case LYS_DEV_NOT_SUPPORTED:
4247 case LYS_DEV_ADD:
4248 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004249 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004250 return LY_EVALID;
4251 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004252 if (d_rpl->type) {
4253 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4254 return LY_EVALID;
4255 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004256 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004257 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004258 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004259 break;
4260 }
4261 break;
4262 case YANG_UNIQUE:
4263 switch (dev_mod) {
4264 case LYS_DEV_NOT_SUPPORTED:
4265 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004266 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004267 return LY_EVALID;
4268 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004269 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 +02004270 break;
4271 }
4272 break;
4273 case YANG_UNITS:
4274 switch (dev_mod) {
4275 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004276 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004277 return LY_EVALID;
4278 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004279 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 +02004280 break;
4281 }
4282 break;
4283 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004284 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004285 break;
4286 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004287 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004288 return LY_EVALID;
4289 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004290 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004291 return ret;
4292}
4293
Michal Vaskoea5abea2018-09-18 13:10:54 +02004294/**
4295 * @brief Parse the deviation statement.
4296 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004297 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004298 * @param[in,out] data Data to read from, always moved to currently handled character.
4299 * @param[in,out] deviations Deviations to add to.
4300 *
4301 * @return LY_ERR values.
4302 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004303LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004304parse_deviation(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004305{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004306 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004307 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004308 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004309 enum yang_keyword kw;
4310 struct lysp_deviation *dev;
4311
Radek Krejci2c4e7172018-10-19 15:56:26 +02004312 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004313
4314 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004315 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004316 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004317
Radek Krejci6d6556c2018-11-08 09:37:45 +01004318 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004319 switch (kw) {
4320 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004321 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 +02004322 break;
4323 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004324 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004325 break;
4326 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004327 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 +02004328 break;
4329 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004330 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004331 break;
4332 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004333 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004334 return LY_EVALID;
4335 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004336 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004337 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004338checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004339 /* mandatory substatements */
4340 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004341 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004342 return LY_EVALID;
4343 }
4344
4345 return ret;
4346}
4347
Michal Vaskoea5abea2018-09-18 13:10:54 +02004348/**
4349 * @brief Parse the feature statement.
4350 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004351 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004352 * @param[in,out] data Data to read from, always moved to currently handled character.
4353 * @param[in,out] features Features to add to.
4354 *
4355 * @return LY_ERR values.
4356 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004357LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004358parse_feature(struct lys_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004359{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004360 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004361 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004362 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004363 enum yang_keyword kw;
4364 struct lysp_feature *feat;
4365
Radek Krejci2c4e7172018-10-19 15:56:26 +02004366 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004367
4368 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004369 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004370 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004371
Radek Krejci6d6556c2018-11-08 09:37:45 +01004372 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004373 switch (kw) {
4374 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004375 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 +02004376 break;
4377 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004378 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 +02004379 break;
4380 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004381 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 +02004382 break;
4383 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004384 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004385 break;
4386 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004387 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004388 break;
4389 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004390 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004391 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004392 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004393 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004394 return ret;
4395}
4396
Michal Vaskoea5abea2018-09-18 13:10:54 +02004397/**
4398 * @brief Parse the identity statement.
4399 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004400 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004401 * @param[in,out] data Data to read from, always moved to currently handled character.
4402 * @param[in,out] identities Identities to add to.
4403 *
4404 * @return LY_ERR values.
4405 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004406LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004407parse_identity(struct lys_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004408{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004409 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004410 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004411 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004412 enum yang_keyword kw;
4413 struct lysp_ident *ident;
4414
Radek Krejci2c4e7172018-10-19 15:56:26 +02004415 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004416
4417 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004418 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004419 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004420
Radek Krejci6d6556c2018-11-08 09:37:45 +01004421 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422 switch (kw) {
4423 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004424 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 +02004425 break;
4426 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01004427 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004428 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 +02004429 break;
4430 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004431 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 +02004432 break;
4433 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004434 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004435 break;
4436 case YANG_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004437 if (ident->bases && ctx->mod_version < 2) {
Radek Krejci10113652018-11-14 16:56:50 +01004438 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4439 return LY_EVALID;
4440 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004441 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 +02004442 break;
4443 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004444 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004445 break;
4446 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004447 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004448 return LY_EVALID;
4449 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004450 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004451 return ret;
4452}
4453
Michal Vaskoea5abea2018-09-18 13:10:54 +02004454/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004455 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004456 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004457 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004458 * @param[in,out] data Data to read from, always moved to currently handled character.
4459 * @param[in,out] mod Module to write to.
4460 *
4461 * @return LY_ERR values.
4462 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004463LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004464parse_module(struct lys_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004465{
4466 LY_ERR ret = 0;
4467 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004468 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004469 enum yang_keyword kw, prev_kw = 0;
4470 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004471 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004472
4473 /* (sub)module name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004474 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004475 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004476
Radek Krejci6d6556c2018-11-08 09:37:45 +01004477 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004478
Radek Krejcie3846472018-10-15 15:24:51 +02004479#define CHECK_ORDER(SECTION) \
4480 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4481
Michal Vasko7fbc8162018-09-17 10:35:16 +02004482 switch (kw) {
4483 /* module header */
4484 case YANG_NAMESPACE:
4485 case YANG_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004486 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4487 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004488 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004489 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004490 break;
4491 /* linkage */
4492 case YANG_INCLUDE:
4493 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004494 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004495 break;
4496 /* meta */
4497 case YANG_ORGANIZATION:
4498 case YANG_CONTACT:
4499 case YANG_DESCRIPTION:
4500 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004501 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004502 break;
4503
4504 /* revision */
4505 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004506 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004507 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004508 /* body */
4509 case YANG_ANYDATA:
4510 case YANG_ANYXML:
4511 case YANG_AUGMENT:
4512 case YANG_CHOICE:
4513 case YANG_CONTAINER:
4514 case YANG_DEVIATION:
4515 case YANG_EXTENSION:
4516 case YANG_FEATURE:
4517 case YANG_GROUPING:
4518 case YANG_IDENTITY:
4519 case YANG_LEAF:
4520 case YANG_LEAF_LIST:
4521 case YANG_LIST:
4522 case YANG_NOTIFICATION:
4523 case YANG_RPC:
4524 case YANG_TYPEDEF:
4525 case YANG_USES:
4526 case YANG_CUSTOM:
4527 mod_stmt = Y_MOD_BODY;
4528 break;
4529 default:
4530 /* error handled in the next switch */
4531 break;
4532 }
Radek Krejcie3846472018-10-15 15:24:51 +02004533#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004534
Radek Krejcie3846472018-10-15 15:24:51 +02004535 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004536 switch (kw) {
4537 /* module header */
4538 case YANG_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004539 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4540 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004541 break;
4542 case YANG_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004543 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 +02004544 break;
4545 case YANG_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004546 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 +02004547 break;
4548
4549 /* linkage */
4550 case YANG_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004551 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004552 break;
4553 case YANG_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004554 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004555 break;
4556
4557 /* meta */
4558 case YANG_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004559 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 +02004560 break;
4561 case YANG_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004562 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 +02004563 break;
4564 case YANG_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004565 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 +02004566 break;
4567 case YANG_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004568 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 +02004569 break;
4570
4571 /* revision */
4572 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004573 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004574 break;
4575
4576 /* body */
4577 case YANG_ANYDATA:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004578 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004579 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004580 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004581 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004582 break;
4583 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004584 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004585 break;
4586 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004587 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004588 break;
4589 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004590 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004591 break;
4592 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004593 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004594 break;
4595 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004596 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004597 break;
4598 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004599 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004600 break;
4601
4602 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004603 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004604 break;
4605 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004606 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004607 break;
4608 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004609 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004610 break;
4611 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004612 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004613 break;
4614 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004615 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004616 break;
4617 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004618 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004619 break;
4620 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004621 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004622 break;
4623 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004624 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004625 break;
4626 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004627 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004628 break;
4629 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004630 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004631 break;
4632
4633 default:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004634 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004635 return LY_EVALID;
4636 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004637 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004638 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004639
Radek Krejci6d6556c2018-11-08 09:37:45 +01004640checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004641 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02004642 LY_CHECK_RET(parse_finalize_reallocated(ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004643
Michal Vasko7fbc8162018-09-17 10:35:16 +02004644 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004645 if (!mod->mod->ns) {
4646 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
4647 return LY_EVALID;
4648 } else if (!mod->mod->prefix) {
4649 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
4650 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004651 }
4652
Radek Krejcie9e987e2018-10-31 12:50:27 +01004653 /* submodules share the namespace with the module names, so there must not be
4654 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004655 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4656 if (dup) {
4657 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
4658 return LY_EVALID;
4659 }
4660
4661 return ret;
4662}
4663
4664/**
4665 * @brief Parse submodule substatements.
4666 *
4667 * @param[in] ctx yang parser context for logging.
4668 * @param[in,out] data Data to read from, always moved to currently handled character.
4669 * @param[out] submod Parsed submodule structure.
4670 *
4671 * @return LY_ERR values.
4672 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004673LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004674parse_submodule(struct lys_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004675{
4676 LY_ERR ret = 0;
4677 char *buf, *word;
4678 size_t word_len;
4679 enum yang_keyword kw, prev_kw = 0;
4680 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4681 struct lysp_submodule *dup;
4682
4683 /* submodule name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004684 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004685 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4686
4687 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4688
4689#define CHECK_ORDER(SECTION) \
4690 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4691
4692 switch (kw) {
4693 /* module header */
4694 case YANG_BELONGS_TO:
4695 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4696 break;
4697 case YANG_YANG_VERSION:
4698 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4699 break;
4700 /* linkage */
4701 case YANG_INCLUDE:
4702 case YANG_IMPORT:
4703 CHECK_ORDER(Y_MOD_LINKAGE);
4704 break;
4705 /* meta */
4706 case YANG_ORGANIZATION:
4707 case YANG_CONTACT:
4708 case YANG_DESCRIPTION:
4709 case YANG_REFERENCE:
4710 CHECK_ORDER(Y_MOD_META);
4711 break;
4712
4713 /* revision */
4714 case YANG_REVISION:
4715 CHECK_ORDER(Y_MOD_REVISION);
4716 break;
4717 /* body */
4718 case YANG_ANYDATA:
4719 case YANG_ANYXML:
4720 case YANG_AUGMENT:
4721 case YANG_CHOICE:
4722 case YANG_CONTAINER:
4723 case YANG_DEVIATION:
4724 case YANG_EXTENSION:
4725 case YANG_FEATURE:
4726 case YANG_GROUPING:
4727 case YANG_IDENTITY:
4728 case YANG_LEAF:
4729 case YANG_LEAF_LIST:
4730 case YANG_LIST:
4731 case YANG_NOTIFICATION:
4732 case YANG_RPC:
4733 case YANG_TYPEDEF:
4734 case YANG_USES:
4735 case YANG_CUSTOM:
4736 mod_stmt = Y_MOD_BODY;
4737 break;
4738 default:
4739 /* error handled in the next switch */
4740 break;
4741 }
4742#undef CHECK_ORDER
4743
4744 prev_kw = kw;
4745 switch (kw) {
4746 /* module header */
4747 case YANG_YANG_VERSION:
4748 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4749 ctx->mod_version = submod->version;
4750 break;
4751 case YANG_BELONGS_TO:
4752 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4753 break;
4754
4755 /* linkage */
4756 case YANG_INCLUDE:
4757 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4758 break;
4759 case YANG_IMPORT:
4760 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4761 break;
4762
4763 /* meta */
4764 case YANG_ORGANIZATION:
4765 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4766 break;
4767 case YANG_CONTACT:
4768 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4769 break;
4770 case YANG_DESCRIPTION:
4771 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4772 break;
4773 case YANG_REFERENCE:
4774 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4775 break;
4776
4777 /* revision */
4778 case YANG_REVISION:
4779 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4780 break;
4781
4782 /* body */
4783 case YANG_ANYDATA:
4784 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
4785 /* fall through */
4786 case YANG_ANYXML:
4787 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4788 break;
4789 case YANG_CHOICE:
4790 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4791 break;
4792 case YANG_CONTAINER:
4793 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4794 break;
4795 case YANG_LEAF:
4796 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4797 break;
4798 case YANG_LEAF_LIST:
4799 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4800 break;
4801 case YANG_LIST:
4802 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4803 break;
4804 case YANG_USES:
4805 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4806 break;
4807
4808 case YANG_AUGMENT:
4809 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4810 break;
4811 case YANG_DEVIATION:
4812 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4813 break;
4814 case YANG_EXTENSION:
4815 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4816 break;
4817 case YANG_FEATURE:
4818 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4819 break;
4820 case YANG_GROUPING:
4821 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4822 break;
4823 case YANG_IDENTITY:
4824 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4825 break;
4826 case YANG_NOTIFICATION:
4827 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4828 break;
4829 case YANG_RPC:
4830 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4831 break;
4832 case YANG_TYPEDEF:
4833 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4834 break;
4835 case YANG_CUSTOM:
4836 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4837 break;
4838
4839 default:
4840 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
4841 return LY_EVALID;
4842 }
4843 }
4844 LY_CHECK_RET(ret);
4845
4846checks:
4847 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02004848 LY_CHECK_RET(parse_finalize_reallocated(ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004849
4850 /* mandatory substatements */
4851 if (!submod->belongsto) {
4852 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
4853 return LY_EVALID;
4854 }
4855
4856 /* submodules share the namespace with the module names, so there must not be
4857 * a submodule of the same name in the context, no need for revision matching */
4858 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4859 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
4860 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004861 return LY_EVALID;
4862 }
4863
Michal Vasko7fbc8162018-09-17 10:35:16 +02004864 return ret;
4865}
4866
Radek Krejcid4557c62018-09-17 11:42:09 +02004867LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004868yang_parse_submodule(struct lys_parser_ctx *context, const char *data, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004869{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004870 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004871 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004872 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004873 enum yang_keyword kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004874 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004875
4876 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004877 ret = get_keyword(context, &data, &kw, &word, &word_len);
4878 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004879
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004880 if (kw == YANG_MODULE) {
4881 LOGERR(context->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
4882 ret = LY_EINVAL;
4883 goto cleanup;
4884 } else if (kw != YANG_SUBMODULE) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004885 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004886 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004887 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004888 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004889 }
4890
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004891 mod_p = calloc(1, sizeof *mod_p);
4892 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4893 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004894
4895 /* substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004896 ret = parse_submodule(context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004897 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004898
4899 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004900 while(*data && isspace(*data)) {
4901 data++;
4902 }
4903 if (*data) {
4904 LOGVAL_YANG(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
4905 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004906 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004907 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004908 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004909
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004910 mod_p->parsing = 0;
4911 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004912
Radek Krejcibbe09a92018-11-08 09:36:54 +01004913cleanup:
4914 if (ret) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004915 lysp_submodule_free(context->ctx, mod_p);
4916 }
4917
4918 return ret;
4919}
4920
4921LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004922yang_parse_module(struct lys_parser_ctx *context, const char *data, struct lys_module *mod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004923{
4924 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004925 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004926 size_t word_len;
4927 enum yang_keyword kw;
4928 struct lysp_module *mod_p = NULL;
4929
4930 /* "module"/"submodule" */
4931 ret = get_keyword(context, &data, &kw, &word, &word_len);
4932 LY_CHECK_GOTO(ret, cleanup);
4933
4934 if (kw == YANG_SUBMODULE) {
4935 LOGERR(context->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
4936 ret = LY_EINVAL;
4937 goto cleanup;
4938 } else if (kw != YANG_MODULE) {
4939 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
4940 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004941 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004942 goto cleanup;
4943 }
4944
4945 mod_p = calloc(1, sizeof *mod_p);
4946 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4947 mod_p->mod = mod;
4948 mod_p->parsing = 1;
4949
4950 /* substatements */
4951 ret = parse_module(context, &data, mod_p);
4952 LY_CHECK_GOTO(ret, cleanup);
4953
4954 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004955 while(*data && isspace(*data)) {
4956 data++;
4957 }
4958 if (*data) {
4959 LOGVAL_YANG(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
4960 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004961 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004962 goto cleanup;
4963 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004964
4965 mod_p->parsing = 0;
4966 mod->parsed = mod_p;
4967
4968cleanup:
4969 if (ret) {
4970 lysp_module_free(mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004971 }
4972
Michal Vasko7fbc8162018-09-17 10:35:16 +02004973 return ret;
4974}