blob: bf1361c986787a1ab5f6b53aaff2826046927998 [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;
345 } else {
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 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200738 break;
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" */
960 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200961 case ':':
962 /* keyword is not actually a keyword, but prefix of an extension.
963 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
964 * and we will be checking the keyword (extension instance) itself */
965 prefix = 1;
966 MOVE_INPUT(ctx, data, 1);
967 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200968 case '{':
969 /* allowed only for input and output statements which can be without arguments */
970 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
971 break;
972 }
973 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200974 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200975 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200976 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
977 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200978 return LY_EVALID;
979 }
980 } else {
981 /* still can be an extension */
982 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200983extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200984 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200985 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
986 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200987 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200988 /* check character validity */
989 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200990 }
991 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200992 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200993 return LY_EVALID;
994 }
995
996 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200997 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200998 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200999 return LY_EVALID;
1000 }
1001
1002 *kw = YANG_CUSTOM;
1003 }
Radek Krejci626df482018-10-11 15:06:31 +02001004success:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001005 if (word_p) {
1006 *word_p = (char *)word_start;
1007 *word_len = *data - word_start;
1008 }
1009
1010 return LY_SUCCESS;
1011}
1012
Michal Vaskoea5abea2018-09-18 13:10:54 +02001013/**
1014 * @brief Parse extension instance substatements.
1015 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001016 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001017 * @param[in,out] data Data to read from, always moved to currently handled character.
1018 * @param[in] word Extension instance substatement name (keyword).
1019 * @param[in] word_len Extension instance substatement name length.
1020 * @param[in,out] child Children of this extension instance to add to.
1021 *
1022 * @return LY_ERR values.
1023 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001024static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001025parse_ext_substmt(struct lys_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001026 struct lysp_stmt **child)
1027{
1028 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001029 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001030 enum yang_keyword kw;
1031 struct lysp_stmt *stmt, *par_child;
1032
1033 stmt = calloc(1, sizeof *stmt);
1034 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
1035
Radek Krejcibb9b1982019-04-08 14:24:59 +02001036 /* insert into parent statements */
1037 if (!*child) {
1038 *child = stmt;
1039 } else {
1040 for (par_child = *child; par_child->next; par_child = par_child->next);
1041 par_child->next = stmt;
1042 }
1043
Radek Krejci44ceedc2018-10-02 15:54:31 +02001044 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001045
1046 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001047 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001048
Radek Krejci0ae092d2018-09-20 16:43:19 +02001049 if (word) {
1050 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001051 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001052 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001053 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001054 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001055 }
1056
Radek Krejci6d6556c2018-11-08 09:37:45 +01001057 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001058 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001059 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001060 return ret;
1061}
1062
Michal Vaskoea5abea2018-09-18 13:10:54 +02001063/**
1064 * @brief Parse extension instance.
1065 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001066 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001067 * @param[in,out] data Data to read from, always moved to currently handled character.
1068 * @param[in] ext_name Extension instance substatement name (keyword).
1069 * @param[in] ext_name_len Extension instance substatement name length.
1070 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1071 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1072 * @param[in,out] exts Extension instances to add to.
1073 *
1074 * @return LY_ERR values.
1075 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001076static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001077parse_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 +02001078 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1079{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001080 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001081 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001082 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001083 struct lysp_ext_instance *e;
1084 enum yang_keyword kw;
1085
Radek Krejci2c4e7172018-10-19 15:56:26 +02001086 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001087
1088 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001089 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001090 e->insubstmt = insubstmt;
1091 e->insubstmt_index = insubstmt_index;
1092
1093 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001094 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001095
Radek Krejci0ae092d2018-09-20 16:43:19 +02001096 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001097 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001098 }
1099
Radek Krejci6d6556c2018-11-08 09:37:45 +01001100 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001101 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001102 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001103 return ret;
1104}
1105
Michal Vaskoea5abea2018-09-18 13:10:54 +02001106/**
1107 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1108 * description, etc...
1109 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001110 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001111 * @param[in,out] data Data to read from, always moved to currently handled character.
1112 * @param[in] substmt Type of this substatement.
1113 * @param[in] substmt_index Index of this substatement.
1114 * @param[in,out] value Place to store the parsed value.
1115 * @param[in] arg Type of the YANG keyword argument (of the value).
1116 * @param[in,out] exts Extension instances to add to.
1117 *
1118 * @return LY_ERR values.
1119 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001120static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001121parse_text_field(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001122 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1123{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001124 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001125 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001126 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001127 enum yang_keyword kw;
1128
1129 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001130 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131 return LY_EVALID;
1132 }
1133
1134 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001135 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001136
1137 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001138 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001139
Radek Krejci6d6556c2018-11-08 09:37:45 +01001140 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001141 switch (kw) {
1142 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001143 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001144 break;
1145 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001146 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001147 return LY_EVALID;
1148 }
1149 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001150 return ret;
1151}
1152
Michal Vaskoea5abea2018-09-18 13:10:54 +02001153/**
1154 * @brief Parse the yang-version statement.
1155 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001156 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001157 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001158 * @param[out] version Storage for the parsed information.
1159 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001160 *
1161 * @return LY_ERR values.
1162 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001163static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001164parse_yangversion(struct lys_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001165{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001166 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001167 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001168 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001169 enum yang_keyword kw;
1170
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001171 if (*version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001172 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001173 return LY_EVALID;
1174 }
1175
1176 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001177 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001178
1179 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001180 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001181 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001182 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001183 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001184 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001185 free(buf);
1186 return LY_EVALID;
1187 }
1188 free(buf);
1189
Radek Krejci6d6556c2018-11-08 09:37:45 +01001190 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001191 switch (kw) {
1192 case YANG_CUSTOM:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001193 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001194 break;
1195 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001196 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001197 return LY_EVALID;
1198 }
1199 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001200 return ret;
1201}
1202
Michal Vaskoea5abea2018-09-18 13:10:54 +02001203/**
1204 * @brief Parse the belongs-to statement.
1205 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001206 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001207 * @param[in,out] data Data to read from, always moved to currently handled character.
1208 * @param[in,out] belongsto Place to store the parsed value.
1209 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1210 * @param[in,out] exts Extension instances to add to.
1211 *
1212 * @return LY_ERR values.
1213 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001214static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001215parse_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 +02001216{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001217 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001218 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001219 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001220 enum yang_keyword kw;
1221
1222 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001223 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001224 return LY_EVALID;
1225 }
1226
1227 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001228 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001229
Radek Krejci44ceedc2018-10-02 15:54:31 +02001230 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001231 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001232 switch (kw) {
1233 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001234 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001235 break;
1236 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001237 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001238 break;
1239 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001240 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001241 return LY_EVALID;
1242 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001243 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001244 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001245checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001246 /* mandatory substatements */
1247 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001248 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001249 return LY_EVALID;
1250 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001251 return ret;
1252}
1253
Michal Vaskoea5abea2018-09-18 13:10:54 +02001254/**
1255 * @brief Parse the revision-date statement.
1256 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001257 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001258 * @param[in,out] data Data to read from, always moved to currently handled character.
1259 * @param[in,out] rev Array to store the parsed value in.
1260 * @param[in,out] exts Extension instances to add to.
1261 *
1262 * @return LY_ERR values.
1263 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001264static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001265parse_revisiondate(struct lys_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001266{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001267 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001268 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001269 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001270 enum yang_keyword kw;
1271
1272 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001273 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001274 return LY_EVALID;
1275 }
1276
1277 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001278 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001279
1280 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001281 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001282 free(buf);
1283 return LY_EVALID;
1284 }
1285
1286 /* store value and spend buf if allocated */
1287 strncpy(rev, word, word_len);
1288 free(buf);
1289
Radek Krejci6d6556c2018-11-08 09:37:45 +01001290 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001291 switch (kw) {
1292 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001293 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001294 break;
1295 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001296 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001297 return LY_EVALID;
1298 }
1299 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001300 return ret;
1301}
1302
Michal Vaskoea5abea2018-09-18 13:10:54 +02001303/**
1304 * @brief Parse the include statement.
1305 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001306 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001307 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001308 * @param[in,out] data Data to read from, always moved to currently handled character.
1309 * @param[in,out] includes Parsed includes to add to.
1310 *
1311 * @return LY_ERR values.
1312 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001313static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001314parse_include(struct lys_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001315{
Radek Krejcid33273d2018-10-25 14:55:52 +02001316 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001317 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001318 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001319 enum yang_keyword kw;
1320 struct lysp_include *inc;
1321
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001322 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001323
1324 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001325 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001326
Radek Krejci086c7132018-10-26 15:29:04 +02001327 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1328
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001329 /* submodules share the namespace with the module names, so there must not be
1330 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001331 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001332 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1333 return LY_EVALID;
1334 }
1335
Radek Krejci6d6556c2018-11-08 09:37:45 +01001336 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001337 switch (kw) {
1338 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001339 YANG_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001340 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 +02001341 break;
1342 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001343 YANG_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001344 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 +02001345 break;
1346 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001347 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001348 break;
1349 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001350 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001351 break;
1352 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001353 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001354 return LY_EVALID;
1355 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001356 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001357 return ret;
1358}
1359
Michal Vaskoea5abea2018-09-18 13:10:54 +02001360/**
1361 * @brief Parse the import statement.
1362 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001363 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001364 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001365 * @param[in,out] data Data to read from, always moved to currently handled character.
1366 * @param[in,out] imports Parsed imports to add to.
1367 *
1368 * @return LY_ERR values.
1369 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001370static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001371parse_import(struct lys_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001372{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001373 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001374 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001375 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001376 enum yang_keyword kw;
1377 struct lysp_import *imp;
1378
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001379 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001380
1381 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001382 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001383 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001384
Radek Krejci6d6556c2018-11-08 09:37:45 +01001385 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001386 switch (kw) {
1387 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001388 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 +01001389 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001390 break;
1391 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001392 YANG_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001393 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 +02001394 break;
1395 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001396 YANG_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001397 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 +02001398 break;
1399 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001400 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001401 break;
1402 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001403 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001404 break;
1405 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001406 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001407 return LY_EVALID;
1408 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001409 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001410 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001411checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001412 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001413 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001414
1415 return ret;
1416}
1417
Michal Vaskoea5abea2018-09-18 13:10:54 +02001418/**
1419 * @brief Parse the revision statement.
1420 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001421 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001422 * @param[in,out] data Data to read from, always moved to currently handled character.
1423 * @param[in,out] revs Parsed revisions to add to.
1424 *
1425 * @return LY_ERR values.
1426 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001427static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001428parse_revision(struct lys_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001429{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001430 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001431 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001432 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001433 enum yang_keyword kw;
1434 struct lysp_revision *rev;
1435
Radek Krejci2c4e7172018-10-19 15:56:26 +02001436 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001437
1438 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001439 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001440
1441 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001442 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001443 return LY_EVALID;
1444 }
1445
Radek Krejcib7db73a2018-10-24 14:18:40 +02001446 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001447 free(buf);
1448
Radek Krejci6d6556c2018-11-08 09:37:45 +01001449 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001450 switch (kw) {
1451 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001452 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 +02001453 break;
1454 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001455 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 +02001456 break;
1457 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001458 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001459 break;
1460 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001461 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001462 return LY_EVALID;
1463 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001464 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001465 return ret;
1466}
1467
Michal Vaskoea5abea2018-09-18 13:10:54 +02001468/**
1469 * @brief Parse a generic text field that can have more instances such as base.
1470 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001471 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001472 * @param[in,out] data Data to read from, always moved to currently handled character.
1473 * @param[in] substmt Type of this substatement.
1474 * @param[in,out] texts Parsed values to add to.
1475 * @param[in] arg Type of the expected argument.
1476 * @param[in,out] exts Extension instances to add to.
1477 *
1478 * @return LY_ERR values.
1479 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001480static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001481parse_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 +02001482 struct lysp_ext_instance **exts)
1483{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001484 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001485 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001486 const char **item;
1487 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001488 enum yang_keyword kw;
1489
1490 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001491 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001492
1493 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001494 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001495
Radek Krejci151a5b72018-10-19 14:21:44 +02001496 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001497 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001498 switch (kw) {
1499 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001500 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001501 break;
1502 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001503 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001504 return LY_EVALID;
1505 }
1506 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001507 return ret;
1508}
1509
Michal Vaskoea5abea2018-09-18 13:10:54 +02001510/**
1511 * @brief Parse the config statement.
1512 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001513 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001514 * @param[in,out] data Data to read from, always moved to currently handled character.
1515 * @param[in,out] flags Flags to add to.
1516 * @param[in,out] exts Extension instances to add to.
1517 *
1518 * @return LY_ERR values.
1519 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001520static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001521parse_config(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001522{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001523 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001524 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001525 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001526 enum yang_keyword kw;
1527
1528 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001529 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001530 return LY_EVALID;
1531 }
1532
1533 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001534 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001535
1536 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1537 *flags |= LYS_CONFIG_W;
1538 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1539 *flags |= LYS_CONFIG_R;
1540 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001541 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001542 free(buf);
1543 return LY_EVALID;
1544 }
1545 free(buf);
1546
Radek Krejci6d6556c2018-11-08 09:37:45 +01001547 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001548 switch (kw) {
1549 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001550 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001551 break;
1552 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001553 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001554 return LY_EVALID;
1555 }
1556 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001557 return ret;
1558}
1559
Michal Vaskoea5abea2018-09-18 13:10:54 +02001560/**
1561 * @brief Parse the mandatory statement.
1562 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001563 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001564 * @param[in,out] data Data to read from, always moved to currently handled character.
1565 * @param[in,out] flags Flags to add to.
1566 * @param[in,out] exts Extension instances to add to.
1567 *
1568 * @return LY_ERR values.
1569 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001570static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001571parse_mandatory(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001572{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001573 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001574 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001575 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001576 enum yang_keyword kw;
1577
1578 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001579 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001580 return LY_EVALID;
1581 }
1582
1583 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001584 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001585
1586 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1587 *flags |= LYS_MAND_TRUE;
1588 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1589 *flags |= LYS_MAND_FALSE;
1590 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001591 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001592 free(buf);
1593 return LY_EVALID;
1594 }
1595 free(buf);
1596
Radek Krejci6d6556c2018-11-08 09:37:45 +01001597 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001598 switch (kw) {
1599 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001600 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001601 break;
1602 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001603 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001604 return LY_EVALID;
1605 }
1606 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001607 return ret;
1608}
1609
Michal Vaskoea5abea2018-09-18 13:10:54 +02001610/**
1611 * @brief Parse a restriction such as range or length.
1612 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001613 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001614 * @param[in,out] data Data to read from, always moved to currently handled character.
1615 * @param[in] restr_kw Type of this particular restriction.
1616 * @param[in,out] exts Extension instances to add to.
1617 *
1618 * @return LY_ERR values.
1619 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001620static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001621parse_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 +02001622{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001623 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001624 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001625 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001626 enum yang_keyword kw;
1627
1628 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001629 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001630
Radek Krejci44ceedc2018-10-02 15:54:31 +02001631 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001632 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001633 switch (kw) {
1634 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001635 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 +02001636 break;
1637 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001638 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 +02001639 break;
1640 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001641 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 +02001642 break;
1643 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001644 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 +02001645 break;
1646 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001647 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001648 break;
1649 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001650 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001651 return LY_EVALID;
1652 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001653 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001654 return ret;
1655}
1656
Michal Vaskoea5abea2018-09-18 13:10:54 +02001657/**
1658 * @brief Parse a restriction that can have more instances such as must.
1659 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001660 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001661 * @param[in,out] data Data to read from, always moved to currently handled character.
1662 * @param[in] restr_kw Type of this particular restriction.
1663 * @param[in,out] restrs Restrictions to add to.
1664 *
1665 * @return LY_ERR values.
1666 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001667static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001668parse_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 +02001669{
1670 struct lysp_restr *restr;
1671
Radek Krejci2c4e7172018-10-19 15:56:26 +02001672 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001673 return parse_restr(ctx, data, restr_kw, restr);
1674}
1675
Michal Vaskoea5abea2018-09-18 13:10:54 +02001676/**
1677 * @brief Parse the status statement.
1678 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001679 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001680 * @param[in,out] data Data to read from, always moved to currently handled character.
1681 * @param[in,out] flags Flags to add to.
1682 * @param[in,out] exts Extension instances to add to.
1683 *
1684 * @return LY_ERR values.
1685 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001686static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001687parse_status(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001688{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001689 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001690 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001691 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001692 enum yang_keyword kw;
1693
1694 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001695 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001696 return LY_EVALID;
1697 }
1698
1699 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001700 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001701
1702 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1703 *flags |= LYS_STATUS_CURR;
1704 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1705 *flags |= LYS_STATUS_DEPRC;
1706 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1707 *flags |= LYS_STATUS_OBSLT;
1708 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001709 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001710 free(buf);
1711 return LY_EVALID;
1712 }
1713 free(buf);
1714
Radek Krejci6d6556c2018-11-08 09:37:45 +01001715 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001716 switch (kw) {
1717 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001718 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001719 break;
1720 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001721 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001722 return LY_EVALID;
1723 }
1724 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001725 return ret;
1726}
1727
Michal Vaskoea5abea2018-09-18 13:10:54 +02001728/**
1729 * @brief Parse the when statement.
1730 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001731 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001732 * @param[in,out] data Data to read from, always moved to currently handled character.
1733 * @param[in,out] when_p When pointer to parse to.
1734 *
1735 * @return LY_ERR values.
1736 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001737static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001738parse_when(struct lys_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001739{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001740 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001741 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001742 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001743 enum yang_keyword kw;
1744 struct lysp_when *when;
1745
1746 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001747 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001748 return LY_EVALID;
1749 }
1750
1751 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001752 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001753 *when_p = when;
1754
1755 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001756 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001757 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001758
Radek Krejci6d6556c2018-11-08 09:37:45 +01001759 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001760 switch (kw) {
1761 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001762 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 +02001763 break;
1764 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001765 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 +02001766 break;
1767 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001768 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001769 break;
1770 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001771 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001772 return LY_EVALID;
1773 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001774 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001775 return ret;
1776}
1777
Michal Vaskoea5abea2018-09-18 13:10:54 +02001778/**
1779 * @brief Parse the anydata or anyxml statement.
1780 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001781 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001782 * @param[in,out] data Data to read from, always moved to currently handled character.
1783 * @param[in] kw Type of this particular keyword.
1784 * @param[in,out] siblings Siblings to add to.
1785 *
1786 * @return LY_ERR values.
1787 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001788LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001789parse_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 +02001790{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001791 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001792 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001793 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001794 struct lysp_node *iter;
1795 struct lysp_node_anydata *any;
1796
1797 /* create structure */
1798 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001799 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001800 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001801 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001802
1803 /* insert into siblings */
1804 if (!*siblings) {
1805 *siblings = (struct lysp_node *)any;
1806 } else {
1807 for (iter = *siblings; iter->next; iter = iter->next);
1808 iter->next = (struct lysp_node *)any;
1809 }
1810
1811 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001812 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001813 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001814
1815 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001816 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001817 switch (kw) {
1818 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001819 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001820 break;
1821 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001822 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 +02001823 break;
1824 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001825 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 +02001826 break;
1827 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001828 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001829 break;
1830 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001831 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001832 break;
1833 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001834 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 +02001835 break;
1836 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001837 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001838 break;
1839 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001840 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001841 break;
1842 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001843 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001844 break;
1845 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001846 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001847 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001848 return LY_EVALID;
1849 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001850 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001851 return ret;
1852}
1853
Michal Vaskoea5abea2018-09-18 13:10:54 +02001854/**
1855 * @brief Parse the value or position statement. Substatement of type enum statement.
1856 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001857 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001858 * @param[in,out] data Data to read from, always moved to currently handled character.
1859 * @param[in] val_kw Type of this particular keyword.
1860 * @param[in,out] value Value to write to.
1861 * @param[in,out] flags Flags to write to.
1862 * @param[in,out] exts Extension instances to add to.
1863 *
1864 * @return LY_ERR values.
1865 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001866static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001867parse_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 +02001868 struct lysp_ext_instance **exts)
1869{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001870 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001871 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001872 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001873 long int num;
1874 unsigned long int unum;
1875 enum yang_keyword kw;
1876
1877 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001878 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001879 return LY_EVALID;
1880 }
1881 *flags |= LYS_SET_VALUE;
1882
1883 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001884 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001885
1886 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 +02001887 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001888 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001889 }
1890
1891 errno = 0;
1892 if (val_kw == YANG_VALUE) {
1893 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001894 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
1895 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1896 goto error;
1897 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001898 } else {
1899 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001900 if (unum > UINT64_C(4294967295)) {
1901 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1902 goto error;
1903 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001904 }
1905 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001906 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001907 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001908 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001909 }
1910 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001911 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001912 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001913 }
1914 if (val_kw == YANG_VALUE) {
1915 *value = num;
1916 } else {
1917 *value = unum;
1918 }
1919 free(buf);
1920
Radek Krejci6d6556c2018-11-08 09:37:45 +01001921 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001922 switch (kw) {
1923 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001924 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 +02001925 break;
1926 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001927 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001928 return LY_EVALID;
1929 }
1930 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001931 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001932
1933error:
1934 free(buf);
1935 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001936}
1937
Michal Vaskoea5abea2018-09-18 13:10:54 +02001938/**
1939 * @brief Parse the enum or bit statement. Substatement of type statement.
1940 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001941 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001942 * @param[in,out] data Data to read from, always moved to currently handled character.
1943 * @param[in] enum_kw Type of this particular keyword.
1944 * @param[in,out] enums Enums or bits to add to.
1945 *
1946 * @return LY_ERR values.
1947 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001948static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001949parse_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 +02001950{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001951 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001952 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001953 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001954 enum yang_keyword kw;
1955 struct lysp_type_enum *enm;
1956
Radek Krejci2c4e7172018-10-19 15:56:26 +02001957 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001958
1959 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001960 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 +01001961 if (enum_kw == YANG_ENUM) {
1962 if (!word_len) {
1963 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
1964 free(buf);
1965 return LY_EVALID;
1966 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
1967 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
1968 word_len, word);
1969 free(buf);
1970 return LY_EVALID;
1971 } else {
1972 for (u = 0; u < word_len; ++u) {
1973 if (iscntrl(word[u])) {
1974 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1975 word_len, word, u + 1);
1976 break;
1977 }
1978 }
1979 }
1980 } else { /* YANG_BIT */
1981
1982 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001983 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001984 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1985
Radek Krejci6d6556c2018-11-08 09:37:45 +01001986 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001987 switch (kw) {
1988 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001989 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 +02001990 break;
1991 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001992 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001993 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 +02001994 break;
1995 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001996 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 +02001997 break;
1998 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001999 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002000 break;
2001 case YANG_VALUE:
2002 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002003 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002004 break;
2005 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002006 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002007 break;
2008 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002009 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002010 return LY_EVALID;
2011 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002012 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002013 return ret;
2014}
2015
Michal Vaskoea5abea2018-09-18 13:10:54 +02002016/**
2017 * @brief Parse the fraction-digits statement. Substatement of type statement.
2018 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002019 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002020 * @param[in,out] data Data to read from, always moved to currently handled character.
2021 * @param[in,out] fracdig Value to write to.
2022 * @param[in,out] exts Extension instances to add to.
2023 *
2024 * @return LY_ERR values.
2025 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002026static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002027parse_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 +02002028{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002029 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002030 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002031 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002032 unsigned long int num;
2033 enum yang_keyword kw;
2034
2035 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002036 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002037 return LY_EVALID;
2038 }
2039
2040 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002041 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002042
2043 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002044 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002045 free(buf);
2046 return LY_EVALID;
2047 }
2048
2049 errno = 0;
2050 num = strtoul(word, &ptr, 10);
2051 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002052 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002053 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002054 free(buf);
2055 return LY_EVALID;
2056 }
2057 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002058 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002059 free(buf);
2060 return LY_EVALID;
2061 }
2062 *fracdig = num;
2063 free(buf);
2064
Radek Krejci6d6556c2018-11-08 09:37:45 +01002065 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002066 switch (kw) {
2067 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002068 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002069 break;
2070 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002071 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002072 return LY_EVALID;
2073 }
2074 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075 return ret;
2076}
2077
Michal Vaskoea5abea2018-09-18 13:10:54 +02002078/**
2079 * @brief Parse the require-instance statement. Substatement of type statement.
2080 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002081 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002082 * @param[in,out] data Data to read from, always moved to currently handled character.
2083 * @param[in,out] reqinst Value to write to.
2084 * @param[in,out] flags Flags to write to.
2085 * @param[in,out] exts Extension instances to add to.
2086 *
2087 * @return LY_ERR values.
2088 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002089static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002090parse_type_reqinstance(struct lys_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002091 struct lysp_ext_instance **exts)
2092{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002093 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002094 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002095 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002096 enum yang_keyword kw;
2097
2098 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002099 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002100 return LY_EVALID;
2101 }
2102 *flags |= LYS_SET_REQINST;
2103
2104 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002105 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002106
2107 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2108 *reqinst = 1;
2109 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002110 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002111 free(buf);
2112 return LY_EVALID;
2113 }
2114 free(buf);
2115
Radek Krejci6d6556c2018-11-08 09:37:45 +01002116 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002117 switch (kw) {
2118 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002119 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002120 break;
2121 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002122 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002123 return LY_EVALID;
2124 }
2125 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002126 return ret;
2127}
2128
Michal Vaskoea5abea2018-09-18 13:10:54 +02002129/**
2130 * @brief Parse the modifier statement. Substatement of type pattern statement.
2131 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002132 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002133 * @param[in,out] data Data to read from, always moved to currently handled character.
2134 * @param[in,out] pat Value to write to.
2135 * @param[in,out] exts Extension instances to add to.
2136 *
2137 * @return LY_ERR values.
2138 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002139static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002140parse_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 +02002141{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002142 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002143 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002144 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002145 enum yang_keyword kw;
2146
2147 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002148 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002149 return LY_EVALID;
2150 }
2151
2152 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002153 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002154
2155 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002156 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002157 free(buf);
2158 return LY_EVALID;
2159 }
2160 free(buf);
2161
2162 /* replace the value in the dictionary */
2163 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002164 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002165 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002166 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002167
2168 assert(buf[0] == 0x06);
2169 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002170 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002171
Radek Krejci6d6556c2018-11-08 09:37:45 +01002172 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002173 switch (kw) {
2174 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002175 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002176 break;
2177 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002178 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002179 return LY_EVALID;
2180 }
2181 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002182 return ret;
2183}
2184
Michal Vaskoea5abea2018-09-18 13:10:54 +02002185/**
2186 * @brief Parse the pattern statement. Substatement of type statement.
2187 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002188 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002189 * @param[in,out] data Data to read from, always moved to currently handled character.
2190 * @param[in,out] patterns Restrictions to add to.
2191 *
2192 * @return LY_ERR values.
2193 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002194static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002195parse_type_pattern(struct lys_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002196{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002197 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002198 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002199 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002200 enum yang_keyword kw;
2201 struct lysp_restr *restr;
2202
Radek Krejci2c4e7172018-10-19 15:56:26 +02002203 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002204
2205 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002206 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002207
2208 /* add special meaning first byte */
2209 if (buf) {
2210 buf = realloc(buf, word_len + 2);
2211 word = buf;
2212 } else {
2213 buf = malloc(word_len + 2);
2214 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002215 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002216 memmove(buf + 1, word, word_len);
2217 buf[0] = 0x06; /* pattern's default regular-match flag */
2218 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2219 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002220
Radek Krejci6d6556c2018-11-08 09:37:45 +01002221 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002222 switch (kw) {
2223 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002224 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 +02002225 break;
2226 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002227 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 +02002228 break;
2229 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002230 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 +02002231 break;
2232 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002233 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 +02002234 break;
2235 case YANG_MODIFIER:
Radek Krejciceaf2122019-01-02 15:03:26 +01002236 YANG_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002237 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002238 break;
2239 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002240 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002241 break;
2242 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002243 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002244 return LY_EVALID;
2245 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002246 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002247 return ret;
2248}
2249
Michal Vaskoea5abea2018-09-18 13:10:54 +02002250/**
2251 * @brief Parse the type statement.
2252 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002253 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002254 * @param[in,out] data Data to read from, always moved to currently handled character.
2255 * @param[in,out] type Type to wrote to.
2256 *
2257 * @return LY_ERR values.
2258 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002259static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002260parse_type(struct lys_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002261{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002262 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002263 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002264 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265 enum yang_keyword kw;
2266 struct lysp_type *nest_type;
2267
2268 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002269 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002270 return LY_EVALID;
2271 }
2272
2273 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002274 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002275 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002276
Radek Krejci6d6556c2018-11-08 09:37:45 +01002277 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002278 switch (kw) {
2279 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002280 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 +01002281 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002282 break;
2283 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002284 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002285 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002286 break;
2287 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002288 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002289 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002290 break;
2291 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002292 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002293 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002294 break;
2295 case YANG_LENGTH:
2296 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002297 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002298 return LY_EVALID;
2299 }
2300 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002301 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002302
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002303 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002304 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002305 break;
2306 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002307 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 +01002308 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002309 break;
2310 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002311 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002312 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002313 break;
2314 case YANG_RANGE:
2315 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002316 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002317 return LY_EVALID;
2318 }
2319 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002320 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002321
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002322 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002323 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002324 break;
2325 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002326 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002327 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002328 break;
2329 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002330 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2331 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002332 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002333 break;
2334 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002335 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002336 break;
2337 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002338 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002339 return LY_EVALID;
2340 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002341 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002342 return ret;
2343}
2344
Michal Vaskoea5abea2018-09-18 13:10:54 +02002345/**
2346 * @brief Parse the leaf statement.
2347 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002348 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002349 * @param[in,out] data Data to read from, always moved to currently handled character.
2350 * @param[in,out] siblings Siblings to add to.
2351 *
2352 * @return LY_ERR values.
2353 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002354LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002355parse_leaf(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002356{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002357 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002358 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002359 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002360 enum yang_keyword kw;
2361 struct lysp_node *iter;
2362 struct lysp_node_leaf *leaf;
2363
2364 /* create structure */
2365 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002366 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002367 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002368 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002369
2370 /* insert into siblings */
2371 if (!*siblings) {
2372 *siblings = (struct lysp_node *)leaf;
2373 } else {
2374 for (iter = *siblings; iter->next; iter = iter->next);
2375 iter->next = (struct lysp_node *)leaf;
2376 }
2377
2378 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002379 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002380 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002381
2382 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002383 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002384 switch (kw) {
2385 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002386 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002387 break;
2388 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002389 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 +02002390 break;
2391 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002392 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 +02002393 break;
2394 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002395 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 +02002396 break;
2397 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002398 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002399 break;
2400 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002401 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002402 break;
2403 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002404 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 +02002405 break;
2406 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002407 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002408 break;
2409 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002410 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002411 break;
2412 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002413 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 +02002414 break;
2415 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002416 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002417 break;
2418 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002419 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002420 break;
2421 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002422 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002423 return LY_EVALID;
2424 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002425 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002426 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002427checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002428 /* mandatory substatements */
2429 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002430 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002431 return LY_EVALID;
2432 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002433 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
2434 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
2435 return LY_EVALID;
2436 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002437
2438 return ret;
2439}
2440
Michal Vaskoea5abea2018-09-18 13:10:54 +02002441/**
2442 * @brief Parse the max-elements statement.
2443 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002444 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002445 * @param[in,out] data Data to read from, always moved to currently handled character.
2446 * @param[in,out] max Value to write to.
2447 * @param[in,out] flags Flags to write to.
2448 * @param[in,out] exts Extension instances to add to.
2449 *
2450 * @return LY_ERR values.
2451 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002452LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002453parse_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 +02002454{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002455 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002456 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002457 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002458 unsigned long int num;
2459 enum yang_keyword kw;
2460
2461 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002462 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002463 return LY_EVALID;
2464 }
2465 *flags |= LYS_SET_MAX;
2466
2467 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002468 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002469
2470 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002471 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002472 free(buf);
2473 return LY_EVALID;
2474 }
2475
2476 if (strncmp(word, "unbounded", word_len)) {
2477 errno = 0;
2478 num = strtoul(word, &ptr, 10);
2479 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002480 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002481 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002482 free(buf);
2483 return LY_EVALID;
2484 }
2485 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002486 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002487 free(buf);
2488 return LY_EVALID;
2489 }
2490
2491 *max = num;
2492 }
2493 free(buf);
2494
Radek Krejci6d6556c2018-11-08 09:37:45 +01002495 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002496 switch (kw) {
2497 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002498 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002499 break;
2500 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002501 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002502 return LY_EVALID;
2503 }
2504 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002505 return ret;
2506}
2507
Michal Vaskoea5abea2018-09-18 13:10:54 +02002508/**
2509 * @brief Parse the min-elements statement.
2510 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002511 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002512 * @param[in,out] data Data to read from, always moved to currently handled character.
2513 * @param[in,out] min Value to write to.
2514 * @param[in,out] flags Flags to write to.
2515 * @param[in,out] exts Extension instances to add to.
2516 *
2517 * @return LY_ERR values.
2518 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002519LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002520parse_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 +02002521{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002522 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002523 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002524 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002525 unsigned long int num;
2526 enum yang_keyword kw;
2527
2528 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002529 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002530 return LY_EVALID;
2531 }
2532 *flags |= LYS_SET_MIN;
2533
2534 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002535 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002536
2537 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002538 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002539 free(buf);
2540 return LY_EVALID;
2541 }
2542
2543 errno = 0;
2544 num = strtoul(word, &ptr, 10);
2545 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002546 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002547 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002548 free(buf);
2549 return LY_EVALID;
2550 }
2551 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002552 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002553 free(buf);
2554 return LY_EVALID;
2555 }
2556 *min = num;
2557 free(buf);
2558
Radek Krejci6d6556c2018-11-08 09:37:45 +01002559 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002560 switch (kw) {
2561 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002562 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002563 break;
2564 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002565 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002566 return LY_EVALID;
2567 }
2568 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002569 return ret;
2570}
2571
Michal Vaskoea5abea2018-09-18 13:10:54 +02002572/**
2573 * @brief Parse the ordered-by statement.
2574 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002575 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002576 * @param[in,out] data Data to read from, always moved to currently handled character.
2577 * @param[in,out] flags Flags to write to.
2578 * @param[in,out] exts Extension instances to add to.
2579 *
2580 * @return LY_ERR values.
2581 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002582static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002583parse_orderedby(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002584{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002585 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002586 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002587 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002588 enum yang_keyword kw;
2589
2590 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002591 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002592 return LY_EVALID;
2593 }
2594
2595 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002596 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002597
2598 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2599 *flags |= LYS_ORDBY_SYSTEM;
2600 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2601 *flags |= LYS_ORDBY_USER;
2602 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002603 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002604 free(buf);
2605 return LY_EVALID;
2606 }
2607 free(buf);
2608
Radek Krejci6d6556c2018-11-08 09:37:45 +01002609 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002610 switch (kw) {
2611 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002612 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002613 break;
2614 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002615 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002616 return LY_EVALID;
2617 }
2618 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619 return ret;
2620}
2621
Michal Vaskoea5abea2018-09-18 13:10:54 +02002622/**
2623 * @brief Parse the leaf-list statement.
2624 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002625 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002626 * @param[in,out] data Data to read from, always moved to currently handled character.
2627 * @param[in,out] siblings Siblings to add to.
2628 *
2629 * @return LY_ERR values.
2630 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002631LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002632parse_leaflist(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002633{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002634 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002635 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002636 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002637 enum yang_keyword kw;
2638 struct lysp_node *iter;
2639 struct lysp_node_leaflist *llist;
2640
2641 /* create structure */
2642 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002643 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002644 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002645 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002646
2647 /* insert into siblings */
2648 if (!*siblings) {
2649 *siblings = (struct lysp_node *)llist;
2650 } else {
2651 for (iter = *siblings; iter->next; iter = iter->next);
2652 iter->next = (struct lysp_node *)llist;
2653 }
2654
2655 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002656 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002657 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002658
2659 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002660 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002661 switch (kw) {
2662 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002663 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002664 break;
2665 case YANG_DEFAULT:
Radek Krejciceaf2122019-01-02 15:03:26 +01002666 YANG_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002667 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 +02002668 break;
2669 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002670 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 +02002671 break;
2672 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002673 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 +02002674 break;
2675 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002676 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002677 break;
2678 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002679 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002680 break;
2681 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002682 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002683 break;
2684 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002685 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002686 break;
2687 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002688 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 +02002689 break;
2690 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002691 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002692 break;
2693 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002694 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695 break;
2696 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002697 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 +02002698 break;
2699 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002700 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002701 break;
2702 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002703 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002704 break;
2705 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002706 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002707 return LY_EVALID;
2708 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002709 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002710 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002711checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002712 /* mandatory substatements */
2713 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002714 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002715 return LY_EVALID;
2716 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002717 if ((llist->min) && (llist->dflts)) {
2718 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
2719 return LY_EVALID;
2720 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002721 if (llist->max && llist->min > llist->max) {
2722 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
2723 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2724 llist->min, llist->max);
2725 return LY_EVALID;
2726 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002727
2728 return ret;
2729}
2730
Michal Vaskoea5abea2018-09-18 13:10:54 +02002731/**
2732 * @brief Parse the refine statement.
2733 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002734 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002735 * @param[in,out] data Data to read from, always moved to currently handled character.
2736 * @param[in,out] refines Refines to add to.
2737 *
2738 * @return LY_ERR values.
2739 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002740static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002741parse_refine(struct lys_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002742{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002743 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002744 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002745 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002746 enum yang_keyword kw;
2747 struct lysp_refine *rf;
2748
Radek Krejci2c4e7172018-10-19 15:56:26 +02002749 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002750
2751 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002752 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002753 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002754
Radek Krejci6d6556c2018-11-08 09:37:45 +01002755 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002756 switch (kw) {
2757 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002758 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002759 break;
2760 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002761 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 +02002762 break;
2763 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002764 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 +02002765 break;
2766 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01002767 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002768 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 +02002769 break;
2770 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002771 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002772 break;
2773 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002774 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002775 break;
2776 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002777 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002778 break;
2779 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002780 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002781 break;
2782 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002783 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 +02002784 break;
2785 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002786 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 +02002787 break;
2788 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002789 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790 break;
2791 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002792 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002793 return LY_EVALID;
2794 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002795 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 return ret;
2797}
2798
Michal Vaskoea5abea2018-09-18 13:10:54 +02002799/**
2800 * @brief Parse the typedef statement.
2801 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002802 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002803 * @param[in,out] data Data to read from, always moved to currently handled character.
2804 * @param[in,out] typedefs Typedefs to add to.
2805 *
2806 * @return LY_ERR values.
2807 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002808static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002809parse_typedef(struct lys_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002810{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002811 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002812 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002813 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002814 enum yang_keyword kw;
2815 struct lysp_tpdf *tpdf;
2816
Radek Krejci2c4e7172018-10-19 15:56:26 +02002817 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002818
2819 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002820 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002821 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002822
2823 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002824 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002825 switch (kw) {
2826 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002827 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 +02002828 break;
2829 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002830 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 +02002831 break;
2832 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002833 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 +02002834 break;
2835 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002836 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002837 break;
2838 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002839 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002840 break;
2841 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002842 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 +02002843 break;
2844 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002845 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846 break;
2847 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002848 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002849 return LY_EVALID;
2850 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002851 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002852 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002853checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002854 /* mandatory substatements */
2855 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002856 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 return LY_EVALID;
2858 }
2859
Radek Krejcibbe09a92018-11-08 09:36:54 +01002860 /* store data for collision check */
2861 if (parent) {
2862 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2863 }
2864
Michal Vasko7fbc8162018-09-17 10:35:16 +02002865 return ret;
2866}
2867
Michal Vaskoea5abea2018-09-18 13:10:54 +02002868/**
2869 * @brief Parse the input or output statement.
2870 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002871 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002872 * @param[in,out] data Data to read from, always moved to currently handled character.
2873 * @param[in] kw Type of this particular keyword
2874 * @param[in,out] inout_p Input/output pointer to write to.
2875 *
2876 * @return LY_ERR values.
2877 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002878static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002879parse_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 +02002880{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002881 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002882 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002883 size_t word_len;
Radek Krejci10113652018-11-14 16:56:50 +01002884 enum yang_keyword kw;
Radek Krejcie86bf772018-12-14 11:39:53 +01002885 unsigned int u;
2886 struct lysp_node *child;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002887
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002888 if (inout_p->nodetype) {
Radek Krejci10113652018-11-14 16:56:50 +01002889 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002890 return LY_EVALID;
2891 }
2892
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002893 /* initiate structure */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002894 inout_p->nodetype = &((struct lysp_action*)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002895 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002896
2897 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002898 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002899 switch (kw) {
2900 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002901 YANG_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002902 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002903 case YANG_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002904 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002905 break;
2906 case YANG_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002907 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002908 break;
2909 case YANG_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002910 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002911 break;
2912 case YANG_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002913 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002914 break;
2915 case YANG_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002916 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002917 break;
2918 case YANG_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002919 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002920 break;
2921 case YANG_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002922 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002923 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002924 case YANG_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002925 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002926 break;
2927 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002928 YANG_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002929 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002930 break;
2931 case YANG_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002932 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002933 break;
2934 case YANG_CUSTOM:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002935 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002936 break;
2937 default:
Radek Krejci10113652018-11-14 16:56:50 +01002938 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002939 return LY_EVALID;
2940 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002941 }
Radek Krejcie86bf772018-12-14 11:39:53 +01002942 /* finalize parent pointers to the reallocated items */
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002943 LY_ARRAY_FOR(inout_p->groupings, u) {
2944 LY_LIST_FOR(inout_p->groupings[u].data, child) {
2945 child->parent = (struct lysp_node*)&inout_p->groupings[u];
Radek Krejcie86bf772018-12-14 11:39:53 +01002946 }
2947 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002948 return ret;
2949}
2950
Michal Vaskoea5abea2018-09-18 13:10:54 +02002951/**
2952 * @brief Parse the action statement.
2953 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002954 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002955 * @param[in,out] data Data to read from, always moved to currently handled character.
2956 * @param[in,out] actions Actions to add to.
2957 *
2958 * @return LY_ERR values.
2959 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002960LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002961parse_action(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002962{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002963 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002964 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002965 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002966 enum yang_keyword kw;
2967 struct lysp_action *act;
Radek Krejcie86bf772018-12-14 11:39:53 +01002968 struct lysp_node *child;
2969 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002970
Radek Krejci2c4e7172018-10-19 15:56:26 +02002971 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002972
2973 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002974 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002975 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002976 act->nodetype = LYS_ACTION;
2977 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978
Radek Krejci6d6556c2018-11-08 09:37:45 +01002979 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002980 switch (kw) {
2981 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002982 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 +02002983 break;
2984 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002985 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 +02002986 break;
2987 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002988 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 +02002989 break;
2990 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002991 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002992 break;
2993
2994 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002995 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002996 break;
2997 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002998 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002999 break;
3000
3001 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003002 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003003 break;
3004 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003005 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003006 break;
3007 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003008 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003009 break;
3010 default:
Radek Krejcif538ce52019-03-05 10:46:14 +01003011 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003012 return LY_EVALID;
3013 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003014 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003015 /* finalize parent pointers to the reallocated items */
3016 LY_ARRAY_FOR(act->groupings, u) {
3017 LY_LIST_FOR(act->groupings[u].data, child) {
3018 child->parent = (struct lysp_node*)&act->groupings[u];
3019 }
3020 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003021 return ret;
3022}
3023
Michal Vaskoea5abea2018-09-18 13:10:54 +02003024/**
3025 * @brief Parse the notification statement.
3026 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003027 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003028 * @param[in,out] data Data to read from, always moved to currently handled character.
3029 * @param[in,out] notifs Notifications to add to.
3030 *
3031 * @return LY_ERR values.
3032 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003033LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003034parse_notif(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003035{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003036 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003037 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003038 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003039 enum yang_keyword kw;
3040 struct lysp_notif *notif;
Radek Krejcie86bf772018-12-14 11:39:53 +01003041 struct lysp_node *child;
3042 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003043
Radek Krejci2c4e7172018-10-19 15:56:26 +02003044 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003045
3046 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003047 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003048 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003049 notif->nodetype = LYS_NOTIF;
3050 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003051
Radek Krejci6d6556c2018-11-08 09:37:45 +01003052 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003053 switch (kw) {
3054 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003055 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 +02003056 break;
3057 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003058 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 +02003059 break;
3060 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003061 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 +02003062 break;
3063 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003064 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003065 break;
3066
3067 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003068 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01003069 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003070 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003071 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003072 break;
3073 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003074 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003075 break;
3076 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003077 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003078 break;
3079 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003080 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003081 break;
3082 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003083 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003084 break;
3085 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003086 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003087 break;
3088 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003089 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003090 break;
3091
3092 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01003093 YANG_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003094 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003095 break;
3096 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003097 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003098 break;
3099 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003100 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003101 break;
3102 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003103 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003104 break;
3105 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003106 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003107 return LY_EVALID;
3108 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003109 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003110 /* finalize parent pointers to the reallocated items */
3111 LY_ARRAY_FOR(notif->groupings, u) {
3112 LY_LIST_FOR(notif->groupings[u].data, child) {
3113 child->parent = (struct lysp_node*)&notif->groupings[u];
3114 }
3115 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003116 return ret;
3117}
3118
Michal Vaskoea5abea2018-09-18 13:10:54 +02003119/**
3120 * @brief Parse the grouping statement.
3121 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003122 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003123 * @param[in,out] data Data to read from, always moved to currently handled character.
3124 * @param[in,out] groupings Groupings to add to.
3125 *
3126 * @return LY_ERR values.
3127 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003128LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003129parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003130{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003131 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003132 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003133 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003134 enum yang_keyword kw;
3135 struct lysp_grp *grp;
Radek Krejcie86bf772018-12-14 11:39:53 +01003136 struct lysp_node *child;
3137 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003138
Radek Krejci2c4e7172018-10-19 15:56:26 +02003139 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003140
3141 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003142 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003143 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003144 grp->nodetype = LYS_GROUPING;
3145 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003146
Radek Krejci6d6556c2018-11-08 09:37:45 +01003147 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003148 switch (kw) {
3149 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003150 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 +02003151 break;
3152 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003153 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 +02003154 break;
3155 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003156 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003157 break;
3158
3159 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003160 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01003161 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003162 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003163 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003164 break;
3165 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003166 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003167 break;
3168 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003169 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003170 break;
3171 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003172 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003173 break;
3174 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003175 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003176 break;
3177 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003178 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003179 break;
3180 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003181 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003182 break;
3183
3184 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003185 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003186 break;
3187 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003188 YANG_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003189 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003190 break;
3191 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003192 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003193 break;
3194 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003195 YANG_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003196 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003197 break;
3198 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003199 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003200 break;
3201 default:
Radek Krejci10113652018-11-14 16:56:50 +01003202 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003203 return LY_EVALID;
3204 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003205 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003206 /* finalize parent pointers to the reallocated items */
3207 LY_ARRAY_FOR(grp->groupings, u) {
3208 LY_LIST_FOR(grp->groupings[u].data, child) {
3209 child->parent = (struct lysp_node*)&grp->groupings[u];
3210 }
3211 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003212 return ret;
3213}
3214
Michal Vaskoea5abea2018-09-18 13:10:54 +02003215/**
3216 * @brief Parse the refine statement.
3217 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003218 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003219 * @param[in,out] data Data to read from, always moved to currently handled character.
3220 * @param[in,out] augments Augments to add to.
3221 *
3222 * @return LY_ERR values.
3223 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003224LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003225parse_augment(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003226{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003227 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003228 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003229 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003230 enum yang_keyword kw;
3231 struct lysp_augment *aug;
3232
Radek Krejci2c4e7172018-10-19 15:56:26 +02003233 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003234
3235 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003236 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003237 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003238 aug->nodetype = LYS_AUGMENT;
3239 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003240
Radek Krejci6d6556c2018-11-08 09:37:45 +01003241 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003242 switch (kw) {
3243 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003244 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 +02003245 break;
3246 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003247 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 +02003248 break;
3249 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003250 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 +02003251 break;
3252 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003253 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003254 break;
3255 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003256 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003257 break;
3258
3259 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003260 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01003261 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003262 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003263 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003264 break;
3265 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003266 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003267 break;
3268 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003269 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003270 break;
3271 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003272 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003273 break;
3274 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003275 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003276 break;
3277 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003278 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003279 break;
3280 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003281 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003282 break;
3283 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003284 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003285 break;
3286
3287 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003288 YANG_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003289 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003290 break;
3291 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003292 YANG_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003293 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003294 break;
3295 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003296 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 break;
3298 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003299 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003300 return LY_EVALID;
3301 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003302 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003303 return ret;
3304}
3305
Michal Vaskoea5abea2018-09-18 13:10:54 +02003306/**
3307 * @brief Parse the uses statement.
3308 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003309 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003310 * @param[in,out] data Data to read from, always moved to currently handled character.
3311 * @param[in,out] siblings Siblings to add to.
3312 *
3313 * @return LY_ERR values.
3314 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003315LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003316parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003317{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003318 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003319 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003320 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003321 enum yang_keyword kw;
3322 struct lysp_node *iter;
3323 struct lysp_node_uses *uses;
3324
3325 /* create structure */
3326 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003327 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003328 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003329 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003330
3331 /* insert into siblings */
3332 if (!*siblings) {
3333 *siblings = (struct lysp_node *)uses;
3334 } else {
3335 for (iter = *siblings; iter->next; iter = iter->next);
3336 iter->next = (struct lysp_node *)uses;
3337 }
3338
3339 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003340 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003341 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003342
3343 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003344 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003345 switch (kw) {
3346 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003347 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 +02003348 break;
3349 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003350 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 +02003351 break;
3352 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003353 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 +02003354 break;
3355 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003356 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003357 break;
3358 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003359 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003360 break;
3361
3362 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003363 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003364 break;
3365 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003366 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003367 break;
3368 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003369 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003370 break;
3371 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003372 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373 return LY_EVALID;
3374 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003375 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003376 return ret;
3377}
3378
Michal Vaskoea5abea2018-09-18 13:10:54 +02003379/**
3380 * @brief Parse the case statement.
3381 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003382 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003383 * @param[in,out] data Data to read from, always moved to currently handled character.
3384 * @param[in,out] siblings Siblings to add to.
3385 *
3386 * @return LY_ERR values.
3387 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003388LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003389parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003390{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003391 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003392 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003393 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003394 enum yang_keyword kw;
3395 struct lysp_node *iter;
3396 struct lysp_node_case *cas;
3397
3398 /* create structure */
3399 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003400 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003401 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003402 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003403
3404 /* insert into siblings */
3405 if (!*siblings) {
3406 *siblings = (struct lysp_node *)cas;
3407 } else {
3408 for (iter = *siblings; iter->next; iter = iter->next);
3409 iter->next = (struct lysp_node *)cas;
3410 }
3411
3412 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003413 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003414 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003415
3416 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003417 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003418 switch (kw) {
3419 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003420 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 +02003421 break;
3422 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003423 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 +02003424 break;
3425 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003426 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 +02003427 break;
3428 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003429 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003430 break;
3431 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003432 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003433 break;
3434
3435 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003436 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003437 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003438 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003439 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003440 break;
3441 case YANG_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003442 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003443 break;
3444 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003445 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003446 break;
3447 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003448 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003449 break;
3450 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003451 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003452 break;
3453 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003454 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003455 break;
3456 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003457 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003458 break;
3459 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003460 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003461 break;
3462 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003463 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003464 return LY_EVALID;
3465 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003466 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003467 return ret;
3468}
3469
Michal Vaskoea5abea2018-09-18 13:10:54 +02003470/**
3471 * @brief Parse the choice statement.
3472 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003473 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003474 * @param[in,out] data Data to read from, always moved to currently handled character.
3475 * @param[in,out] siblings Siblings to add to.
3476 *
3477 * @return LY_ERR values.
3478 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003479LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003480parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003481{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003482 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003484 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003485 enum yang_keyword kw;
3486 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003487 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003488
3489 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003490 choice = calloc(1, sizeof *choice);
3491 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3492 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003493 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003494
3495 /* insert into siblings */
3496 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003497 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003498 } else {
3499 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003500 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003501 }
3502
3503 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003504 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003505 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003506
3507 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003508 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003509 switch (kw) {
3510 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003511 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003512 break;
3513 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003514 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 +02003515 break;
3516 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003517 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 +02003518 break;
3519 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003520 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003521 break;
3522 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003523 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 +02003524 break;
3525 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003526 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003527 break;
3528 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003529 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530 break;
3531 case YANG_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003532 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 +02003533 break;
3534
3535 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003536 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003537 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003538 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003539 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003540 break;
3541 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003542 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 break;
3544 case YANG_CHOICE:
Radek Krejciceaf2122019-01-02 15:03:26 +01003545 YANG_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003546 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003547 break;
3548 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003549 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003550 break;
3551 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003552 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003553 break;
3554 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003555 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003556 break;
3557 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003558 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003559 break;
3560 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003561 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003562 break;
3563 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003564 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003565 return LY_EVALID;
3566 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003568 LY_CHECK_RET(ret);
3569checks:
3570 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
3571 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
3572 return LY_EVALID;
3573 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003574 return ret;
3575}
3576
Michal Vaskoea5abea2018-09-18 13:10:54 +02003577/**
3578 * @brief Parse the container statement.
3579 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003580 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003581 * @param[in,out] data Data to read from, always moved to currently handled character.
3582 * @param[in,out] siblings Siblings to add to.
3583 *
3584 * @return LY_ERR values.
3585 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003586LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003587parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003588{
3589 LY_ERR ret = 0;
3590 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003591 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003592 enum yang_keyword kw;
3593 struct lysp_node *iter;
3594 struct lysp_node_container *cont;
Radek Krejcie86bf772018-12-14 11:39:53 +01003595 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003596
3597 /* create structure */
3598 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003599 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003600 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003601 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003602
3603 /* insert into siblings */
3604 if (!*siblings) {
3605 *siblings = (struct lysp_node *)cont;
3606 } else {
3607 for (iter = *siblings; iter->next; iter = iter->next);
3608 iter->next = (struct lysp_node *)cont;
3609 }
3610
3611 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003612 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003613 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003614
3615 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003616 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003617 switch (kw) {
3618 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003619 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003620 break;
3621 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003622 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 +02003623 break;
3624 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003625 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 +02003626 break;
3627 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003628 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 +02003629 break;
3630 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003631 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003632 break;
3633 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003634 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003635 break;
3636 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003637 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 +02003638 break;
3639
3640 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003641 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003642 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003644 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003645 break;
3646 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003647 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003648 break;
3649 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003650 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003651 break;
3652 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003653 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003654 break;
3655 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003656 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003657 break;
3658 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003659 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003660 break;
3661 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003662 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003663 break;
3664
3665 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003666 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003667 break;
3668 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003669 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003670 break;
3671 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003672 YANG_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003673 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003674 break;
3675 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003676 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003677 break;
3678 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003679 YANG_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003680 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003681 break;
3682 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003683 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003684 break;
3685 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003686 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003687 return LY_EVALID;
3688 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003689 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003690 /* finalize parent pointers to the reallocated items */
3691 LY_ARRAY_FOR(cont->groupings, u) {
3692 LY_LIST_FOR(cont->groupings[u].data, iter) {
3693 iter->parent = (struct lysp_node*)&cont->groupings[u];
3694 }
3695 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003696 return ret;
3697}
3698
Michal Vaskoea5abea2018-09-18 13:10:54 +02003699/**
3700 * @brief Parse the list statement.
3701 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003702 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003703 * @param[in,out] data Data to read from, always moved to currently handled character.
3704 * @param[in,out] siblings Siblings to add to.
3705 *
3706 * @return LY_ERR values.
3707 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003708LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003709parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003710{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003711 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003712 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003713 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003714 enum yang_keyword kw;
3715 struct lysp_node *iter;
3716 struct lysp_node_list *list;
Radek Krejcie86bf772018-12-14 11:39:53 +01003717 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003718
3719 /* create structure */
3720 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003721 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003722 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003723 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003724
3725 /* insert into siblings */
3726 if (!*siblings) {
3727 *siblings = (struct lysp_node *)list;
3728 } else {
3729 for (iter = *siblings; iter->next; iter = iter->next);
3730 iter->next = (struct lysp_node *)list;
3731 }
3732
3733 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003734 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003735 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003736
3737 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003738 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003739 switch (kw) {
3740 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003741 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003742 break;
3743 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003744 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 +02003745 break;
3746 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003747 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 +02003748 break;
3749 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003750 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 +02003751 break;
3752 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003753 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003754 break;
3755 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003756 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003757 break;
3758 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003759 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 +02003760 break;
3761 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003762 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003763 break;
3764 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003765 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003766 break;
3767 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003768 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003769 break;
3770 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003771 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 +02003772 break;
3773
3774 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003775 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003776 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003777 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003778 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003779 break;
3780 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003781 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003782 break;
3783 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003784 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003785 break;
3786 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003787 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003788 break;
3789 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003790 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003791 break;
3792 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003793 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003794 break;
3795 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003796 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003797 break;
3798
3799 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003800 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003801 break;
3802 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003803 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003804 break;
3805 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003806 YANG_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003807 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003808 break;
3809 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003810 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003811 break;
3812 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003813 YANG_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003814 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003815 break;
3816 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003817 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003818 break;
3819 default:
Radek Krejci10113652018-11-14 16:56:50 +01003820 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003821 return LY_EVALID;
3822 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003823 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003824 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01003825 /* finalize parent pointers to the reallocated items */
3826 LY_ARRAY_FOR(list->groupings, u) {
3827 LY_LIST_FOR(list->groupings[u].data, iter) {
3828 iter->parent = (struct lysp_node*)&list->groupings[u];
3829 }
3830 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003831checks:
3832 if (list->max && list->min > list->max) {
3833 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
3834 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3835 list->min, list->max);
3836 return LY_EVALID;
3837 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003838
3839 return ret;
3840}
3841
Michal Vaskoea5abea2018-09-18 13:10:54 +02003842/**
3843 * @brief Parse the yin-element statement.
3844 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003845 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003846 * @param[in,out] data Data to read from, always moved to currently handled character.
3847 * @param[in,out] flags Flags to write to.
3848 * @param[in,out] exts Extension instances to add to.
3849 *
3850 * @return LY_ERR values.
3851 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003852static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003853parse_yinelement(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003854{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003855 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003856 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003857 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003858 enum yang_keyword kw;
3859
3860 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003861 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003862 return LY_EVALID;
3863 }
3864
3865 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003866 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003867
3868 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3869 *flags |= LYS_YINELEM_TRUE;
3870 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3871 *flags |= LYS_YINELEM_FALSE;
3872 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003873 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003874 free(buf);
3875 return LY_EVALID;
3876 }
3877 free(buf);
3878
Radek Krejci6d6556c2018-11-08 09:37:45 +01003879 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003880 switch (kw) {
3881 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003882 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3883 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003884 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003885 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003886 return LY_EVALID;
3887 }
3888 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003889 return ret;
3890}
3891
Michal Vaskoea5abea2018-09-18 13:10:54 +02003892/**
3893 * @brief Parse the yin-element statement.
3894 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003895 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003896 * @param[in,out] data Data to read from, always moved to currently handled character.
3897 * @param[in,out] argument Value to write to.
3898 * @param[in,out] flags Flags to write to.
3899 * @param[in,out] exts Extension instances to add to.
3900 *
3901 * @return LY_ERR values.
3902 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003903static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003904parse_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 +02003905{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003906 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003907 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003908 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003909 enum yang_keyword kw;
3910
3911 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003912 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003913 return LY_EVALID;
3914 }
3915
3916 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003917 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003918 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003919
Radek Krejci6d6556c2018-11-08 09:37:45 +01003920 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003921 switch (kw) {
3922 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003923 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003924 break;
3925 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003926 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003927 break;
3928 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003929 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003930 return LY_EVALID;
3931 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003932 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003933 return ret;
3934}
3935
Michal Vaskoea5abea2018-09-18 13:10:54 +02003936/**
3937 * @brief Parse the extension statement.
3938 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003939 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003940 * @param[in,out] data Data to read from, always moved to currently handled character.
3941 * @param[in,out] extensions Extensions to add to.
3942 *
3943 * @return LY_ERR values.
3944 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003945static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003946parse_extension(struct lys_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003947{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003948 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003949 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003950 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003951 enum yang_keyword kw;
3952 struct lysp_ext *ex;
3953
Radek Krejci2c4e7172018-10-19 15:56:26 +02003954 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003955
3956 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003957 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003958 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003959
Radek Krejci6d6556c2018-11-08 09:37:45 +01003960 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003961 switch (kw) {
3962 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003963 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 +02003964 break;
3965 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003966 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 +02003967 break;
3968 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003969 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003970 break;
3971 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003972 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003973 break;
3974 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003975 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003976 break;
3977 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003978 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003979 return LY_EVALID;
3980 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003981 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003982 return ret;
3983}
3984
Michal Vaskoea5abea2018-09-18 13:10:54 +02003985/**
3986 * @brief Parse the deviate statement.
3987 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003988 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003989 * @param[in,out] data Data to read from, always moved to currently handled character.
3990 * @param[in,out] deviates Deviates to add to.
3991 *
3992 * @return LY_ERR values.
3993 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003994LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003995parse_deviate(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003996{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003997 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003998 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003999 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004000 enum yang_keyword kw;
4001 struct lysp_deviate *iter, *d;
4002 struct lysp_deviate_add *d_add = NULL;
4003 struct lysp_deviate_rpl *d_rpl = NULL;
4004 struct lysp_deviate_del *d_del = NULL;
4005 const char **d_units, ***d_uniques, ***d_dflts;
4006 struct lysp_restr **d_musts;
4007 uint16_t *d_flags;
4008 uint32_t *d_min, *d_max;
4009
4010 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004011 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004012
4013 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4014 dev_mod = LYS_DEV_NOT_SUPPORTED;
4015 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4016 dev_mod = LYS_DEV_ADD;
4017 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4018 dev_mod = LYS_DEV_REPLACE;
4019 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4020 dev_mod = LYS_DEV_DELETE;
4021 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004022 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004023 free(buf);
4024 return LY_EVALID;
4025 }
4026 free(buf);
4027
4028 /* create structure */
4029 switch (dev_mod) {
4030 case LYS_DEV_NOT_SUPPORTED:
4031 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004032 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004033 break;
4034 case LYS_DEV_ADD:
4035 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004036 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004037 d = (struct lysp_deviate *)d_add;
4038 d_units = &d_add->units;
4039 d_uniques = &d_add->uniques;
4040 d_dflts = &d_add->dflts;
4041 d_musts = &d_add->musts;
4042 d_flags = &d_add->flags;
4043 d_min = &d_add->min;
4044 d_max = &d_add->max;
4045 break;
4046 case LYS_DEV_REPLACE:
4047 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004048 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004049 d = (struct lysp_deviate *)d_rpl;
4050 d_units = &d_rpl->units;
4051 d_flags = &d_rpl->flags;
4052 d_min = &d_rpl->min;
4053 d_max = &d_rpl->max;
4054 break;
4055 case LYS_DEV_DELETE:
4056 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004057 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004058 d = (struct lysp_deviate *)d_del;
4059 d_units = &d_del->units;
4060 d_uniques = &d_del->uniques;
4061 d_dflts = &d_del->dflts;
4062 d_musts = &d_del->musts;
4063 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004064 break;
4065 default:
4066 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004067 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004068 }
4069 d->mod = dev_mod;
4070
4071 /* insert into siblings */
4072 if (!*deviates) {
4073 *deviates = d;
4074 } else {
4075 for (iter = *deviates; iter->next; iter = iter->next);
4076 iter->next = d;
4077 }
4078
Radek Krejci6d6556c2018-11-08 09:37:45 +01004079 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004080 switch (kw) {
4081 case YANG_CONFIG:
4082 switch (dev_mod) {
4083 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004084 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004085 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004086 return LY_EVALID;
4087 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004088 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004089 break;
4090 }
4091 break;
4092 case YANG_DEFAULT:
4093 switch (dev_mod) {
4094 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004095 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004096 return LY_EVALID;
4097 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004098 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 +02004099 break;
4100 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004101 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 +02004102 break;
4103 }
4104 break;
4105 case YANG_MANDATORY:
4106 switch (dev_mod) {
4107 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004108 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004109 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004110 return LY_EVALID;
4111 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004112 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004113 break;
4114 }
4115 break;
4116 case YANG_MAX_ELEMENTS:
4117 switch (dev_mod) {
4118 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004119 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004120 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004121 return LY_EVALID;
4122 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004123 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004124 break;
4125 }
4126 break;
4127 case YANG_MIN_ELEMENTS:
4128 switch (dev_mod) {
4129 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004130 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004131 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004132 return LY_EVALID;
4133 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004134 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004135 break;
4136 }
4137 break;
4138 case YANG_MUST:
4139 switch (dev_mod) {
4140 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004141 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004142 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004143 return LY_EVALID;
4144 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004145 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004146 break;
4147 }
4148 break;
4149 case YANG_TYPE:
4150 switch (dev_mod) {
4151 case LYS_DEV_NOT_SUPPORTED:
4152 case LYS_DEV_ADD:
4153 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004154 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004155 return LY_EVALID;
4156 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004157 if (d_rpl->type) {
4158 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4159 return LY_EVALID;
4160 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004161 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004162 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004163 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004164 break;
4165 }
4166 break;
4167 case YANG_UNIQUE:
4168 switch (dev_mod) {
4169 case LYS_DEV_NOT_SUPPORTED:
4170 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004171 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004172 return LY_EVALID;
4173 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004174 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 +02004175 break;
4176 }
4177 break;
4178 case YANG_UNITS:
4179 switch (dev_mod) {
4180 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004181 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004182 return LY_EVALID;
4183 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004184 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 +02004185 break;
4186 }
4187 break;
4188 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004189 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004190 break;
4191 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004192 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004193 return LY_EVALID;
4194 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004195 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004196 return ret;
4197}
4198
Michal Vaskoea5abea2018-09-18 13:10:54 +02004199/**
4200 * @brief Parse the deviation statement.
4201 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004202 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004203 * @param[in,out] data Data to read from, always moved to currently handled character.
4204 * @param[in,out] deviations Deviations to add to.
4205 *
4206 * @return LY_ERR values.
4207 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004208LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004209parse_deviation(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004210{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004211 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004212 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004213 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004214 enum yang_keyword kw;
4215 struct lysp_deviation *dev;
4216
Radek Krejci2c4e7172018-10-19 15:56:26 +02004217 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004218
4219 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004220 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004221 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004222
Radek Krejci6d6556c2018-11-08 09:37:45 +01004223 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004224 switch (kw) {
4225 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004226 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 +02004227 break;
4228 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004229 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004230 break;
4231 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004232 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 +02004233 break;
4234 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004235 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236 break;
4237 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004238 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004239 return LY_EVALID;
4240 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004241 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004242 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004243checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004244 /* mandatory substatements */
4245 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004246 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004247 return LY_EVALID;
4248 }
4249
4250 return ret;
4251}
4252
Michal Vaskoea5abea2018-09-18 13:10:54 +02004253/**
4254 * @brief Parse the feature statement.
4255 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004256 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004257 * @param[in,out] data Data to read from, always moved to currently handled character.
4258 * @param[in,out] features Features to add to.
4259 *
4260 * @return LY_ERR values.
4261 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004262LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004263parse_feature(struct lys_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004264{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004265 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004266 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004267 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004268 enum yang_keyword kw;
4269 struct lysp_feature *feat;
4270
Radek Krejci2c4e7172018-10-19 15:56:26 +02004271 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004272
4273 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004274 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004275 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004276
Radek Krejci6d6556c2018-11-08 09:37:45 +01004277 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004278 switch (kw) {
4279 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004280 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 +02004281 break;
4282 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004283 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 +02004284 break;
4285 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004286 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 +02004287 break;
4288 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004289 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004290 break;
4291 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004292 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004293 break;
4294 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004295 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004296 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004297 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004298 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004299 return ret;
4300}
4301
Michal Vaskoea5abea2018-09-18 13:10:54 +02004302/**
4303 * @brief Parse the identity statement.
4304 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004305 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004306 * @param[in,out] data Data to read from, always moved to currently handled character.
4307 * @param[in,out] identities Identities to add to.
4308 *
4309 * @return LY_ERR values.
4310 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004311LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004312parse_identity(struct lys_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004313{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004314 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004315 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004316 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004317 enum yang_keyword kw;
4318 struct lysp_ident *ident;
4319
Radek Krejci2c4e7172018-10-19 15:56:26 +02004320 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004321
4322 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004323 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004324 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004325
Radek Krejci6d6556c2018-11-08 09:37:45 +01004326 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004327 switch (kw) {
4328 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004329 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 +02004330 break;
4331 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01004332 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004333 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 +02004334 break;
4335 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004336 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 +02004337 break;
4338 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004339 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004340 break;
4341 case YANG_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004342 if (ident->bases && ctx->mod_version < 2) {
Radek Krejci10113652018-11-14 16:56:50 +01004343 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4344 return LY_EVALID;
4345 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004346 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 +02004347 break;
4348 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004349 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004350 break;
4351 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004352 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004353 return LY_EVALID;
4354 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004355 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004356 return ret;
4357}
4358
Michal Vaskoea5abea2018-09-18 13:10:54 +02004359/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004360 * @brief Finalize some of the (sub)module structure after parsing.
4361 *
4362 * Update parent pointers in the nodes inside grouping/RPC/Notification, which could be reallocated.
4363 *
4364 * @param[in] mod Parsed module to be updated.
4365 * @return LY_ERR value (currently only LY_SUCCESS, but it can change in future).
4366 */
4367static LY_ERR
4368parse_sub_module_finalize(struct lysp_module *mod)
4369{
4370 unsigned int u;
4371 struct lysp_node *child;
4372
4373 /* finalize parent pointers to the reallocated items */
4374 LY_ARRAY_FOR(mod->groupings, u) {
4375 LY_LIST_FOR(mod->groupings[u].data, child) {
4376 child->parent = (struct lysp_node*)&mod->groupings[u];
4377 }
4378 }
4379
4380 /* TODO the same finalization for rpcs and notifications, do also in the relevant nodes */
4381
4382 return LY_SUCCESS;
4383}
4384
4385/**
4386 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004387 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004388 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004389 * @param[in,out] data Data to read from, always moved to currently handled character.
4390 * @param[in,out] mod Module to write to.
4391 *
4392 * @return LY_ERR values.
4393 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004394LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004395parse_module(struct lys_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004396{
4397 LY_ERR ret = 0;
4398 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004399 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004400 enum yang_keyword kw, prev_kw = 0;
4401 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004402 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004403
4404 /* (sub)module name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004405 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004406 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004407
Radek Krejci6d6556c2018-11-08 09:37:45 +01004408 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004409
Radek Krejcie3846472018-10-15 15:24:51 +02004410#define CHECK_ORDER(SECTION) \
4411 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4412
Michal Vasko7fbc8162018-09-17 10:35:16 +02004413 switch (kw) {
4414 /* module header */
4415 case YANG_NAMESPACE:
4416 case YANG_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004417 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4418 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004419 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004420 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004421 break;
4422 /* linkage */
4423 case YANG_INCLUDE:
4424 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004425 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004426 break;
4427 /* meta */
4428 case YANG_ORGANIZATION:
4429 case YANG_CONTACT:
4430 case YANG_DESCRIPTION:
4431 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004432 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004433 break;
4434
4435 /* revision */
4436 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004437 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004438 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004439 /* body */
4440 case YANG_ANYDATA:
4441 case YANG_ANYXML:
4442 case YANG_AUGMENT:
4443 case YANG_CHOICE:
4444 case YANG_CONTAINER:
4445 case YANG_DEVIATION:
4446 case YANG_EXTENSION:
4447 case YANG_FEATURE:
4448 case YANG_GROUPING:
4449 case YANG_IDENTITY:
4450 case YANG_LEAF:
4451 case YANG_LEAF_LIST:
4452 case YANG_LIST:
4453 case YANG_NOTIFICATION:
4454 case YANG_RPC:
4455 case YANG_TYPEDEF:
4456 case YANG_USES:
4457 case YANG_CUSTOM:
4458 mod_stmt = Y_MOD_BODY;
4459 break;
4460 default:
4461 /* error handled in the next switch */
4462 break;
4463 }
Radek Krejcie3846472018-10-15 15:24:51 +02004464#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004465
Radek Krejcie3846472018-10-15 15:24:51 +02004466 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004467 switch (kw) {
4468 /* module header */
4469 case YANG_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004470 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4471 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004472 break;
4473 case YANG_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004474 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 +02004475 break;
4476 case YANG_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004477 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 +02004478 break;
4479
4480 /* linkage */
4481 case YANG_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004482 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004483 break;
4484 case YANG_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004485 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004486 break;
4487
4488 /* meta */
4489 case YANG_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004490 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 +02004491 break;
4492 case YANG_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004493 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 +02004494 break;
4495 case YANG_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004496 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 +02004497 break;
4498 case YANG_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004499 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 +02004500 break;
4501
4502 /* revision */
4503 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004504 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004505 break;
4506
4507 /* body */
4508 case YANG_ANYDATA:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004509 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004510 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004511 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004512 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004513 break;
4514 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004515 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004516 break;
4517 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004518 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004519 break;
4520 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004521 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004522 break;
4523 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004524 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004525 break;
4526 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004527 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004528 break;
4529 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004530 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004531 break;
4532
4533 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004534 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004535 break;
4536 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004537 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004538 break;
4539 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004540 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004541 break;
4542 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004543 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004544 break;
4545 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004546 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004547 break;
4548 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004549 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004550 break;
4551 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004552 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004553 break;
4554 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004555 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004556 break;
4557 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004558 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004559 break;
4560 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004561 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004562 break;
4563
4564 default:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004565 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004566 return LY_EVALID;
4567 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004568 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004569 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004570
Radek Krejci6d6556c2018-11-08 09:37:45 +01004571checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004572 /* finalize parent pointers to the reallocated items */
4573 LY_CHECK_RET(parse_sub_module_finalize(mod));
4574
Michal Vasko7fbc8162018-09-17 10:35:16 +02004575 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004576 if (!mod->mod->ns) {
4577 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
4578 return LY_EVALID;
4579 } else if (!mod->mod->prefix) {
4580 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
4581 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004582 }
4583
Radek Krejcie9e987e2018-10-31 12:50:27 +01004584 /* submodules share the namespace with the module names, so there must not be
4585 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004586 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4587 if (dup) {
4588 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
4589 return LY_EVALID;
4590 }
4591
4592 return ret;
4593}
4594
4595/**
4596 * @brief Parse submodule substatements.
4597 *
4598 * @param[in] ctx yang parser context for logging.
4599 * @param[in,out] data Data to read from, always moved to currently handled character.
4600 * @param[out] submod Parsed submodule structure.
4601 *
4602 * @return LY_ERR values.
4603 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004604LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004605parse_submodule(struct lys_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004606{
4607 LY_ERR ret = 0;
4608 char *buf, *word;
4609 size_t word_len;
4610 enum yang_keyword kw, prev_kw = 0;
4611 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4612 struct lysp_submodule *dup;
4613
4614 /* submodule name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004615 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004616 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4617
4618 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4619
4620#define CHECK_ORDER(SECTION) \
4621 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4622
4623 switch (kw) {
4624 /* module header */
4625 case YANG_BELONGS_TO:
4626 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4627 break;
4628 case YANG_YANG_VERSION:
4629 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4630 break;
4631 /* linkage */
4632 case YANG_INCLUDE:
4633 case YANG_IMPORT:
4634 CHECK_ORDER(Y_MOD_LINKAGE);
4635 break;
4636 /* meta */
4637 case YANG_ORGANIZATION:
4638 case YANG_CONTACT:
4639 case YANG_DESCRIPTION:
4640 case YANG_REFERENCE:
4641 CHECK_ORDER(Y_MOD_META);
4642 break;
4643
4644 /* revision */
4645 case YANG_REVISION:
4646 CHECK_ORDER(Y_MOD_REVISION);
4647 break;
4648 /* body */
4649 case YANG_ANYDATA:
4650 case YANG_ANYXML:
4651 case YANG_AUGMENT:
4652 case YANG_CHOICE:
4653 case YANG_CONTAINER:
4654 case YANG_DEVIATION:
4655 case YANG_EXTENSION:
4656 case YANG_FEATURE:
4657 case YANG_GROUPING:
4658 case YANG_IDENTITY:
4659 case YANG_LEAF:
4660 case YANG_LEAF_LIST:
4661 case YANG_LIST:
4662 case YANG_NOTIFICATION:
4663 case YANG_RPC:
4664 case YANG_TYPEDEF:
4665 case YANG_USES:
4666 case YANG_CUSTOM:
4667 mod_stmt = Y_MOD_BODY;
4668 break;
4669 default:
4670 /* error handled in the next switch */
4671 break;
4672 }
4673#undef CHECK_ORDER
4674
4675 prev_kw = kw;
4676 switch (kw) {
4677 /* module header */
4678 case YANG_YANG_VERSION:
4679 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4680 ctx->mod_version = submod->version;
4681 break;
4682 case YANG_BELONGS_TO:
4683 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4684 break;
4685
4686 /* linkage */
4687 case YANG_INCLUDE:
4688 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4689 break;
4690 case YANG_IMPORT:
4691 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4692 break;
4693
4694 /* meta */
4695 case YANG_ORGANIZATION:
4696 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4697 break;
4698 case YANG_CONTACT:
4699 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4700 break;
4701 case YANG_DESCRIPTION:
4702 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4703 break;
4704 case YANG_REFERENCE:
4705 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4706 break;
4707
4708 /* revision */
4709 case YANG_REVISION:
4710 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4711 break;
4712
4713 /* body */
4714 case YANG_ANYDATA:
4715 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
4716 /* fall through */
4717 case YANG_ANYXML:
4718 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4719 break;
4720 case YANG_CHOICE:
4721 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4722 break;
4723 case YANG_CONTAINER:
4724 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4725 break;
4726 case YANG_LEAF:
4727 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4728 break;
4729 case YANG_LEAF_LIST:
4730 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4731 break;
4732 case YANG_LIST:
4733 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4734 break;
4735 case YANG_USES:
4736 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4737 break;
4738
4739 case YANG_AUGMENT:
4740 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4741 break;
4742 case YANG_DEVIATION:
4743 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4744 break;
4745 case YANG_EXTENSION:
4746 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4747 break;
4748 case YANG_FEATURE:
4749 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4750 break;
4751 case YANG_GROUPING:
4752 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4753 break;
4754 case YANG_IDENTITY:
4755 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4756 break;
4757 case YANG_NOTIFICATION:
4758 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4759 break;
4760 case YANG_RPC:
4761 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4762 break;
4763 case YANG_TYPEDEF:
4764 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4765 break;
4766 case YANG_CUSTOM:
4767 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4768 break;
4769
4770 default:
4771 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
4772 return LY_EVALID;
4773 }
4774 }
4775 LY_CHECK_RET(ret);
4776
4777checks:
4778 /* finalize parent pointers to the reallocated items */
4779 LY_CHECK_RET(parse_sub_module_finalize((struct lysp_module*)submod));
4780
4781 /* mandatory substatements */
4782 if (!submod->belongsto) {
4783 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
4784 return LY_EVALID;
4785 }
4786
4787 /* submodules share the namespace with the module names, so there must not be
4788 * a submodule of the same name in the context, no need for revision matching */
4789 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4790 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
4791 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004792 return LY_EVALID;
4793 }
4794
Michal Vasko7fbc8162018-09-17 10:35:16 +02004795 return ret;
4796}
4797
Radek Krejcid4557c62018-09-17 11:42:09 +02004798LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004799yang_parse_submodule(struct lys_parser_ctx *context, const char *data, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004800{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004801 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004802 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004803 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004804 enum yang_keyword kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004805 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004806
4807 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004808 ret = get_keyword(context, &data, &kw, &word, &word_len);
4809 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004810
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004811 if (kw == YANG_MODULE) {
4812 LOGERR(context->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
4813 ret = LY_EINVAL;
4814 goto cleanup;
4815 } else if (kw != YANG_SUBMODULE) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004816 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004817 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004818 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004819 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004820 }
4821
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004822 mod_p = calloc(1, sizeof *mod_p);
4823 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4824 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004825
4826 /* substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004827 ret = parse_submodule(context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004828 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004829
4830 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004831 while(*data && isspace(*data)) {
4832 data++;
4833 }
4834 if (*data) {
4835 LOGVAL_YANG(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
4836 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004837 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004838 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004839 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004840
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004841 mod_p->parsing = 0;
4842 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004843
Radek Krejcibbe09a92018-11-08 09:36:54 +01004844cleanup:
4845 if (ret) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004846 lysp_submodule_free(context->ctx, mod_p);
4847 }
4848
4849 return ret;
4850}
4851
4852LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004853yang_parse_module(struct lys_parser_ctx *context, const char *data, struct lys_module *mod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004854{
4855 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004856 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004857 size_t word_len;
4858 enum yang_keyword kw;
4859 struct lysp_module *mod_p = NULL;
4860
4861 /* "module"/"submodule" */
4862 ret = get_keyword(context, &data, &kw, &word, &word_len);
4863 LY_CHECK_GOTO(ret, cleanup);
4864
4865 if (kw == YANG_SUBMODULE) {
4866 LOGERR(context->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
4867 ret = LY_EINVAL;
4868 goto cleanup;
4869 } else if (kw != YANG_MODULE) {
4870 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
4871 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004872 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004873 goto cleanup;
4874 }
4875
4876 mod_p = calloc(1, sizeof *mod_p);
4877 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4878 mod_p->mod = mod;
4879 mod_p->parsing = 1;
4880
4881 /* substatements */
4882 ret = parse_module(context, &data, mod_p);
4883 LY_CHECK_GOTO(ret, cleanup);
4884
4885 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004886 while(*data && isspace(*data)) {
4887 data++;
4888 }
4889 if (*data) {
4890 LOGVAL_YANG(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
4891 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004892 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004893 goto cleanup;
4894 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004895
4896 mod_p->parsing = 0;
4897 mod->parsed = mod_p;
4898
4899cleanup:
4900 if (ret) {
4901 lysp_module_free(mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004902 }
4903
Michal Vasko7fbc8162018-09-17 10:35:16 +02004904 return ret;
4905}