blob: 328da74bed2d4574df3771a4b658c490a4b45640 [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
Michal Vaskoea5abea2018-09-18 13:10:54 +0200129/**
130 * @brief Add another character to dynamic buffer, a low-level function.
131 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200132 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200133 *
Radek Krejci404251e2018-10-09 12:06:44 +0200134 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200135 * @param[in, out] input Input string to process.
136 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200137 * @param[in,out] buf Buffer to use, can be moved by realloc().
138 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200139 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200140 *
141 * @return LY_ERR values.
142 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200143LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200144buf_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 +0200145{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200146 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200147 *buf_len += 16;
148 *buf = ly_realloc(*buf, *buf_len);
149 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
150 }
Radek Krejcic0917392019-04-10 13:04:04 +0200151 if (*buf_used) {
152 memcpy(&(*buf)[*buf_used], *input, len);
153 } else {
154 memcpy(*buf, *input, len);
155 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200156
Radek Krejci44ceedc2018-10-02 15:54:31 +0200157 (*buf_used) += len;
158 (*input) += len;
159
Michal Vasko7fbc8162018-09-17 10:35:16 +0200160 return LY_SUCCESS;
161}
162
Michal Vaskoea5abea2018-09-18 13:10:54 +0200163/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200164 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200165 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200166 * @param[in] ctx yang parser context for logging.
167 * @param[in] c UTF8 code point of a character to check.
168 * @return LY_ERR values.
169 */
170static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200171check_stringchar(struct lys_parser_ctx *ctx, unsigned int c)
Radek Krejci44ceedc2018-10-02 15:54:31 +0200172{
173 if (!is_yangutf8char(c)) {
174 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
175 return LY_EVALID;
176 }
177 return LY_SUCCESS;
178}
179
180/**
181 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
182 *
183 * @param[in] ctx yang parser context for logging.
184 * @param[in] c UTF8 code point of a character to check.
185 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200186 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
187 * 0 - colon not yet found (no prefix)
188 * 1 - \p c is the colon character
189 * 2 - prefix already processed, now processing the identifier
190 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200191 * If the identifier cannot be prefixed, NULL is expected.
192 * @return LY_ERR values.
193 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200194LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200195check_identifierchar(struct lys_parser_ctx *ctx, unsigned int c, int first, int *prefix)
Radek Krejci44ceedc2018-10-02 15:54:31 +0200196{
197 if (first || (prefix && (*prefix) == 1)) {
198 if (!is_yangidentstartchar(c)) {
199 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
200 return LY_EVALID;
201 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200202 if (prefix) {
203 if (first) {
204 (*prefix) = 0;
205 } else {
206 (*prefix) = 2;
207 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200208 }
209 } else if (c == ':' && prefix && (*prefix) == 0) {
210 (*prefix) = 1;
211 } else if (!is_yangidentchar(c)) {
212 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
213 return LY_EVALID;
214 }
215
216 return LY_SUCCESS;
217}
218
219/**
220 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
221 *
222 * @param[in] ctx yang parser context for logging.
223 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
224 * when function returns.
225 * @param[in] arg Type of the input string to select method of checking character validity.
226 * @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 +0200227 * 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 +0200228 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
229 * @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 +0200230 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200231 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200232 *
233 * @return LY_ERR values.
234 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200235LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200236buf_store_char(struct lys_parser_ctx *ctx, const char **input, enum yang_arg arg,
Radek Krejci44ceedc2018-10-02 15:54:31 +0200237 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200238{
Radek Krejci404251e2018-10-09 12:06:44 +0200239 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200240 unsigned int c;
241 size_t len;
242
Radek Krejcif29b7c32019-04-09 16:17:49 +0200243 /* check valid combination of input paremeters - if need_buf specified, word_b must be provided */
244 assert(!need_buf || (need_buf && word_b));
245
Radek Krejci44ceedc2018-10-02 15:54:31 +0200246 /* get UTF8 code point (and number of bytes coding the character) */
247 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
248 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
249 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200250 if (c == '\n') {
251 ctx->indent = 0;
252 } else {
253 /* note - even the multibyte character is count as 1 */
254 ++ctx->indent;
255 }
256
Radek Krejci44ceedc2018-10-02 15:54:31 +0200257 /* check character validity */
258 switch (arg) {
259 case Y_IDENTIF_ARG:
260 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
261 break;
262 case Y_PREF_IDENTIF_ARG:
263 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
264 break;
265 case Y_STR_ARG:
266 case Y_MAYBE_STR_ARG:
267 LY_CHECK_RET(check_stringchar(ctx, c));
268 break;
269 }
270
Michal Vasko7fbc8162018-09-17 10:35:16 +0200271 if (word_b && *word_b) {
272 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200273 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200274 return LY_EMEM;
275 }
276
277 /* in case of realloc */
278 *word_p = *word_b;
Radek Krejcif29b7c32019-04-09 16:17:49 +0200279 } else if (word_b && need_buf) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200280 /* first time we need a buffer, copy everything read up to now */
281 if (*word_len) {
282 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200283 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200284 *buf_len = *word_len;
285 memcpy(*word_b, *word_p, *word_len);
286 }
287
288 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200289 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200290 return LY_EMEM;
291 }
292
293 /* in case of realloc */
294 *word_p = *word_b;
295 } else {
296 /* just remember the first character pointer */
297 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200298 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200299 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200300 /* ... and update the word's length */
301 (*word_len) += len;
302 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200303 }
304
305 return LY_SUCCESS;
306}
307
Michal Vaskoea5abea2018-09-18 13:10:54 +0200308/**
309 * @brief Skip YANG comment in data.
310 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200311 * @param[in] ctx yang parser context for logging.
312 * @param[in,out] data Data to read from, automatically moved after the comment.
313 * @param[in] comment Type of the comment to process:
314 * 1 for a one-line comment,
315 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200316 *
317 * @return LY_ERR values.
318 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200319LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200320skip_comment(struct lys_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200321{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200322 /* internal statuses: 0 - comment ended,
323 * 1 - in line comment,
324 * 2 - in block comment,
325 * 3 - in block comment with last read character '*'
326 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200327 while (**data && comment) {
328 switch (comment) {
329 case 1:
330 if (**data == '\n') {
331 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200332 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200333 }
334 break;
335 case 2:
336 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200337 comment = 3;
338 } else if (**data == '\n') {
339 ++ctx->line;
340 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200341 break;
342 case 3:
343 if (**data == '/') {
344 comment = 0;
Radek Krejci5b930492019-06-11 14:54:08 +0200345 } else if (**data != '*') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200346 if (**data == '\n') {
347 ++ctx->line;
348 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200349 comment = 2;
350 }
351 break;
352 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200353 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200354 }
355
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200356 if (**data == '\n') {
357 ctx->indent = 0;
358 } else {
359 ++ctx->indent;
360 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200361 ++(*data);
362 }
363
364 if (!**data && (comment > 1)) {
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200365 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-input, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200366 return LY_EVALID;
367 }
368
369 return LY_SUCCESS;
370}
371
Michal Vaskoea5abea2018-09-18 13:10:54 +0200372/**
373 * @brief Read a quoted string from data.
374 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200375 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200376 * @param[in,out] data Data to read from, always moved to currently handled character.
377 * @param[in] arg Type of YANG keyword argument expected.
378 * @param[out] word_p Pointer to the read quoted string.
379 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
380 * set to NULL. Otherwise equal to \p word_p.
381 * @param[out] word_len Length of the read quoted string.
382 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
383 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
384 * indenation in the final quoted string.
385 *
386 * @return LY_ERR values.
387 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200388static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200389read_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 +0200390 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200391{
392 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
393 * 4 - string finished, now skipping whitespaces looking for +,
394 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200395 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200396 const char *c;
397
398 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200399 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200400 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200401 } else {
402 assert(**data == '\'');
403 string = 1;
404 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200405 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200406
407 while (**data && string) {
408 switch (string) {
409 case 1:
410 switch (**data) {
411 case '\'':
412 /* string may be finished, but check for + */
413 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200414 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200415 break;
416 default:
417 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200418 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 +0200419 break;
420 }
421 break;
422 case 2:
423 switch (**data) {
424 case '\"':
425 /* string may be finished, but check for + */
426 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200427 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200428 break;
429 case '\\':
430 /* special character following */
431 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200432 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200433 break;
434 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200435 if (current_indent < block_indent) {
436 ++current_indent;
437 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200438 } else {
439 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200440 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 +0200441 }
442 break;
443 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200444 if (current_indent < block_indent) {
445 assert(need_buf);
446 current_indent += 8;
447 ctx->indent += 8;
448 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
449 /* store leftover spaces from the tab */
450 c = " ";
451 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 +0200452 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200453 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200454 } else {
455 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200456 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 +0200457 /* additional characters for indentation - only 1 was count in buf_store_char */
458 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200459 }
460 break;
461 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200462 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200463 /* we will be removing the indents so we need our own buffer */
464 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200465
466 /* remove trailing tabs and spaces */
467 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
468 --(*word_len);
469 }
470
471 /* start indentation */
472 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200473 }
474
475 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200476 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
477
478 /* maintain line number */
479 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200480
481 /* reset context indentation counter for possible string after this one */
482 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200483 break;
484 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200485 /* first non-whitespace character, stop eating indentation */
486 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200487
488 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200489 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 +0200490 break;
491 }
492 break;
493 case 3:
494 /* string encoded characters */
495 switch (**data) {
496 case 'n':
497 c = "\n";
498 break;
499 case 't':
500 c = "\t";
501 break;
502 case '\"':
503 c = *data;
504 break;
505 case '\\':
506 c = *data;
507 break;
508 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200509 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200510 return LY_EVALID;
511 }
512
513 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200514 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 +0200515
516 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200517 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200518 break;
519 case 4:
520 switch (**data) {
521 case '+':
522 /* string continues */
523 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200524 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200525 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200526 case '\n':
527 ++ctx->line;
528 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200529 case ' ':
530 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200531 /* just skip */
532 break;
533 default:
534 /* string is finished */
535 goto string_end;
536 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200537 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200538 break;
539 case 5:
540 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200541 case '\n':
542 ++ctx->line;
543 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200544 case ' ':
545 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200546 /* skip */
547 break;
548 case '\'':
549 string = 1;
550 break;
551 case '\"':
552 string = 2;
553 break;
554 default:
555 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200556 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200557 return LY_EVALID;
558 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200559 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200560 break;
561 default:
562 return LY_EINT;
563 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200564 }
565
566string_end:
Radek Krejci4e199f52019-05-28 09:09:28 +0200567 if (arg <= Y_PREF_IDENTIF_ARG && !(*word_len)) {
568 /* empty identifier */
569 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Statement argument is required.");
570 return LY_EVALID;
571 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200572 return LY_SUCCESS;
573}
574
Michal Vaskoea5abea2018-09-18 13:10:54 +0200575/**
576 * @brief Get another YANG string from the raw data.
577 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200578 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200579 * @param[in,out] data Data to read from, always moved to currently handled character.
580 * @param[in] arg Type of YANG keyword argument expected.
Radek Krejcid3ca0632019-04-16 16:54:54 +0200581 * @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 +0200582 * @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 +0200583 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
584 * set to NULL. Otherwise equal to \p word_p.
585 * @param[out] word_len Length of the read string.
586 *
587 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200588 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200589LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200590get_argument(struct lys_parser_ctx *ctx, const char **data, enum yang_arg arg,
Radek Krejcid3ca0632019-04-16 16:54:54 +0200591 uint16_t *flags, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200592{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200593 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200594
595 /* word buffer - dynamically allocated */
596 *word_b = NULL;
597
598 /* word pointer - just a pointer to data */
599 *word_p = NULL;
600
601 *word_len = 0;
602 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200603 switch (**data) {
604 case '\'':
605 case '\"':
606 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200607 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
608 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
609 "unquoted string character, optsep, semicolon or opening brace");
610 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200611 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200612 if (flags) {
613 (*flags) |= (**data) == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
614 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100615 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200616 goto str_end;
617 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200618 if ((*data)[1] == '/') {
619 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200620 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100621 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200622 } else if ((*data)[1] == '*') {
623 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200624 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100625 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200626 } else {
627 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100628 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 +0200629 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200630 break;
631 case ' ':
632 if (*word_len) {
633 /* word is finished */
634 goto str_end;
635 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200636 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200637 break;
638 case '\t':
639 if (*word_len) {
640 /* word is finished */
641 goto str_end;
642 }
643 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200644 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200645
646 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200647 break;
648 case '\n':
649 if (*word_len) {
650 /* word is finished */
651 goto str_end;
652 }
653 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200654 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200655
656 /* track line numbers */
657 ++ctx->line;
658
659 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200660 break;
661 case ';':
662 case '{':
663 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
664 /* word is finished */
665 goto str_end;
666 }
667
Radek Krejci44ceedc2018-10-02 15:54:31 +0200668 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200669 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200670 case '}':
671 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
672 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
673 "unquoted string character, optsep, semicolon or opening brace");
674 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200675 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200676 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 +0200677 break;
678 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200679 }
680
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200681 /* unexpected end of loop */
682 LOGVAL_YANG(ctx, LY_VCODE_EOF);
683 return LY_EVALID;
684
Michal Vasko7fbc8162018-09-17 10:35:16 +0200685str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200686 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200687 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200688 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
689 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
690 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200691 *word_p = *word_b;
692 }
693
694 return LY_SUCCESS;
695}
696
Michal Vaskoea5abea2018-09-18 13:10:54 +0200697/**
698 * @brief Get another YANG keyword from the raw data.
699 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200700 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200701 * @param[in,out] data Data to read from, always moved to currently handled character.
702 * @param[out] kw YANG keyword read.
703 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
704 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
705 *
706 * @return LY_ERR values.
707 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200708LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200709get_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 +0200710{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200711 int prefix;
712 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200713 unsigned int c;
714 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200715
716 if (word_p) {
717 *word_p = NULL;
718 *word_len = 0;
719 }
720
721 /* first skip "optsep", comments */
722 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200723 switch (**data) {
724 case '/':
725 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200726 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200727 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100728 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200729 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200730 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200731 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100732 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200733 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200734 /* error - not a comment after all, keyword cannot start with slash */
735 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
736 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200737 }
Radek Krejci13028282019-06-11 14:56:48 +0200738 continue;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200739 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200740 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200741 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200742 ctx->indent = 0;
743 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200744 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200745 /* skip whitespaces (optsep) */
746 ++ctx->indent;
747 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200748 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200749 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200750 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200751 break;
752 default:
753 /* either a keyword start or an invalid character */
754 goto keyword_start;
755 }
756
757 ++(*data);
758 }
759
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200760#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
761#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
762#define IF_KW_PREFIX_END }
763
Michal Vasko7fbc8162018-09-17 10:35:16 +0200764keyword_start:
765 word_start = *data;
766 *kw = YANG_NONE;
767
768 /* read the keyword itself */
769 switch (**data) {
770 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200771 MOVE_INPUT(ctx, data, 1);
772 IF_KW("rgument", 7, YANG_ARGUMENT)
773 else IF_KW("ugment", 6, YANG_AUGMENT)
774 else IF_KW("ction", 5, YANG_ACTION)
775 else IF_KW_PREFIX("ny", 2)
776 IF_KW("data", 4, YANG_ANYDATA)
777 else IF_KW("xml", 3, YANG_ANYXML)
778 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200779 break;
780 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200781 MOVE_INPUT(ctx, data, 1);
782 IF_KW("ase", 3, YANG_BASE)
783 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
784 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200785 break;
786 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200787 MOVE_INPUT(ctx, data, 1);
788 IF_KW("ase", 3, YANG_CASE)
789 else IF_KW("hoice", 5, YANG_CHOICE)
790 else IF_KW_PREFIX("on", 2)
791 IF_KW("fig", 3, YANG_CONFIG)
792 else IF_KW_PREFIX("ta", 2)
793 IF_KW("ct", 2, YANG_CONTACT)
794 else IF_KW("iner", 4, YANG_CONTAINER)
795 IF_KW_PREFIX_END
796 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200797 break;
798 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200799 MOVE_INPUT(ctx, data, 1);
800 IF_KW_PREFIX("e", 1)
801 IF_KW("fault", 5, YANG_DEFAULT)
802 else IF_KW("scription", 9, YANG_DESCRIPTION)
803 else IF_KW_PREFIX("viat", 4)
804 IF_KW("e", 1, YANG_DEVIATE)
805 else IF_KW("ion", 3, YANG_DEVIATION)
806 IF_KW_PREFIX_END
807 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200808 break;
809 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200810 MOVE_INPUT(ctx, data, 1);
811 IF_KW("num", 3, YANG_ENUM)
812 else IF_KW_PREFIX("rror-", 5)
813 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
814 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
815 IF_KW_PREFIX_END
816 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200817 break;
818 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200819 MOVE_INPUT(ctx, data, 1);
820 IF_KW("eature", 6, YANG_FEATURE)
821 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200822 break;
823 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200824 MOVE_INPUT(ctx, data, 1);
825 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200826 break;
827 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200828 MOVE_INPUT(ctx, data, 1);
829 IF_KW("dentity", 7, YANG_IDENTITY)
830 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
831 else IF_KW("mport", 5, YANG_IMPORT)
832 else IF_KW_PREFIX("n", 1)
833 IF_KW("clude", 5, YANG_INCLUDE)
834 else IF_KW("put", 3, YANG_INPUT)
835 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200836 break;
837 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200838 MOVE_INPUT(ctx, data, 1);
839 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200840 break;
841 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200842 MOVE_INPUT(ctx, data, 1);
843 IF_KW_PREFIX("e", 1)
844 IF_KW("af-list", 7, YANG_LEAF_LIST)
845 else IF_KW("af", 2, YANG_LEAF)
846 else IF_KW("ngth", 4, YANG_LENGTH)
847 IF_KW_PREFIX_END
848 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200849 break;
850 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200851 MOVE_INPUT(ctx, data, 1);
852 IF_KW_PREFIX("a", 1)
853 IF_KW("ndatory", 7, YANG_MANDATORY)
854 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
855 IF_KW_PREFIX_END
856 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
857 else IF_KW("ust", 3, YANG_MUST)
858 else IF_KW_PREFIX("od", 2)
859 IF_KW("ule", 3, YANG_MODULE)
860 else IF_KW("ifier", 5, YANG_MODIFIER)
861 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200862 break;
863 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200864 MOVE_INPUT(ctx, data, 1);
865 IF_KW("amespace", 8, YANG_NAMESPACE)
866 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200867 break;
868 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200869 MOVE_INPUT(ctx, data, 1);
870 IF_KW_PREFIX("r", 1)
871 IF_KW("dered-by", 8, YANG_ORDERED_BY)
872 else IF_KW("ganization", 10, YANG_ORGANIZATION)
873 IF_KW_PREFIX_END
874 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200875 break;
876 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200877 MOVE_INPUT(ctx, data, 1);
878 IF_KW("ath", 3, YANG_PATH)
879 else IF_KW("attern", 6, YANG_PATTERN)
880 else IF_KW("osition", 7, YANG_POSITION)
881 else IF_KW_PREFIX("re", 2)
882 IF_KW("fix", 3, YANG_PREFIX)
883 else IF_KW("sence", 5, YANG_PRESENCE)
884 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200885 break;
886 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200887 MOVE_INPUT(ctx, data, 1);
888 IF_KW("ange", 4, YANG_RANGE)
889 else IF_KW_PREFIX("e", 1)
890 IF_KW_PREFIX("f", 1)
891 IF_KW("erence", 6, YANG_REFERENCE)
892 else IF_KW("ine", 3, YANG_REFINE)
893 IF_KW_PREFIX_END
894 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
895 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
896 else IF_KW("vision", 6, YANG_REVISION)
897 IF_KW_PREFIX_END
898 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200899 break;
900 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200901 MOVE_INPUT(ctx, data, 1);
902 IF_KW("tatus", 5, YANG_STATUS)
903 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200904 break;
905 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200906 MOVE_INPUT(ctx, data, 1);
907 IF_KW("ypedef", 6, YANG_TYPEDEF)
908 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200909 break;
910 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200911 MOVE_INPUT(ctx, data, 1);
912 IF_KW_PREFIX("ni", 2)
913 IF_KW("que", 3, YANG_UNIQUE)
914 else IF_KW("ts", 2, YANG_UNITS)
915 IF_KW_PREFIX_END
916 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200917 break;
918 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200919 MOVE_INPUT(ctx, data, 1);
920 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200921 break;
922 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200923 MOVE_INPUT(ctx, data, 1);
924 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200925 break;
926 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200927 MOVE_INPUT(ctx, data, 1);
928 IF_KW("ang-version", 11, YANG_YANG_VERSION)
929 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200930 break;
931 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200932 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200933 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200934 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200935 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200936 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200937 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200938 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200939 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200940 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200941 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200942 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200943 default:
944 break;
945 }
946
Radek Krejci0904c162019-01-02 15:03:59 +0100947#undef IF_KW
948#undef IF_KW_PREFIX
949#undef IF_KW_PREFIX_END
950
Michal Vasko7fbc8162018-09-17 10:35:16 +0200951 if (*kw != YANG_NONE) {
952 /* make sure we have the whole keyword */
953 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200954 case '\n':
955 ++ctx->line;
956 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200957 case ' ':
958 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200959 /* mandatory "sep" */
Radek Krejci13028282019-06-11 14:56:48 +0200960 MOVE_INPUT(ctx, data, 1);
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
1138 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001139 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001140
Radek Krejci6d6556c2018-11-08 09:37:45 +01001141 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001142 switch (kw) {
1143 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001144 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001145 break;
1146 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001147 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001148 return LY_EVALID;
1149 }
1150 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001151 return ret;
1152}
1153
Michal Vaskoea5abea2018-09-18 13:10:54 +02001154/**
1155 * @brief Parse the yang-version statement.
1156 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001157 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001158 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001159 * @param[out] version Storage for the parsed information.
1160 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001161 *
1162 * @return LY_ERR values.
1163 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001164static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001165parse_yangversion(struct lys_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001166{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001167 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001168 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001169 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001170 enum yang_keyword kw;
1171
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001172 if (*version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001173 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001174 return LY_EVALID;
1175 }
1176
1177 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001178 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001179
1180 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001181 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001182 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001183 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001185 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001186 free(buf);
1187 return LY_EVALID;
1188 }
1189 free(buf);
1190
Radek Krejci6d6556c2018-11-08 09:37:45 +01001191 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001192 switch (kw) {
1193 case YANG_CUSTOM:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001194 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001195 break;
1196 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001197 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001198 return LY_EVALID;
1199 }
1200 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001201 return ret;
1202}
1203
Michal Vaskoea5abea2018-09-18 13:10:54 +02001204/**
1205 * @brief Parse the belongs-to statement.
1206 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001207 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001208 * @param[in,out] data Data to read from, always moved to currently handled character.
1209 * @param[in,out] belongsto Place to store the parsed value.
1210 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1211 * @param[in,out] exts Extension instances to add to.
1212 *
1213 * @return LY_ERR values.
1214 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001215static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001216parse_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 +02001217{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001218 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001219 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001220 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001221 enum yang_keyword kw;
1222
1223 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001224 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001225 return LY_EVALID;
1226 }
1227
1228 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001229 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001230
Radek Krejci44ceedc2018-10-02 15:54:31 +02001231 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001232 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001233 switch (kw) {
1234 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001235 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001236 break;
1237 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001238 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001239 break;
1240 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001241 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001242 return LY_EVALID;
1243 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001244 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001245 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001246checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001247 /* mandatory substatements */
1248 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001249 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001250 return LY_EVALID;
1251 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001252 return ret;
1253}
1254
Michal Vaskoea5abea2018-09-18 13:10:54 +02001255/**
1256 * @brief Parse the revision-date statement.
1257 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001258 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001259 * @param[in,out] data Data to read from, always moved to currently handled character.
1260 * @param[in,out] rev Array to store the parsed value in.
1261 * @param[in,out] exts Extension instances to add to.
1262 *
1263 * @return LY_ERR values.
1264 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001265static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001266parse_revisiondate(struct lys_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001267{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001268 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001269 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001270 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001271 enum yang_keyword kw;
1272
1273 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001274 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001275 return LY_EVALID;
1276 }
1277
1278 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001279 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001280
1281 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001282 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001283 free(buf);
1284 return LY_EVALID;
1285 }
1286
1287 /* store value and spend buf if allocated */
1288 strncpy(rev, word, word_len);
1289 free(buf);
1290
Radek Krejci6d6556c2018-11-08 09:37:45 +01001291 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001292 switch (kw) {
1293 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001294 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001295 break;
1296 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001297 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001298 return LY_EVALID;
1299 }
1300 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001301 return ret;
1302}
1303
Michal Vaskoea5abea2018-09-18 13:10:54 +02001304/**
1305 * @brief Parse the include statement.
1306 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001307 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001308 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001309 * @param[in,out] data Data to read from, always moved to currently handled character.
1310 * @param[in,out] includes Parsed includes to add to.
1311 *
1312 * @return LY_ERR values.
1313 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001314static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001315parse_include(struct lys_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001316{
Radek Krejcid33273d2018-10-25 14:55:52 +02001317 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001318 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001319 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001320 enum yang_keyword kw;
1321 struct lysp_include *inc;
1322
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001323 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001324
1325 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001326 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001327
Radek Krejci086c7132018-10-26 15:29:04 +02001328 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1329
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001330 /* submodules share the namespace with the module names, so there must not be
1331 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001332 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001333 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1334 return LY_EVALID;
1335 }
1336
Radek Krejci6d6556c2018-11-08 09:37:45 +01001337 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001338 switch (kw) {
1339 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001340 YANG_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001341 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 +02001342 break;
1343 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001344 YANG_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001345 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 +02001346 break;
1347 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001348 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001349 break;
1350 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001351 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001352 break;
1353 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001354 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001355 return LY_EVALID;
1356 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001357 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001358 return ret;
1359}
1360
Michal Vaskoea5abea2018-09-18 13:10:54 +02001361/**
1362 * @brief Parse the import statement.
1363 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001364 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001365 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001366 * @param[in,out] data Data to read from, always moved to currently handled character.
1367 * @param[in,out] imports Parsed imports to add to.
1368 *
1369 * @return LY_ERR values.
1370 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001371static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001372parse_import(struct lys_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001373{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001374 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001375 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001376 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001377 enum yang_keyword kw;
1378 struct lysp_import *imp;
1379
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001380 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001381
1382 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001383 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001384 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001385
Radek Krejci6d6556c2018-11-08 09:37:45 +01001386 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001387 switch (kw) {
1388 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001389 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 +01001390 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001391 break;
1392 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001393 YANG_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001394 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 +02001395 break;
1396 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001397 YANG_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001398 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 +02001399 break;
1400 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001401 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001402 break;
1403 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001404 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001405 break;
1406 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001407 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001408 return LY_EVALID;
1409 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001410 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001411 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001412checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001413 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001414 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001415
1416 return ret;
1417}
1418
Michal Vaskoea5abea2018-09-18 13:10:54 +02001419/**
1420 * @brief Parse the revision statement.
1421 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001422 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001423 * @param[in,out] data Data to read from, always moved to currently handled character.
1424 * @param[in,out] revs Parsed revisions to add to.
1425 *
1426 * @return LY_ERR values.
1427 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001428static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001429parse_revision(struct lys_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001430{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001431 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001432 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001433 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001434 enum yang_keyword kw;
1435 struct lysp_revision *rev;
1436
Radek Krejci2c4e7172018-10-19 15:56:26 +02001437 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438
1439 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001440 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001441
1442 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001443 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001444 return LY_EVALID;
1445 }
1446
Radek Krejcib7db73a2018-10-24 14:18:40 +02001447 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001448 free(buf);
1449
Radek Krejci6d6556c2018-11-08 09:37:45 +01001450 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001451 switch (kw) {
1452 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001453 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 +02001454 break;
1455 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001456 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 +02001457 break;
1458 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001459 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001460 break;
1461 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001462 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001463 return LY_EVALID;
1464 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001465 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001466 return ret;
1467}
1468
Michal Vaskoea5abea2018-09-18 13:10:54 +02001469/**
1470 * @brief Parse a generic text field that can have more instances such as base.
1471 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001472 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001473 * @param[in,out] data Data to read from, always moved to currently handled character.
1474 * @param[in] substmt Type of this substatement.
1475 * @param[in,out] texts Parsed values to add to.
1476 * @param[in] arg Type of the expected argument.
1477 * @param[in,out] exts Extension instances to add to.
1478 *
1479 * @return LY_ERR values.
1480 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001481static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001482parse_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 +02001483 struct lysp_ext_instance **exts)
1484{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001485 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001486 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001487 const char **item;
1488 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001489 enum yang_keyword kw;
1490
1491 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001492 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001493
1494 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001495 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001496
Radek Krejci151a5b72018-10-19 14:21:44 +02001497 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001498 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001499 switch (kw) {
1500 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001501 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001502 break;
1503 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001504 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001505 return LY_EVALID;
1506 }
1507 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001508 return ret;
1509}
1510
Michal Vaskoea5abea2018-09-18 13:10:54 +02001511/**
1512 * @brief Parse the config statement.
1513 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001514 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001515 * @param[in,out] data Data to read from, always moved to currently handled character.
1516 * @param[in,out] flags Flags to add to.
1517 * @param[in,out] exts Extension instances to add to.
1518 *
1519 * @return LY_ERR values.
1520 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001521static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001522parse_config(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001523{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001524 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001525 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001526 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001527 enum yang_keyword kw;
1528
1529 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001530 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001531 return LY_EVALID;
1532 }
1533
1534 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001535 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001536
1537 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1538 *flags |= LYS_CONFIG_W;
1539 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1540 *flags |= LYS_CONFIG_R;
1541 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001542 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001543 free(buf);
1544 return LY_EVALID;
1545 }
1546 free(buf);
1547
Radek Krejci6d6556c2018-11-08 09:37:45 +01001548 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001549 switch (kw) {
1550 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001551 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001552 break;
1553 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001554 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001555 return LY_EVALID;
1556 }
1557 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001558 return ret;
1559}
1560
Michal Vaskoea5abea2018-09-18 13:10:54 +02001561/**
1562 * @brief Parse the mandatory statement.
1563 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001564 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001565 * @param[in,out] data Data to read from, always moved to currently handled character.
1566 * @param[in,out] flags Flags to add to.
1567 * @param[in,out] exts Extension instances to add to.
1568 *
1569 * @return LY_ERR values.
1570 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001571static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001572parse_mandatory(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001573{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001574 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001575 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001576 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001577 enum yang_keyword kw;
1578
1579 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001580 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001581 return LY_EVALID;
1582 }
1583
1584 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001585 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001586
1587 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1588 *flags |= LYS_MAND_TRUE;
1589 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1590 *flags |= LYS_MAND_FALSE;
1591 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001592 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001593 free(buf);
1594 return LY_EVALID;
1595 }
1596 free(buf);
1597
Radek Krejci6d6556c2018-11-08 09:37:45 +01001598 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001599 switch (kw) {
1600 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001601 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001602 break;
1603 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001604 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001605 return LY_EVALID;
1606 }
1607 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001608 return ret;
1609}
1610
Michal Vaskoea5abea2018-09-18 13:10:54 +02001611/**
1612 * @brief Parse a restriction such as range or length.
1613 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001614 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001615 * @param[in,out] data Data to read from, always moved to currently handled character.
1616 * @param[in] restr_kw Type of this particular restriction.
1617 * @param[in,out] exts Extension instances to add to.
1618 *
1619 * @return LY_ERR values.
1620 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001621static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001622parse_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 +02001623{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001624 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001625 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001626 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001627 enum yang_keyword kw;
1628
1629 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001630 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001631
Radek Krejci44ceedc2018-10-02 15:54:31 +02001632 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001633 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001634 switch (kw) {
1635 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001636 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 +02001637 break;
1638 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001639 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 +02001640 break;
1641 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001642 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 +02001643 break;
1644 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001645 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 +02001646 break;
1647 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001648 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001649 break;
1650 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001651 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001652 return LY_EVALID;
1653 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001654 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001655 return ret;
1656}
1657
Michal Vaskoea5abea2018-09-18 13:10:54 +02001658/**
1659 * @brief Parse a restriction that can have more instances such as must.
1660 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001661 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001662 * @param[in,out] data Data to read from, always moved to currently handled character.
1663 * @param[in] restr_kw Type of this particular restriction.
1664 * @param[in,out] restrs Restrictions to add to.
1665 *
1666 * @return LY_ERR values.
1667 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001668static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001669parse_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 +02001670{
1671 struct lysp_restr *restr;
1672
Radek Krejci2c4e7172018-10-19 15:56:26 +02001673 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001674 return parse_restr(ctx, data, restr_kw, restr);
1675}
1676
Michal Vaskoea5abea2018-09-18 13:10:54 +02001677/**
1678 * @brief Parse the status statement.
1679 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001680 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001681 * @param[in,out] data Data to read from, always moved to currently handled character.
1682 * @param[in,out] flags Flags to add to.
1683 * @param[in,out] exts Extension instances to add to.
1684 *
1685 * @return LY_ERR values.
1686 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001687static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001688parse_status(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001689{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001690 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001691 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001692 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001693 enum yang_keyword kw;
1694
1695 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001696 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001697 return LY_EVALID;
1698 }
1699
1700 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001701 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001702
1703 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1704 *flags |= LYS_STATUS_CURR;
1705 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1706 *flags |= LYS_STATUS_DEPRC;
1707 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1708 *flags |= LYS_STATUS_OBSLT;
1709 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001710 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001711 free(buf);
1712 return LY_EVALID;
1713 }
1714 free(buf);
1715
Radek Krejci6d6556c2018-11-08 09:37:45 +01001716 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001717 switch (kw) {
1718 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001719 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001720 break;
1721 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001722 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001723 return LY_EVALID;
1724 }
1725 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001726 return ret;
1727}
1728
Michal Vaskoea5abea2018-09-18 13:10:54 +02001729/**
1730 * @brief Parse the when statement.
1731 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001732 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001733 * @param[in,out] data Data to read from, always moved to currently handled character.
1734 * @param[in,out] when_p When pointer to parse to.
1735 *
1736 * @return LY_ERR values.
1737 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001738static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001739parse_when(struct lys_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001740{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001741 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001742 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001743 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001744 enum yang_keyword kw;
1745 struct lysp_when *when;
1746
1747 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001748 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001749 return LY_EVALID;
1750 }
1751
1752 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001753 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001754 *when_p = when;
1755
1756 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001757 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001758 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001759
Radek Krejci6d6556c2018-11-08 09:37:45 +01001760 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001761 switch (kw) {
1762 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001763 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 +02001764 break;
1765 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001766 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 +02001767 break;
1768 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001769 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001770 break;
1771 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001772 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001773 return LY_EVALID;
1774 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001775 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001776 return ret;
1777}
1778
Michal Vaskoea5abea2018-09-18 13:10:54 +02001779/**
1780 * @brief Parse the anydata or anyxml statement.
1781 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001782 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001783 * @param[in,out] data Data to read from, always moved to currently handled character.
1784 * @param[in] kw Type of this particular keyword.
1785 * @param[in,out] siblings Siblings to add to.
1786 *
1787 * @return LY_ERR values.
1788 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001789LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001790parse_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 +02001791{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001792 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001793 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001794 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001795 struct lysp_node *iter;
1796 struct lysp_node_anydata *any;
1797
1798 /* create structure */
1799 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001800 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001801 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001802 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001803
1804 /* insert into siblings */
1805 if (!*siblings) {
1806 *siblings = (struct lysp_node *)any;
1807 } else {
1808 for (iter = *siblings; iter->next; iter = iter->next);
1809 iter->next = (struct lysp_node *)any;
1810 }
1811
1812 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001813 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001814 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001815
1816 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001817 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001818 switch (kw) {
1819 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001820 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001821 break;
1822 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001823 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 +02001824 break;
1825 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001826 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 +02001827 break;
1828 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001829 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001830 break;
1831 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001832 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833 break;
1834 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001835 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 +02001836 break;
1837 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001838 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001839 break;
1840 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001841 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001842 break;
1843 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001844 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001845 break;
1846 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001847 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001848 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001849 return LY_EVALID;
1850 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001851 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001852 return ret;
1853}
1854
Michal Vaskoea5abea2018-09-18 13:10:54 +02001855/**
1856 * @brief Parse the value or position statement. Substatement of type enum statement.
1857 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001858 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001859 * @param[in,out] data Data to read from, always moved to currently handled character.
1860 * @param[in] val_kw Type of this particular keyword.
1861 * @param[in,out] value Value to write to.
1862 * @param[in,out] flags Flags to write to.
1863 * @param[in,out] exts Extension instances to add to.
1864 *
1865 * @return LY_ERR values.
1866 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001867static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001868parse_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 +02001869 struct lysp_ext_instance **exts)
1870{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001871 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001872 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001873 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001874 long int num;
1875 unsigned long int unum;
1876 enum yang_keyword kw;
1877
1878 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001879 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001880 return LY_EVALID;
1881 }
1882 *flags |= LYS_SET_VALUE;
1883
1884 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001885 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001886
1887 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 +02001888 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001889 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001890 }
1891
1892 errno = 0;
1893 if (val_kw == YANG_VALUE) {
1894 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001895 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
1896 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1897 goto error;
1898 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001899 } else {
1900 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001901 if (unum > UINT64_C(4294967295)) {
1902 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1903 goto error;
1904 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001905 }
1906 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001907 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001908 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001909 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001910 }
1911 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001912 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001913 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001914 }
1915 if (val_kw == YANG_VALUE) {
1916 *value = num;
1917 } else {
1918 *value = unum;
1919 }
1920 free(buf);
1921
Radek Krejci6d6556c2018-11-08 09:37:45 +01001922 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001923 switch (kw) {
1924 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001925 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 +02001926 break;
1927 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001928 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001929 return LY_EVALID;
1930 }
1931 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001932 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001933
1934error:
1935 free(buf);
1936 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001937}
1938
Michal Vaskoea5abea2018-09-18 13:10:54 +02001939/**
1940 * @brief Parse the enum or bit statement. Substatement of type statement.
1941 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001942 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001943 * @param[in,out] data Data to read from, always moved to currently handled character.
1944 * @param[in] enum_kw Type of this particular keyword.
1945 * @param[in,out] enums Enums or bits to add to.
1946 *
1947 * @return LY_ERR values.
1948 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001950parse_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 +02001951{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001952 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001953 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001954 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001955 enum yang_keyword kw;
1956 struct lysp_type_enum *enm;
1957
Radek Krejci2c4e7172018-10-19 15:56:26 +02001958 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001959
1960 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001961 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 +01001962 if (enum_kw == YANG_ENUM) {
1963 if (!word_len) {
1964 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
1965 free(buf);
1966 return LY_EVALID;
1967 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
1968 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
1969 word_len, word);
1970 free(buf);
1971 return LY_EVALID;
1972 } else {
1973 for (u = 0; u < word_len; ++u) {
1974 if (iscntrl(word[u])) {
1975 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1976 word_len, word, u + 1);
1977 break;
1978 }
1979 }
1980 }
1981 } else { /* YANG_BIT */
1982
1983 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001984 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001985 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1986
Radek Krejci6d6556c2018-11-08 09:37:45 +01001987 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001988 switch (kw) {
1989 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001990 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 +02001991 break;
1992 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001993 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001994 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 +02001995 break;
1996 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001997 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 +02001998 break;
1999 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002000 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002001 break;
2002 case YANG_VALUE:
2003 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002004 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002005 break;
2006 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002007 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002008 break;
2009 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002010 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002011 return LY_EVALID;
2012 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002013 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002014 return ret;
2015}
2016
Michal Vaskoea5abea2018-09-18 13:10:54 +02002017/**
2018 * @brief Parse the fraction-digits statement. Substatement of type statement.
2019 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002020 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002021 * @param[in,out] data Data to read from, always moved to currently handled character.
2022 * @param[in,out] fracdig Value to write to.
2023 * @param[in,out] exts Extension instances to add to.
2024 *
2025 * @return LY_ERR values.
2026 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002027static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002028parse_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 +02002029{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002030 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002031 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002032 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002033 unsigned long int num;
2034 enum yang_keyword kw;
2035
2036 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002037 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002038 return LY_EVALID;
2039 }
2040
2041 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002042 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002043
2044 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002045 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002046 free(buf);
2047 return LY_EVALID;
2048 }
2049
2050 errno = 0;
2051 num = strtoul(word, &ptr, 10);
2052 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002053 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002054 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002055 free(buf);
2056 return LY_EVALID;
2057 }
2058 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002059 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002060 free(buf);
2061 return LY_EVALID;
2062 }
2063 *fracdig = num;
2064 free(buf);
2065
Radek Krejci6d6556c2018-11-08 09:37:45 +01002066 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002067 switch (kw) {
2068 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002069 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002070 break;
2071 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002072 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002073 return LY_EVALID;
2074 }
2075 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002076 return ret;
2077}
2078
Michal Vaskoea5abea2018-09-18 13:10:54 +02002079/**
2080 * @brief Parse the require-instance statement. Substatement of type statement.
2081 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002082 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002083 * @param[in,out] data Data to read from, always moved to currently handled character.
2084 * @param[in,out] reqinst Value to write to.
2085 * @param[in,out] flags Flags to write to.
2086 * @param[in,out] exts Extension instances to add to.
2087 *
2088 * @return LY_ERR values.
2089 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002090static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002091parse_type_reqinstance(struct lys_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002092 struct lysp_ext_instance **exts)
2093{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002094 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002095 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002096 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002097 enum yang_keyword kw;
2098
2099 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002100 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002101 return LY_EVALID;
2102 }
2103 *flags |= LYS_SET_REQINST;
2104
2105 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002106 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002107
2108 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2109 *reqinst = 1;
2110 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002111 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002112 free(buf);
2113 return LY_EVALID;
2114 }
2115 free(buf);
2116
Radek Krejci6d6556c2018-11-08 09:37:45 +01002117 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002118 switch (kw) {
2119 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002120 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002121 break;
2122 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002123 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002124 return LY_EVALID;
2125 }
2126 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002127 return ret;
2128}
2129
Michal Vaskoea5abea2018-09-18 13:10:54 +02002130/**
2131 * @brief Parse the modifier statement. Substatement of type pattern statement.
2132 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002133 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002134 * @param[in,out] data Data to read from, always moved to currently handled character.
2135 * @param[in,out] pat Value to write to.
2136 * @param[in,out] exts Extension instances to add to.
2137 *
2138 * @return LY_ERR values.
2139 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002140static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002141parse_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 +02002142{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002143 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002144 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002145 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002146 enum yang_keyword kw;
2147
2148 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002149 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002150 return LY_EVALID;
2151 }
2152
2153 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002154 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002155
2156 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002157 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002158 free(buf);
2159 return LY_EVALID;
2160 }
2161 free(buf);
2162
2163 /* replace the value in the dictionary */
2164 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002165 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002166 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002167 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002168
2169 assert(buf[0] == 0x06);
2170 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002171 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002172
Radek Krejci6d6556c2018-11-08 09:37:45 +01002173 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002174 switch (kw) {
2175 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002176 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002177 break;
2178 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002179 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002180 return LY_EVALID;
2181 }
2182 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002183 return ret;
2184}
2185
Michal Vaskoea5abea2018-09-18 13:10:54 +02002186/**
2187 * @brief Parse the pattern statement. Substatement of type statement.
2188 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002189 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002190 * @param[in,out] data Data to read from, always moved to currently handled character.
2191 * @param[in,out] patterns Restrictions to add to.
2192 *
2193 * @return LY_ERR values.
2194 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002195static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002196parse_type_pattern(struct lys_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002197{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002198 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002199 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002200 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002201 enum yang_keyword kw;
2202 struct lysp_restr *restr;
2203
Radek Krejci2c4e7172018-10-19 15:56:26 +02002204 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002205
2206 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002207 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002208
2209 /* add special meaning first byte */
2210 if (buf) {
2211 buf = realloc(buf, word_len + 2);
2212 word = buf;
2213 } else {
2214 buf = malloc(word_len + 2);
2215 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002216 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002217 memmove(buf + 1, word, word_len);
2218 buf[0] = 0x06; /* pattern's default regular-match flag */
2219 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2220 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002221
Radek Krejci6d6556c2018-11-08 09:37:45 +01002222 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002223 switch (kw) {
2224 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002225 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 +02002226 break;
2227 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002228 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 +02002229 break;
2230 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002231 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 +02002232 break;
2233 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002234 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 +02002235 break;
2236 case YANG_MODIFIER:
Radek Krejciceaf2122019-01-02 15:03:26 +01002237 YANG_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002238 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002239 break;
2240 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002241 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002242 break;
2243 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002244 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002245 return LY_EVALID;
2246 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002247 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002248 return ret;
2249}
2250
Michal Vaskoea5abea2018-09-18 13:10:54 +02002251/**
2252 * @brief Parse the type statement.
2253 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002254 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002255 * @param[in,out] data Data to read from, always moved to currently handled character.
2256 * @param[in,out] type Type to wrote to.
2257 *
2258 * @return LY_ERR values.
2259 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002260static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002261parse_type(struct lys_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002262{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002263 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002264 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002265 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002266 enum yang_keyword kw;
2267 struct lysp_type *nest_type;
2268
2269 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002270 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002271 return LY_EVALID;
2272 }
2273
2274 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002275 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002276 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002277
Radek Krejci6d6556c2018-11-08 09:37:45 +01002278 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002279 switch (kw) {
2280 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002281 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 +01002282 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002283 break;
2284 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002285 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002286 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002287 break;
2288 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002289 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002290 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002291 break;
2292 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002293 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002294 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002295 break;
2296 case YANG_LENGTH:
2297 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002298 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002299 return LY_EVALID;
2300 }
2301 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002302 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002303
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002304 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002305 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002306 break;
2307 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002308 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 +01002309 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002310 break;
2311 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002312 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002313 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002314 break;
2315 case YANG_RANGE:
2316 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002317 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002318 return LY_EVALID;
2319 }
2320 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002321 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002322
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002323 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002324 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002325 break;
2326 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002327 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002328 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002329 break;
2330 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002331 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2332 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002333 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002334 break;
2335 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002336 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002337 break;
2338 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002339 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002340 return LY_EVALID;
2341 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002342 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002343 return ret;
2344}
2345
Michal Vaskoea5abea2018-09-18 13:10:54 +02002346/**
2347 * @brief Parse the leaf statement.
2348 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002349 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002350 * @param[in,out] data Data to read from, always moved to currently handled character.
2351 * @param[in,out] siblings Siblings to add to.
2352 *
2353 * @return LY_ERR values.
2354 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002355LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002356parse_leaf(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002357{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002358 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002359 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002360 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002361 enum yang_keyword kw;
2362 struct lysp_node *iter;
2363 struct lysp_node_leaf *leaf;
2364
2365 /* create structure */
2366 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002367 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002368 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002369 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002370
2371 /* insert into siblings */
2372 if (!*siblings) {
2373 *siblings = (struct lysp_node *)leaf;
2374 } else {
2375 for (iter = *siblings; iter->next; iter = iter->next);
2376 iter->next = (struct lysp_node *)leaf;
2377 }
2378
2379 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002380 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002381 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002382
2383 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002384 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002385 switch (kw) {
2386 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002387 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002388 break;
2389 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002390 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 +02002391 break;
2392 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002393 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 +02002394 break;
2395 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002396 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 +02002397 break;
2398 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002399 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002400 break;
2401 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002402 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002403 break;
2404 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002405 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 +02002406 break;
2407 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002408 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002409 break;
2410 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002411 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002412 break;
2413 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002414 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 +02002415 break;
2416 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002417 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002418 break;
2419 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002420 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002421 break;
2422 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002423 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002424 return LY_EVALID;
2425 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002426 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002427 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002428checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002429 /* mandatory substatements */
2430 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002431 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002432 return LY_EVALID;
2433 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002434 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
2435 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
2436 return LY_EVALID;
2437 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002438
2439 return ret;
2440}
2441
Michal Vaskoea5abea2018-09-18 13:10:54 +02002442/**
2443 * @brief Parse the max-elements statement.
2444 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002445 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002446 * @param[in,out] data Data to read from, always moved to currently handled character.
2447 * @param[in,out] max Value to write to.
2448 * @param[in,out] flags Flags to write to.
2449 * @param[in,out] exts Extension instances to add to.
2450 *
2451 * @return LY_ERR values.
2452 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002453LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002454parse_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 +02002455{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002456 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002457 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002458 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002459 unsigned long int num;
2460 enum yang_keyword kw;
2461
2462 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002463 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002464 return LY_EVALID;
2465 }
2466 *flags |= LYS_SET_MAX;
2467
2468 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002469 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002470
2471 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002472 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002473 free(buf);
2474 return LY_EVALID;
2475 }
2476
2477 if (strncmp(word, "unbounded", word_len)) {
2478 errno = 0;
2479 num = strtoul(word, &ptr, 10);
2480 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002481 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002482 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002483 free(buf);
2484 return LY_EVALID;
2485 }
2486 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002487 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002488 free(buf);
2489 return LY_EVALID;
2490 }
2491
2492 *max = num;
2493 }
2494 free(buf);
2495
Radek Krejci6d6556c2018-11-08 09:37:45 +01002496 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002497 switch (kw) {
2498 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002499 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002500 break;
2501 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002502 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002503 return LY_EVALID;
2504 }
2505 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002506 return ret;
2507}
2508
Michal Vaskoea5abea2018-09-18 13:10:54 +02002509/**
2510 * @brief Parse the min-elements statement.
2511 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002512 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002513 * @param[in,out] data Data to read from, always moved to currently handled character.
2514 * @param[in,out] min Value to write to.
2515 * @param[in,out] flags Flags to write to.
2516 * @param[in,out] exts Extension instances to add to.
2517 *
2518 * @return LY_ERR values.
2519 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002520LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002521parse_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 +02002522{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002523 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002524 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002525 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002526 unsigned long int num;
2527 enum yang_keyword kw;
2528
2529 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002530 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002531 return LY_EVALID;
2532 }
2533 *flags |= LYS_SET_MIN;
2534
2535 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002536 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002537
2538 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002539 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002540 free(buf);
2541 return LY_EVALID;
2542 }
2543
2544 errno = 0;
2545 num = strtoul(word, &ptr, 10);
2546 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002547 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002548 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002549 free(buf);
2550 return LY_EVALID;
2551 }
2552 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002553 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002554 free(buf);
2555 return LY_EVALID;
2556 }
2557 *min = num;
2558 free(buf);
2559
Radek Krejci6d6556c2018-11-08 09:37:45 +01002560 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002561 switch (kw) {
2562 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002563 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002564 break;
2565 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002566 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002567 return LY_EVALID;
2568 }
2569 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002570 return ret;
2571}
2572
Michal Vaskoea5abea2018-09-18 13:10:54 +02002573/**
2574 * @brief Parse the ordered-by statement.
2575 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002576 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002577 * @param[in,out] data Data to read from, always moved to currently handled character.
2578 * @param[in,out] flags Flags to write to.
2579 * @param[in,out] exts Extension instances to add to.
2580 *
2581 * @return LY_ERR values.
2582 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002583static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002584parse_orderedby(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002585{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002586 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002587 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002588 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002589 enum yang_keyword kw;
2590
2591 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002592 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002593 return LY_EVALID;
2594 }
2595
2596 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002597 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002598
2599 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2600 *flags |= LYS_ORDBY_SYSTEM;
2601 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2602 *flags |= LYS_ORDBY_USER;
2603 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002604 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002605 free(buf);
2606 return LY_EVALID;
2607 }
2608 free(buf);
2609
Radek Krejci6d6556c2018-11-08 09:37:45 +01002610 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002611 switch (kw) {
2612 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002613 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002614 break;
2615 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002616 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002617 return LY_EVALID;
2618 }
2619 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002620 return ret;
2621}
2622
Michal Vaskoea5abea2018-09-18 13:10:54 +02002623/**
2624 * @brief Parse the leaf-list statement.
2625 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002626 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002627 * @param[in,out] data Data to read from, always moved to currently handled character.
2628 * @param[in,out] siblings Siblings to add to.
2629 *
2630 * @return LY_ERR values.
2631 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002632LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002633parse_leaflist(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002634{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002635 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002637 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002638 enum yang_keyword kw;
2639 struct lysp_node *iter;
2640 struct lysp_node_leaflist *llist;
2641
2642 /* create structure */
2643 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002644 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002645 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002646 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002647
2648 /* insert into siblings */
2649 if (!*siblings) {
2650 *siblings = (struct lysp_node *)llist;
2651 } else {
2652 for (iter = *siblings; iter->next; iter = iter->next);
2653 iter->next = (struct lysp_node *)llist;
2654 }
2655
2656 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002657 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002658 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002659
2660 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002661 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002662 switch (kw) {
2663 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002664 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002665 break;
2666 case YANG_DEFAULT:
Radek Krejciceaf2122019-01-02 15:03:26 +01002667 YANG_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002668 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 +02002669 break;
2670 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002671 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 +02002672 break;
2673 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002674 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 +02002675 break;
2676 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002677 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002678 break;
2679 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002680 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002681 break;
2682 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002683 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002684 break;
2685 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002686 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002687 break;
2688 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002689 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 +02002690 break;
2691 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002692 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002693 break;
2694 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002695 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002696 break;
2697 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002698 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 +02002699 break;
2700 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002701 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002702 break;
2703 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002704 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002705 break;
2706 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002707 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002708 return LY_EVALID;
2709 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002710 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002711 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002712checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002713 /* mandatory substatements */
2714 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002715 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002716 return LY_EVALID;
2717 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002718 if ((llist->min) && (llist->dflts)) {
2719 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
2720 return LY_EVALID;
2721 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002722 if (llist->max && llist->min > llist->max) {
2723 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
2724 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2725 llist->min, llist->max);
2726 return LY_EVALID;
2727 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002728
2729 return ret;
2730}
2731
Michal Vaskoea5abea2018-09-18 13:10:54 +02002732/**
2733 * @brief Parse the refine statement.
2734 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002735 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002736 * @param[in,out] data Data to read from, always moved to currently handled character.
2737 * @param[in,out] refines Refines to add to.
2738 *
2739 * @return LY_ERR values.
2740 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002741static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002742parse_refine(struct lys_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002743{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002744 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002745 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002746 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002747 enum yang_keyword kw;
2748 struct lysp_refine *rf;
2749
Radek Krejci2c4e7172018-10-19 15:56:26 +02002750 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002751
2752 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002753 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002754 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002755
Radek Krejci6d6556c2018-11-08 09:37:45 +01002756 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002757 switch (kw) {
2758 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002759 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002760 break;
2761 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002762 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 +02002763 break;
2764 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002765 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 +02002766 break;
2767 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01002768 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002769 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 +02002770 break;
2771 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002772 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002773 break;
2774 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002775 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002776 break;
2777 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002778 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002779 break;
2780 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002781 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002782 break;
2783 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002784 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 +02002785 break;
2786 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002787 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 +02002788 break;
2789 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002790 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002791 break;
2792 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002793 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002794 return LY_EVALID;
2795 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002797 return ret;
2798}
2799
Michal Vaskoea5abea2018-09-18 13:10:54 +02002800/**
2801 * @brief Parse the typedef statement.
2802 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002803 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002804 * @param[in,out] data Data to read from, always moved to currently handled character.
2805 * @param[in,out] typedefs Typedefs to add to.
2806 *
2807 * @return LY_ERR values.
2808 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002810parse_typedef(struct lys_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002811{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002812 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002813 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002814 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002815 enum yang_keyword kw;
2816 struct lysp_tpdf *tpdf;
2817
Radek Krejci2c4e7172018-10-19 15:56:26 +02002818 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002819
2820 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002821 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002822 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002823
2824 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002825 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002826 switch (kw) {
2827 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002828 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 +02002829 break;
2830 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002831 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 +02002832 break;
2833 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002834 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 +02002835 break;
2836 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002837 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002838 break;
2839 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002840 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002841 break;
2842 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002843 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 +02002844 break;
2845 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002846 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002847 break;
2848 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002849 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002850 return LY_EVALID;
2851 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002852 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002853 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002854checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002855 /* mandatory substatements */
2856 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002857 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002858 return LY_EVALID;
2859 }
2860
Radek Krejcibbe09a92018-11-08 09:36:54 +01002861 /* store data for collision check */
2862 if (parent) {
2863 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2864 }
2865
Michal Vasko7fbc8162018-09-17 10:35:16 +02002866 return ret;
2867}
2868
Michal Vaskoea5abea2018-09-18 13:10:54 +02002869/**
2870 * @brief Parse the input or output statement.
2871 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002872 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002873 * @param[in,out] data Data to read from, always moved to currently handled character.
2874 * @param[in] kw Type of this particular keyword
2875 * @param[in,out] inout_p Input/output pointer to write to.
2876 *
2877 * @return LY_ERR values.
2878 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002879static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002880parse_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 +02002881{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002882 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002883 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002884 size_t word_len;
Radek Krejci10113652018-11-14 16:56:50 +01002885 enum yang_keyword kw;
Radek Krejcie86bf772018-12-14 11:39:53 +01002886 unsigned int u;
2887 struct lysp_node *child;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002888
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002889 if (inout_p->nodetype) {
Radek Krejci10113652018-11-14 16:56:50 +01002890 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891 return LY_EVALID;
2892 }
2893
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002894 /* initiate structure */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002895 inout_p->nodetype = &((struct lysp_action*)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002896 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002897
2898 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002899 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002900 switch (kw) {
2901 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002902 YANG_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002903 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002904 case YANG_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002905 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002906 break;
2907 case YANG_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002908 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002909 break;
2910 case YANG_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002911 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002912 break;
2913 case YANG_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002914 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002915 break;
2916 case YANG_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002917 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918 break;
2919 case YANG_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002920 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002921 break;
2922 case YANG_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002923 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002924 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002925 case YANG_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002926 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002927 break;
2928 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002929 YANG_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002930 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002931 break;
2932 case YANG_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002933 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002934 break;
2935 case YANG_CUSTOM:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002936 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002937 break;
2938 default:
Radek Krejci10113652018-11-14 16:56:50 +01002939 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002940 return LY_EVALID;
2941 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002942 }
Radek Krejcie86bf772018-12-14 11:39:53 +01002943 /* finalize parent pointers to the reallocated items */
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002944 LY_ARRAY_FOR(inout_p->groupings, u) {
2945 LY_LIST_FOR(inout_p->groupings[u].data, child) {
2946 child->parent = (struct lysp_node*)&inout_p->groupings[u];
Radek Krejcie86bf772018-12-14 11:39:53 +01002947 }
2948 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002949 return ret;
2950}
2951
Michal Vaskoea5abea2018-09-18 13:10:54 +02002952/**
2953 * @brief Parse the action statement.
2954 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002955 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002956 * @param[in,out] data Data to read from, always moved to currently handled character.
2957 * @param[in,out] actions Actions to add to.
2958 *
2959 * @return LY_ERR values.
2960 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002961LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002962parse_action(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002963{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002964 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002965 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002966 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002967 enum yang_keyword kw;
2968 struct lysp_action *act;
Radek Krejcie86bf772018-12-14 11:39:53 +01002969 struct lysp_node *child;
2970 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002971
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 Krejci6d6556c2018-11-08 09:37:45 +01002980 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
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 Krejcie86bf772018-12-14 11:39:53 +01003016 /* finalize parent pointers to the reallocated items */
3017 LY_ARRAY_FOR(act->groupings, u) {
3018 LY_LIST_FOR(act->groupings[u].data, child) {
3019 child->parent = (struct lysp_node*)&act->groupings[u];
3020 }
3021 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003022 return ret;
3023}
3024
Michal Vaskoea5abea2018-09-18 13:10:54 +02003025/**
3026 * @brief Parse the notification statement.
3027 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003028 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003029 * @param[in,out] data Data to read from, always moved to currently handled character.
3030 * @param[in,out] notifs Notifications to add to.
3031 *
3032 * @return LY_ERR values.
3033 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003034LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003035parse_notif(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003036{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003037 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003038 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003039 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003040 enum yang_keyword kw;
3041 struct lysp_notif *notif;
Radek Krejcie86bf772018-12-14 11:39:53 +01003042 struct lysp_node *child;
3043 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003044
Radek Krejci2c4e7172018-10-19 15:56:26 +02003045 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003046
3047 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003048 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003049 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003050 notif->nodetype = LYS_NOTIF;
3051 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003052
Radek Krejci6d6556c2018-11-08 09:37:45 +01003053 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003054 switch (kw) {
3055 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003056 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 +02003057 break;
3058 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003059 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 +02003060 break;
3061 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003062 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 +02003063 break;
3064 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003065 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003066 break;
3067
3068 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003069 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01003070 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003072 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003073 break;
3074 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003075 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076 break;
3077 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003078 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079 break;
3080 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003081 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003082 break;
3083 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003084 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003085 break;
3086 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003087 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003088 break;
3089 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003090 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003091 break;
3092
3093 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01003094 YANG_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003095 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003096 break;
3097 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003098 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003099 break;
3100 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003101 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003102 break;
3103 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003104 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003105 break;
3106 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003107 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003108 return LY_EVALID;
3109 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003110 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003111 /* finalize parent pointers to the reallocated items */
3112 LY_ARRAY_FOR(notif->groupings, u) {
3113 LY_LIST_FOR(notif->groupings[u].data, child) {
3114 child->parent = (struct lysp_node*)&notif->groupings[u];
3115 }
3116 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003117 return ret;
3118}
3119
Michal Vaskoea5abea2018-09-18 13:10:54 +02003120/**
3121 * @brief Parse the grouping statement.
3122 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003123 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003124 * @param[in,out] data Data to read from, always moved to currently handled character.
3125 * @param[in,out] groupings Groupings to add to.
3126 *
3127 * @return LY_ERR values.
3128 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003129LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003130parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003131{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003132 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003133 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003134 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 enum yang_keyword kw;
3136 struct lysp_grp *grp;
Radek Krejcie86bf772018-12-14 11:39:53 +01003137 struct lysp_node *child;
3138 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003139
Radek Krejci2c4e7172018-10-19 15:56:26 +02003140 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003141
3142 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003143 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003144 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003145 grp->nodetype = LYS_GROUPING;
3146 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003147
Radek Krejci6d6556c2018-11-08 09:37:45 +01003148 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003149 switch (kw) {
3150 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003151 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 +02003152 break;
3153 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003154 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 +02003155 break;
3156 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003157 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003158 break;
3159
3160 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003161 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01003162 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003163 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003164 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003165 break;
3166 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003167 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003168 break;
3169 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003170 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003171 break;
3172 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003174 break;
3175 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003176 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003177 break;
3178 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003179 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003180 break;
3181 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003182 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003183 break;
3184
3185 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003186 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003187 break;
3188 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003189 YANG_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003190 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003191 break;
3192 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003193 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003194 break;
3195 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003196 YANG_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003197 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003198 break;
3199 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003200 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003201 break;
3202 default:
Radek Krejci10113652018-11-14 16:56:50 +01003203 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003204 return LY_EVALID;
3205 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003206 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003207 /* finalize parent pointers to the reallocated items */
3208 LY_ARRAY_FOR(grp->groupings, u) {
3209 LY_LIST_FOR(grp->groupings[u].data, child) {
3210 child->parent = (struct lysp_node*)&grp->groupings[u];
3211 }
3212 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003213 return ret;
3214}
3215
Michal Vaskoea5abea2018-09-18 13:10:54 +02003216/**
3217 * @brief Parse the refine statement.
3218 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003219 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003220 * @param[in,out] data Data to read from, always moved to currently handled character.
3221 * @param[in,out] augments Augments to add to.
3222 *
3223 * @return LY_ERR values.
3224 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003225LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003226parse_augment(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003227{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003228 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003229 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003230 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003231 enum yang_keyword kw;
3232 struct lysp_augment *aug;
3233
Radek Krejci2c4e7172018-10-19 15:56:26 +02003234 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003235
3236 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003237 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003238 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003239 aug->nodetype = LYS_AUGMENT;
3240 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003241
Radek Krejci6d6556c2018-11-08 09:37:45 +01003242 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003243 switch (kw) {
3244 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003245 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 +02003246 break;
3247 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003248 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 +02003249 break;
3250 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003251 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 +02003252 break;
3253 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003254 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003255 break;
3256 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003257 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003258 break;
3259
3260 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003261 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01003262 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003263 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003264 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003265 break;
3266 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003267 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003268 break;
3269 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003270 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003271 break;
3272 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003273 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003274 break;
3275 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003276 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003277 break;
3278 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003279 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003280 break;
3281 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003282 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003283 break;
3284 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003285 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003286 break;
3287
3288 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003289 YANG_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003290 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003291 break;
3292 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003293 YANG_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003294 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003295 break;
3296 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003297 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003298 break;
3299 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003300 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003301 return LY_EVALID;
3302 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003303 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003304 return ret;
3305}
3306
Michal Vaskoea5abea2018-09-18 13:10:54 +02003307/**
3308 * @brief Parse the uses statement.
3309 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003310 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003311 * @param[in,out] data Data to read from, always moved to currently handled character.
3312 * @param[in,out] siblings Siblings to add to.
3313 *
3314 * @return LY_ERR values.
3315 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003316LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003317parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003318{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003319 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003320 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003321 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003322 enum yang_keyword kw;
3323 struct lysp_node *iter;
3324 struct lysp_node_uses *uses;
3325
3326 /* create structure */
3327 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003328 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003329 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003330 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003331
3332 /* insert into siblings */
3333 if (!*siblings) {
3334 *siblings = (struct lysp_node *)uses;
3335 } else {
3336 for (iter = *siblings; iter->next; iter = iter->next);
3337 iter->next = (struct lysp_node *)uses;
3338 }
3339
3340 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003341 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003342 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003343
3344 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003345 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003346 switch (kw) {
3347 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003348 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 +02003349 break;
3350 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003351 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 +02003352 break;
3353 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003354 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003355 break;
3356 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003357 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003358 break;
3359 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003360 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003361 break;
3362
3363 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003364 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003365 break;
3366 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003367 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003368 break;
3369 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003370 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003371 break;
3372 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003373 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003374 return LY_EVALID;
3375 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003376 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003377 return ret;
3378}
3379
Michal Vaskoea5abea2018-09-18 13:10:54 +02003380/**
3381 * @brief Parse the case statement.
3382 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003383 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003384 * @param[in,out] data Data to read from, always moved to currently handled character.
3385 * @param[in,out] siblings Siblings to add to.
3386 *
3387 * @return LY_ERR values.
3388 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003389LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003390parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003391{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003392 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003393 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003394 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003395 enum yang_keyword kw;
3396 struct lysp_node *iter;
3397 struct lysp_node_case *cas;
3398
3399 /* create structure */
3400 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003401 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003402 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003403 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003404
3405 /* insert into siblings */
3406 if (!*siblings) {
3407 *siblings = (struct lysp_node *)cas;
3408 } else {
3409 for (iter = *siblings; iter->next; iter = iter->next);
3410 iter->next = (struct lysp_node *)cas;
3411 }
3412
3413 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003414 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003415 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003416
3417 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003418 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003419 switch (kw) {
3420 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003421 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 +02003422 break;
3423 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003424 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 +02003425 break;
3426 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003427 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 +02003428 break;
3429 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003430 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003431 break;
3432 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003433 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003434 break;
3435
3436 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003437 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003438 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003439 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003440 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003441 break;
3442 case YANG_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003443 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003444 break;
3445 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003446 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003447 break;
3448 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003449 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003450 break;
3451 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003452 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003453 break;
3454 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003455 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003456 break;
3457 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003458 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003459 break;
3460 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003461 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003462 break;
3463 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003464 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003465 return LY_EVALID;
3466 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003467 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003468 return ret;
3469}
3470
Michal Vaskoea5abea2018-09-18 13:10:54 +02003471/**
3472 * @brief Parse the choice statement.
3473 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003474 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003475 * @param[in,out] data Data to read from, always moved to currently handled character.
3476 * @param[in,out] siblings Siblings to add to.
3477 *
3478 * @return LY_ERR values.
3479 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003480LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003481parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003482{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003483 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003484 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003485 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003486 enum yang_keyword kw;
3487 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003488 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003489
3490 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003491 choice = calloc(1, sizeof *choice);
3492 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3493 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003494 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003495
3496 /* insert into siblings */
3497 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003498 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003499 } else {
3500 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003501 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003502 }
3503
3504 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003505 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003506 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003507
3508 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003509 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003510 switch (kw) {
3511 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003512 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003513 break;
3514 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003515 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 +02003516 break;
3517 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003518 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 +02003519 break;
3520 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003521 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003522 break;
3523 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003524 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 +02003525 break;
3526 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003527 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003528 break;
3529 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003530 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003531 break;
3532 case YANG_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003533 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 +02003534 break;
3535
3536 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003537 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003538 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003539 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003540 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003541 break;
3542 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003543 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003544 break;
3545 case YANG_CHOICE:
Radek Krejciceaf2122019-01-02 15:03:26 +01003546 YANG_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003547 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003548 break;
3549 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003550 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003551 break;
3552 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003553 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003554 break;
3555 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003556 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003557 break;
3558 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003559 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003560 break;
3561 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003562 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563 break;
3564 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003565 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003566 return LY_EVALID;
3567 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003568 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003569 LY_CHECK_RET(ret);
3570checks:
3571 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
3572 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
3573 return LY_EVALID;
3574 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003575 return ret;
3576}
3577
Michal Vaskoea5abea2018-09-18 13:10:54 +02003578/**
3579 * @brief Parse the container statement.
3580 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003581 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003582 * @param[in,out] data Data to read from, always moved to currently handled character.
3583 * @param[in,out] siblings Siblings to add to.
3584 *
3585 * @return LY_ERR values.
3586 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003587LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003588parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003589{
3590 LY_ERR ret = 0;
3591 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003592 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003593 enum yang_keyword kw;
3594 struct lysp_node *iter;
3595 struct lysp_node_container *cont;
Radek Krejcie86bf772018-12-14 11:39:53 +01003596 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003597
3598 /* create structure */
3599 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003600 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003601 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003602 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003603
3604 /* insert into siblings */
3605 if (!*siblings) {
3606 *siblings = (struct lysp_node *)cont;
3607 } else {
3608 for (iter = *siblings; iter->next; iter = iter->next);
3609 iter->next = (struct lysp_node *)cont;
3610 }
3611
3612 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003613 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003614 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003615
3616 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003617 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003618 switch (kw) {
3619 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003620 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003621 break;
3622 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003623 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 +02003624 break;
3625 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003626 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 +02003627 break;
3628 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003629 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 +02003630 break;
3631 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003632 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003633 break;
3634 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003635 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003636 break;
3637 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003638 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 +02003639 break;
3640
3641 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003642 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003643 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003644 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003645 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003646 break;
3647 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003648 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003649 break;
3650 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003651 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003652 break;
3653 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003654 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003655 break;
3656 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003657 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003658 break;
3659 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003660 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003661 break;
3662 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003663 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003664 break;
3665
3666 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003667 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003668 break;
3669 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003670 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003671 break;
3672 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003673 YANG_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003674 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003675 break;
3676 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003677 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003678 break;
3679 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003680 YANG_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003681 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003682 break;
3683 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003684 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003685 break;
3686 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003687 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003688 return LY_EVALID;
3689 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003690 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003691 /* finalize parent pointers to the reallocated items */
3692 LY_ARRAY_FOR(cont->groupings, u) {
3693 LY_LIST_FOR(cont->groupings[u].data, iter) {
3694 iter->parent = (struct lysp_node*)&cont->groupings[u];
3695 }
3696 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003697 return ret;
3698}
3699
Michal Vaskoea5abea2018-09-18 13:10:54 +02003700/**
3701 * @brief Parse the list statement.
3702 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003703 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003704 * @param[in,out] data Data to read from, always moved to currently handled character.
3705 * @param[in,out] siblings Siblings to add to.
3706 *
3707 * @return LY_ERR values.
3708 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003709LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003710parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003711{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003712 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003713 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003714 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003715 enum yang_keyword kw;
3716 struct lysp_node *iter;
3717 struct lysp_node_list *list;
Radek Krejcie86bf772018-12-14 11:39:53 +01003718 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003719
3720 /* create structure */
3721 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003722 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003723 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003724 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725
3726 /* insert into siblings */
3727 if (!*siblings) {
3728 *siblings = (struct lysp_node *)list;
3729 } else {
3730 for (iter = *siblings; iter->next; iter = iter->next);
3731 iter->next = (struct lysp_node *)list;
3732 }
3733
3734 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003735 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003736 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003737
3738 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003739 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003740 switch (kw) {
3741 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003742 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003743 break;
3744 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003745 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 +02003746 break;
3747 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003748 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 +02003749 break;
3750 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003751 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 +02003752 break;
3753 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003754 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003755 break;
3756 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003757 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003758 break;
3759 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003760 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 +02003761 break;
3762 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003763 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003764 break;
3765 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003766 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003767 break;
3768 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003769 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003770 break;
3771 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003772 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 +02003773 break;
3774
3775 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003776 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003777 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003778 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003779 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003780 break;
3781 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003782 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003783 break;
3784 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003785 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003786 break;
3787 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003788 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003789 break;
3790 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003791 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003792 break;
3793 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003794 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003795 break;
3796 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003797 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003798 break;
3799
3800 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003801 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003802 break;
3803 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003804 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003805 break;
3806 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003807 YANG_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003808 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003809 break;
3810 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003811 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003812 break;
3813 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003814 YANG_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003815 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003816 break;
3817 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003818 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003819 break;
3820 default:
Radek Krejci10113652018-11-14 16:56:50 +01003821 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003822 return LY_EVALID;
3823 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003824 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003825 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01003826 /* finalize parent pointers to the reallocated items */
3827 LY_ARRAY_FOR(list->groupings, u) {
3828 LY_LIST_FOR(list->groupings[u].data, iter) {
3829 iter->parent = (struct lysp_node*)&list->groupings[u];
3830 }
3831 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003832checks:
3833 if (list->max && list->min > list->max) {
3834 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
3835 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3836 list->min, list->max);
3837 return LY_EVALID;
3838 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003839
3840 return ret;
3841}
3842
Michal Vaskoea5abea2018-09-18 13:10:54 +02003843/**
3844 * @brief Parse the yin-element statement.
3845 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003846 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003847 * @param[in,out] data Data to read from, always moved to currently handled character.
3848 * @param[in,out] flags Flags to write to.
3849 * @param[in,out] exts Extension instances to add to.
3850 *
3851 * @return LY_ERR values.
3852 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003853static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003854parse_yinelement(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003855{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003856 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003858 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003859 enum yang_keyword kw;
3860
3861 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003862 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003863 return LY_EVALID;
3864 }
3865
3866 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003867 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003868
3869 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3870 *flags |= LYS_YINELEM_TRUE;
3871 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3872 *flags |= LYS_YINELEM_FALSE;
3873 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003874 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875 free(buf);
3876 return LY_EVALID;
3877 }
3878 free(buf);
3879
Radek Krejci6d6556c2018-11-08 09:37:45 +01003880 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003881 switch (kw) {
3882 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003883 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3884 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003885 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003886 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003887 return LY_EVALID;
3888 }
3889 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003890 return ret;
3891}
3892
Michal Vaskoea5abea2018-09-18 13:10:54 +02003893/**
3894 * @brief Parse the yin-element statement.
3895 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003896 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003897 * @param[in,out] data Data to read from, always moved to currently handled character.
3898 * @param[in,out] argument Value to write to.
3899 * @param[in,out] flags Flags to write to.
3900 * @param[in,out] exts Extension instances to add to.
3901 *
3902 * @return LY_ERR values.
3903 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003904static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003905parse_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 +02003906{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003907 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003909 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003910 enum yang_keyword kw;
3911
3912 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003913 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003914 return LY_EVALID;
3915 }
3916
3917 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003918 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003919 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003920
Radek Krejci6d6556c2018-11-08 09:37:45 +01003921 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 switch (kw) {
3923 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003924 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003925 break;
3926 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003927 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003928 break;
3929 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003930 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003931 return LY_EVALID;
3932 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003933 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003934 return ret;
3935}
3936
Michal Vaskoea5abea2018-09-18 13:10:54 +02003937/**
3938 * @brief Parse the extension 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] extensions Extensions to add to.
3943 *
3944 * @return LY_ERR values.
3945 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003946static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003947parse_extension(struct lys_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003948{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003949 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003950 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003951 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003952 enum yang_keyword kw;
3953 struct lysp_ext *ex;
3954
Radek Krejci2c4e7172018-10-19 15:56:26 +02003955 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003956
3957 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003958 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003959 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003960
Radek Krejci6d6556c2018-11-08 09:37:45 +01003961 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003962 switch (kw) {
3963 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003964 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 +02003965 break;
3966 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003967 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 +02003968 break;
3969 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003970 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003971 break;
3972 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003973 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003974 break;
3975 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003976 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003977 break;
3978 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003979 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003980 return LY_EVALID;
3981 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003982 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003983 return ret;
3984}
3985
Michal Vaskoea5abea2018-09-18 13:10:54 +02003986/**
3987 * @brief Parse the deviate statement.
3988 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003989 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003990 * @param[in,out] data Data to read from, always moved to currently handled character.
3991 * @param[in,out] deviates Deviates to add to.
3992 *
3993 * @return LY_ERR values.
3994 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003995LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003996parse_deviate(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003997{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003998 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003999 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004000 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004001 enum yang_keyword kw;
4002 struct lysp_deviate *iter, *d;
4003 struct lysp_deviate_add *d_add = NULL;
4004 struct lysp_deviate_rpl *d_rpl = NULL;
4005 struct lysp_deviate_del *d_del = NULL;
4006 const char **d_units, ***d_uniques, ***d_dflts;
4007 struct lysp_restr **d_musts;
4008 uint16_t *d_flags;
4009 uint32_t *d_min, *d_max;
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));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004013
4014 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4015 dev_mod = LYS_DEV_NOT_SUPPORTED;
4016 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4017 dev_mod = LYS_DEV_ADD;
4018 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4019 dev_mod = LYS_DEV_REPLACE;
4020 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4021 dev_mod = LYS_DEV_DELETE;
4022 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004023 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004024 free(buf);
4025 return LY_EVALID;
4026 }
4027 free(buf);
4028
4029 /* create structure */
4030 switch (dev_mod) {
4031 case LYS_DEV_NOT_SUPPORTED:
4032 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004033 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004034 break;
4035 case LYS_DEV_ADD:
4036 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004037 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004038 d = (struct lysp_deviate *)d_add;
4039 d_units = &d_add->units;
4040 d_uniques = &d_add->uniques;
4041 d_dflts = &d_add->dflts;
4042 d_musts = &d_add->musts;
4043 d_flags = &d_add->flags;
4044 d_min = &d_add->min;
4045 d_max = &d_add->max;
4046 break;
4047 case LYS_DEV_REPLACE:
4048 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004049 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004050 d = (struct lysp_deviate *)d_rpl;
4051 d_units = &d_rpl->units;
4052 d_flags = &d_rpl->flags;
4053 d_min = &d_rpl->min;
4054 d_max = &d_rpl->max;
4055 break;
4056 case LYS_DEV_DELETE:
4057 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004058 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004059 d = (struct lysp_deviate *)d_del;
4060 d_units = &d_del->units;
4061 d_uniques = &d_del->uniques;
4062 d_dflts = &d_del->dflts;
4063 d_musts = &d_del->musts;
4064 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004065 break;
4066 default:
4067 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004068 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004069 }
4070 d->mod = dev_mod;
4071
4072 /* insert into siblings */
4073 if (!*deviates) {
4074 *deviates = d;
4075 } else {
4076 for (iter = *deviates; iter->next; iter = iter->next);
4077 iter->next = d;
4078 }
4079
Radek Krejci6d6556c2018-11-08 09:37:45 +01004080 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004081 switch (kw) {
4082 case YANG_CONFIG:
4083 switch (dev_mod) {
4084 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004085 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004086 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004087 return LY_EVALID;
4088 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004089 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004090 break;
4091 }
4092 break;
4093 case YANG_DEFAULT:
4094 switch (dev_mod) {
4095 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004096 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004097 return LY_EVALID;
4098 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004099 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 +02004100 break;
4101 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004102 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 +02004103 break;
4104 }
4105 break;
4106 case YANG_MANDATORY:
4107 switch (dev_mod) {
4108 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004109 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004110 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004111 return LY_EVALID;
4112 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004113 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004114 break;
4115 }
4116 break;
4117 case YANG_MAX_ELEMENTS:
4118 switch (dev_mod) {
4119 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004120 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004121 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004122 return LY_EVALID;
4123 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004124 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004125 break;
4126 }
4127 break;
4128 case YANG_MIN_ELEMENTS:
4129 switch (dev_mod) {
4130 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004131 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004132 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004133 return LY_EVALID;
4134 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004135 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004136 break;
4137 }
4138 break;
4139 case YANG_MUST:
4140 switch (dev_mod) {
4141 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004142 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004143 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004144 return LY_EVALID;
4145 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004146 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004147 break;
4148 }
4149 break;
4150 case YANG_TYPE:
4151 switch (dev_mod) {
4152 case LYS_DEV_NOT_SUPPORTED:
4153 case LYS_DEV_ADD:
4154 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004155 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004156 return LY_EVALID;
4157 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004158 if (d_rpl->type) {
4159 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4160 return LY_EVALID;
4161 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004162 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004163 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004164 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004165 break;
4166 }
4167 break;
4168 case YANG_UNIQUE:
4169 switch (dev_mod) {
4170 case LYS_DEV_NOT_SUPPORTED:
4171 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004172 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004173 return LY_EVALID;
4174 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004175 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 +02004176 break;
4177 }
4178 break;
4179 case YANG_UNITS:
4180 switch (dev_mod) {
4181 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004182 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004183 return LY_EVALID;
4184 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004185 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 +02004186 break;
4187 }
4188 break;
4189 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004190 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004191 break;
4192 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004193 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004194 return LY_EVALID;
4195 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004196 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004197 return ret;
4198}
4199
Michal Vaskoea5abea2018-09-18 13:10:54 +02004200/**
4201 * @brief Parse the deviation statement.
4202 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004203 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004204 * @param[in,out] data Data to read from, always moved to currently handled character.
4205 * @param[in,out] deviations Deviations to add to.
4206 *
4207 * @return LY_ERR values.
4208 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004209LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004210parse_deviation(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004211{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004212 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004213 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004214 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004215 enum yang_keyword kw;
4216 struct lysp_deviation *dev;
4217
Radek Krejci2c4e7172018-10-19 15:56:26 +02004218 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004219
4220 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004221 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004222 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004223
Radek Krejci6d6556c2018-11-08 09:37:45 +01004224 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004225 switch (kw) {
4226 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004227 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 +02004228 break;
4229 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004230 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004231 break;
4232 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004233 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 +02004234 break;
4235 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004236 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004237 break;
4238 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004239 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004240 return LY_EVALID;
4241 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004242 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004243 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004244checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004245 /* mandatory substatements */
4246 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004247 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004248 return LY_EVALID;
4249 }
4250
4251 return ret;
4252}
4253
Michal Vaskoea5abea2018-09-18 13:10:54 +02004254/**
4255 * @brief Parse the feature statement.
4256 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004257 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004258 * @param[in,out] data Data to read from, always moved to currently handled character.
4259 * @param[in,out] features Features to add to.
4260 *
4261 * @return LY_ERR values.
4262 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004263LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004264parse_feature(struct lys_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004265{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004266 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004267 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004268 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004269 enum yang_keyword kw;
4270 struct lysp_feature *feat;
4271
Radek Krejci2c4e7172018-10-19 15:56:26 +02004272 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004273
4274 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004275 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004276 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004277
Radek Krejci6d6556c2018-11-08 09:37:45 +01004278 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004279 switch (kw) {
4280 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004281 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 +02004282 break;
4283 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004284 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 +02004285 break;
4286 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004287 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 +02004288 break;
4289 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004290 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004291 break;
4292 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004293 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004294 break;
4295 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004296 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004297 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004298 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004299 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004300 return ret;
4301}
4302
Michal Vaskoea5abea2018-09-18 13:10:54 +02004303/**
4304 * @brief Parse the identity statement.
4305 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004306 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004307 * @param[in,out] data Data to read from, always moved to currently handled character.
4308 * @param[in,out] identities Identities to add to.
4309 *
4310 * @return LY_ERR values.
4311 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004312LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004313parse_identity(struct lys_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004314{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004315 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004317 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004318 enum yang_keyword kw;
4319 struct lysp_ident *ident;
4320
Radek Krejci2c4e7172018-10-19 15:56:26 +02004321 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004322
4323 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004324 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004325 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004326
Radek Krejci6d6556c2018-11-08 09:37:45 +01004327 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004328 switch (kw) {
4329 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004330 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 +02004331 break;
4332 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01004333 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004334 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 +02004335 break;
4336 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004337 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004338 break;
4339 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004340 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004341 break;
4342 case YANG_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004343 if (ident->bases && ctx->mod_version < 2) {
Radek Krejci10113652018-11-14 16:56:50 +01004344 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4345 return LY_EVALID;
4346 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004347 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 +02004348 break;
4349 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004350 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004351 break;
4352 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004353 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004354 return LY_EVALID;
4355 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004356 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004357 return ret;
4358}
4359
Michal Vaskoea5abea2018-09-18 13:10:54 +02004360/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004361 * @brief Finalize some of the (sub)module structure after parsing.
4362 *
4363 * Update parent pointers in the nodes inside grouping/RPC/Notification, which could be reallocated.
4364 *
4365 * @param[in] mod Parsed module to be updated.
4366 * @return LY_ERR value (currently only LY_SUCCESS, but it can change in future).
4367 */
4368static LY_ERR
4369parse_sub_module_finalize(struct lysp_module *mod)
4370{
4371 unsigned int u;
4372 struct lysp_node *child;
4373
4374 /* finalize parent pointers to the reallocated items */
4375 LY_ARRAY_FOR(mod->groupings, u) {
4376 LY_LIST_FOR(mod->groupings[u].data, child) {
4377 child->parent = (struct lysp_node*)&mod->groupings[u];
4378 }
4379 }
4380
4381 /* TODO the same finalization for rpcs and notifications, do also in the relevant nodes */
4382
4383 return LY_SUCCESS;
4384}
4385
4386/**
4387 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004388 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004389 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004390 * @param[in,out] data Data to read from, always moved to currently handled character.
4391 * @param[in,out] mod Module to write to.
4392 *
4393 * @return LY_ERR values.
4394 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004395LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004396parse_module(struct lys_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004397{
4398 LY_ERR ret = 0;
4399 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004400 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004401 enum yang_keyword kw, prev_kw = 0;
4402 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004403 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004404
4405 /* (sub)module name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004406 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004407 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004408
Radek Krejci6d6556c2018-11-08 09:37:45 +01004409 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004410
Radek Krejcie3846472018-10-15 15:24:51 +02004411#define CHECK_ORDER(SECTION) \
4412 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4413
Michal Vasko7fbc8162018-09-17 10:35:16 +02004414 switch (kw) {
4415 /* module header */
4416 case YANG_NAMESPACE:
4417 case YANG_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004418 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4419 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004420 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004421 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422 break;
4423 /* linkage */
4424 case YANG_INCLUDE:
4425 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004426 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004427 break;
4428 /* meta */
4429 case YANG_ORGANIZATION:
4430 case YANG_CONTACT:
4431 case YANG_DESCRIPTION:
4432 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004433 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004434 break;
4435
4436 /* revision */
4437 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004438 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004439 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004440 /* body */
4441 case YANG_ANYDATA:
4442 case YANG_ANYXML:
4443 case YANG_AUGMENT:
4444 case YANG_CHOICE:
4445 case YANG_CONTAINER:
4446 case YANG_DEVIATION:
4447 case YANG_EXTENSION:
4448 case YANG_FEATURE:
4449 case YANG_GROUPING:
4450 case YANG_IDENTITY:
4451 case YANG_LEAF:
4452 case YANG_LEAF_LIST:
4453 case YANG_LIST:
4454 case YANG_NOTIFICATION:
4455 case YANG_RPC:
4456 case YANG_TYPEDEF:
4457 case YANG_USES:
4458 case YANG_CUSTOM:
4459 mod_stmt = Y_MOD_BODY;
4460 break;
4461 default:
4462 /* error handled in the next switch */
4463 break;
4464 }
Radek Krejcie3846472018-10-15 15:24:51 +02004465#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004466
Radek Krejcie3846472018-10-15 15:24:51 +02004467 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004468 switch (kw) {
4469 /* module header */
4470 case YANG_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004471 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4472 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004473 break;
4474 case YANG_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004475 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 +02004476 break;
4477 case YANG_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004478 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 +02004479 break;
4480
4481 /* linkage */
4482 case YANG_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004483 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004484 break;
4485 case YANG_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004486 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004487 break;
4488
4489 /* meta */
4490 case YANG_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004491 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 +02004492 break;
4493 case YANG_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004494 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 +02004495 break;
4496 case YANG_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004497 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 +02004498 break;
4499 case YANG_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004500 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 +02004501 break;
4502
4503 /* revision */
4504 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004505 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004506 break;
4507
4508 /* body */
4509 case YANG_ANYDATA:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004510 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004511 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004512 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004513 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004514 break;
4515 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004516 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004517 break;
4518 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004519 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004520 break;
4521 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004522 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004523 break;
4524 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004525 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004526 break;
4527 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004528 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004529 break;
4530 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004531 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004532 break;
4533
4534 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004535 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004536 break;
4537 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004538 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004539 break;
4540 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004541 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004542 break;
4543 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004544 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004545 break;
4546 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004547 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004548 break;
4549 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004550 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004551 break;
4552 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004553 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004554 break;
4555 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004556 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004557 break;
4558 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004559 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004560 break;
4561 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004562 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004563 break;
4564
4565 default:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004566 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004567 return LY_EVALID;
4568 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004569 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004570 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004571
Radek Krejci6d6556c2018-11-08 09:37:45 +01004572checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004573 /* finalize parent pointers to the reallocated items */
4574 LY_CHECK_RET(parse_sub_module_finalize(mod));
4575
Michal Vasko7fbc8162018-09-17 10:35:16 +02004576 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004577 if (!mod->mod->ns) {
4578 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
4579 return LY_EVALID;
4580 } else if (!mod->mod->prefix) {
4581 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
4582 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004583 }
4584
Radek Krejcie9e987e2018-10-31 12:50:27 +01004585 /* submodules share the namespace with the module names, so there must not be
4586 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004587 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4588 if (dup) {
4589 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
4590 return LY_EVALID;
4591 }
4592
4593 return ret;
4594}
4595
4596/**
4597 * @brief Parse submodule substatements.
4598 *
4599 * @param[in] ctx yang parser context for logging.
4600 * @param[in,out] data Data to read from, always moved to currently handled character.
4601 * @param[out] submod Parsed submodule structure.
4602 *
4603 * @return LY_ERR values.
4604 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004605LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004606parse_submodule(struct lys_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004607{
4608 LY_ERR ret = 0;
4609 char *buf, *word;
4610 size_t word_len;
4611 enum yang_keyword kw, prev_kw = 0;
4612 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4613 struct lysp_submodule *dup;
4614
4615 /* submodule name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004616 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004617 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4618
4619 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4620
4621#define CHECK_ORDER(SECTION) \
4622 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4623
4624 switch (kw) {
4625 /* module header */
4626 case YANG_BELONGS_TO:
4627 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4628 break;
4629 case YANG_YANG_VERSION:
4630 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4631 break;
4632 /* linkage */
4633 case YANG_INCLUDE:
4634 case YANG_IMPORT:
4635 CHECK_ORDER(Y_MOD_LINKAGE);
4636 break;
4637 /* meta */
4638 case YANG_ORGANIZATION:
4639 case YANG_CONTACT:
4640 case YANG_DESCRIPTION:
4641 case YANG_REFERENCE:
4642 CHECK_ORDER(Y_MOD_META);
4643 break;
4644
4645 /* revision */
4646 case YANG_REVISION:
4647 CHECK_ORDER(Y_MOD_REVISION);
4648 break;
4649 /* body */
4650 case YANG_ANYDATA:
4651 case YANG_ANYXML:
4652 case YANG_AUGMENT:
4653 case YANG_CHOICE:
4654 case YANG_CONTAINER:
4655 case YANG_DEVIATION:
4656 case YANG_EXTENSION:
4657 case YANG_FEATURE:
4658 case YANG_GROUPING:
4659 case YANG_IDENTITY:
4660 case YANG_LEAF:
4661 case YANG_LEAF_LIST:
4662 case YANG_LIST:
4663 case YANG_NOTIFICATION:
4664 case YANG_RPC:
4665 case YANG_TYPEDEF:
4666 case YANG_USES:
4667 case YANG_CUSTOM:
4668 mod_stmt = Y_MOD_BODY;
4669 break;
4670 default:
4671 /* error handled in the next switch */
4672 break;
4673 }
4674#undef CHECK_ORDER
4675
4676 prev_kw = kw;
4677 switch (kw) {
4678 /* module header */
4679 case YANG_YANG_VERSION:
4680 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4681 ctx->mod_version = submod->version;
4682 break;
4683 case YANG_BELONGS_TO:
4684 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4685 break;
4686
4687 /* linkage */
4688 case YANG_INCLUDE:
4689 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4690 break;
4691 case YANG_IMPORT:
4692 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4693 break;
4694
4695 /* meta */
4696 case YANG_ORGANIZATION:
4697 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4698 break;
4699 case YANG_CONTACT:
4700 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4701 break;
4702 case YANG_DESCRIPTION:
4703 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4704 break;
4705 case YANG_REFERENCE:
4706 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4707 break;
4708
4709 /* revision */
4710 case YANG_REVISION:
4711 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4712 break;
4713
4714 /* body */
4715 case YANG_ANYDATA:
4716 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
4717 /* fall through */
4718 case YANG_ANYXML:
4719 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4720 break;
4721 case YANG_CHOICE:
4722 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4723 break;
4724 case YANG_CONTAINER:
4725 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4726 break;
4727 case YANG_LEAF:
4728 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4729 break;
4730 case YANG_LEAF_LIST:
4731 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4732 break;
4733 case YANG_LIST:
4734 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4735 break;
4736 case YANG_USES:
4737 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4738 break;
4739
4740 case YANG_AUGMENT:
4741 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4742 break;
4743 case YANG_DEVIATION:
4744 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4745 break;
4746 case YANG_EXTENSION:
4747 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4748 break;
4749 case YANG_FEATURE:
4750 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4751 break;
4752 case YANG_GROUPING:
4753 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4754 break;
4755 case YANG_IDENTITY:
4756 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4757 break;
4758 case YANG_NOTIFICATION:
4759 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4760 break;
4761 case YANG_RPC:
4762 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4763 break;
4764 case YANG_TYPEDEF:
4765 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4766 break;
4767 case YANG_CUSTOM:
4768 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4769 break;
4770
4771 default:
4772 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
4773 return LY_EVALID;
4774 }
4775 }
4776 LY_CHECK_RET(ret);
4777
4778checks:
4779 /* finalize parent pointers to the reallocated items */
4780 LY_CHECK_RET(parse_sub_module_finalize((struct lysp_module*)submod));
4781
4782 /* mandatory substatements */
4783 if (!submod->belongsto) {
4784 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
4785 return LY_EVALID;
4786 }
4787
4788 /* submodules share the namespace with the module names, so there must not be
4789 * a submodule of the same name in the context, no need for revision matching */
4790 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4791 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
4792 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004793 return LY_EVALID;
4794 }
4795
Michal Vasko7fbc8162018-09-17 10:35:16 +02004796 return ret;
4797}
4798
Radek Krejcid4557c62018-09-17 11:42:09 +02004799LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004800yang_parse_submodule(struct lys_parser_ctx *context, const char *data, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004801{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004802 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004803 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004804 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004805 enum yang_keyword kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004806 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004807
4808 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004809 ret = get_keyword(context, &data, &kw, &word, &word_len);
4810 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004811
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004812 if (kw == YANG_MODULE) {
4813 LOGERR(context->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
4814 ret = LY_EINVAL;
4815 goto cleanup;
4816 } else if (kw != YANG_SUBMODULE) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004817 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004818 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004819 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004820 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004821 }
4822
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004823 mod_p = calloc(1, sizeof *mod_p);
4824 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4825 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004826
4827 /* substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004828 ret = parse_submodule(context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004829 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004830
4831 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004832 while(*data && isspace(*data)) {
4833 data++;
4834 }
4835 if (*data) {
4836 LOGVAL_YANG(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
4837 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004838 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004839 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004840 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004841
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004842 mod_p->parsing = 0;
4843 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004844
Radek Krejcibbe09a92018-11-08 09:36:54 +01004845cleanup:
4846 if (ret) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004847 lysp_submodule_free(context->ctx, mod_p);
4848 }
4849
4850 return ret;
4851}
4852
4853LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004854yang_parse_module(struct lys_parser_ctx *context, const char *data, struct lys_module *mod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004855{
4856 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004857 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004858 size_t word_len;
4859 enum yang_keyword kw;
4860 struct lysp_module *mod_p = NULL;
4861
4862 /* "module"/"submodule" */
4863 ret = get_keyword(context, &data, &kw, &word, &word_len);
4864 LY_CHECK_GOTO(ret, cleanup);
4865
4866 if (kw == YANG_SUBMODULE) {
4867 LOGERR(context->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
4868 ret = LY_EINVAL;
4869 goto cleanup;
4870 } else if (kw != YANG_MODULE) {
4871 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
4872 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004873 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004874 goto cleanup;
4875 }
4876
4877 mod_p = calloc(1, sizeof *mod_p);
4878 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4879 mod_p->mod = mod;
4880 mod_p->parsing = 1;
4881
4882 /* substatements */
4883 ret = parse_module(context, &data, mod_p);
4884 LY_CHECK_GOTO(ret, cleanup);
4885
4886 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004887 while(*data && isspace(*data)) {
4888 data++;
4889 }
4890 if (*data) {
4891 LOGVAL_YANG(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
4892 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004893 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004894 goto cleanup;
4895 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004896
4897 mod_p->parsing = 0;
4898 mod->parsed = mod_p;
4899
4900cleanup:
4901 if (ret) {
4902 lysp_module_free(mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004903 }
4904
Michal Vasko7fbc8162018-09-17 10:35:16 +02004905 return ret;
4906}