blob: 5d94c1336aecafc12e104f05a6d5c5047fabaec0 [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:
567 return LY_SUCCESS;
568}
569
Michal Vaskoea5abea2018-09-18 13:10:54 +0200570/**
571 * @brief Get another YANG string from the raw data.
572 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200573 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200574 * @param[in,out] data Data to read from, always moved to currently handled character.
575 * @param[in] arg Type of YANG keyword argument expected.
Radek Krejcid3ca0632019-04-16 16:54:54 +0200576 * @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 +0200577 * @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 +0200578 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
579 * set to NULL. Otherwise equal to \p word_p.
580 * @param[out] word_len Length of the read string.
581 *
582 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200583 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200584LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200585get_argument(struct lys_parser_ctx *ctx, const char **data, enum yang_arg arg,
Radek Krejcid3ca0632019-04-16 16:54:54 +0200586 uint16_t *flags, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200587{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200588 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200589
590 /* word buffer - dynamically allocated */
591 *word_b = NULL;
592
593 /* word pointer - just a pointer to data */
594 *word_p = NULL;
595
596 *word_len = 0;
597 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200598 switch (**data) {
599 case '\'':
600 case '\"':
601 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200602 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
603 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
604 "unquoted string character, optsep, semicolon or opening brace");
605 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200606 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200607 if (flags) {
608 (*flags) |= (**data) == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
609 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100610 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200611 goto str_end;
612 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200613 if ((*data)[1] == '/') {
614 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200615 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100616 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200617 } else if ((*data)[1] == '*') {
618 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200619 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100620 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200621 } else {
622 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100623 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 +0200624 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200625 break;
626 case ' ':
627 if (*word_len) {
628 /* word is finished */
629 goto str_end;
630 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200631 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200632 break;
633 case '\t':
634 if (*word_len) {
635 /* word is finished */
636 goto str_end;
637 }
638 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200639 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200640
641 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200642 break;
643 case '\n':
644 if (*word_len) {
645 /* word is finished */
646 goto str_end;
647 }
648 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200649 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200650
651 /* track line numbers */
652 ++ctx->line;
653
654 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200655 break;
656 case ';':
657 case '{':
658 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
659 /* word is finished */
660 goto str_end;
661 }
662
Radek Krejci44ceedc2018-10-02 15:54:31 +0200663 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200664 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200665 case '}':
666 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
667 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
668 "unquoted string character, optsep, semicolon or opening brace");
669 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200670 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200671 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 +0200672 break;
673 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200674 }
675
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200676 /* unexpected end of loop */
677 LOGVAL_YANG(ctx, LY_VCODE_EOF);
678 return LY_EVALID;
679
Michal Vasko7fbc8162018-09-17 10:35:16 +0200680str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200681 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200682 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200683 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
684 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
685 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200686 *word_p = *word_b;
687 }
688
689 return LY_SUCCESS;
690}
691
Michal Vaskoea5abea2018-09-18 13:10:54 +0200692/**
693 * @brief Get another YANG keyword from the raw data.
694 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200695 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200696 * @param[in,out] data Data to read from, always moved to currently handled character.
697 * @param[out] kw YANG keyword read.
698 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
699 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
700 *
701 * @return LY_ERR values.
702 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200703LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200704get_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 +0200705{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200706 int prefix;
707 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200708 unsigned int c;
709 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200710
711 if (word_p) {
712 *word_p = NULL;
713 *word_len = 0;
714 }
715
716 /* first skip "optsep", comments */
717 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200718 switch (**data) {
719 case '/':
720 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200721 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200722 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100723 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200724 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200725 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200726 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100727 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200728 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200729 /* error - not a comment after all, keyword cannot start with slash */
730 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
731 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200732 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200733 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200734 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200735 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200736 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200737 ctx->indent = 0;
738 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200739 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200740 /* skip whitespaces (optsep) */
741 ++ctx->indent;
742 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200743 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200744 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200745 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200746 break;
747 default:
748 /* either a keyword start or an invalid character */
749 goto keyword_start;
750 }
751
752 ++(*data);
753 }
754
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200755#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
756#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
757#define IF_KW_PREFIX_END }
758
Michal Vasko7fbc8162018-09-17 10:35:16 +0200759keyword_start:
760 word_start = *data;
761 *kw = YANG_NONE;
762
763 /* read the keyword itself */
764 switch (**data) {
765 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200766 MOVE_INPUT(ctx, data, 1);
767 IF_KW("rgument", 7, YANG_ARGUMENT)
768 else IF_KW("ugment", 6, YANG_AUGMENT)
769 else IF_KW("ction", 5, YANG_ACTION)
770 else IF_KW_PREFIX("ny", 2)
771 IF_KW("data", 4, YANG_ANYDATA)
772 else IF_KW("xml", 3, YANG_ANYXML)
773 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200774 break;
775 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200776 MOVE_INPUT(ctx, data, 1);
777 IF_KW("ase", 3, YANG_BASE)
778 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
779 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200780 break;
781 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200782 MOVE_INPUT(ctx, data, 1);
783 IF_KW("ase", 3, YANG_CASE)
784 else IF_KW("hoice", 5, YANG_CHOICE)
785 else IF_KW_PREFIX("on", 2)
786 IF_KW("fig", 3, YANG_CONFIG)
787 else IF_KW_PREFIX("ta", 2)
788 IF_KW("ct", 2, YANG_CONTACT)
789 else IF_KW("iner", 4, YANG_CONTAINER)
790 IF_KW_PREFIX_END
791 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200792 break;
793 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200794 MOVE_INPUT(ctx, data, 1);
795 IF_KW_PREFIX("e", 1)
796 IF_KW("fault", 5, YANG_DEFAULT)
797 else IF_KW("scription", 9, YANG_DESCRIPTION)
798 else IF_KW_PREFIX("viat", 4)
799 IF_KW("e", 1, YANG_DEVIATE)
800 else IF_KW("ion", 3, YANG_DEVIATION)
801 IF_KW_PREFIX_END
802 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200803 break;
804 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200805 MOVE_INPUT(ctx, data, 1);
806 IF_KW("num", 3, YANG_ENUM)
807 else IF_KW_PREFIX("rror-", 5)
808 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
809 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
810 IF_KW_PREFIX_END
811 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200812 break;
813 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200814 MOVE_INPUT(ctx, data, 1);
815 IF_KW("eature", 6, YANG_FEATURE)
816 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200817 break;
818 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200819 MOVE_INPUT(ctx, data, 1);
820 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200821 break;
822 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200823 MOVE_INPUT(ctx, data, 1);
824 IF_KW("dentity", 7, YANG_IDENTITY)
825 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
826 else IF_KW("mport", 5, YANG_IMPORT)
827 else IF_KW_PREFIX("n", 1)
828 IF_KW("clude", 5, YANG_INCLUDE)
829 else IF_KW("put", 3, YANG_INPUT)
830 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200831 break;
832 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200833 MOVE_INPUT(ctx, data, 1);
834 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200835 break;
836 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200837 MOVE_INPUT(ctx, data, 1);
838 IF_KW_PREFIX("e", 1)
839 IF_KW("af-list", 7, YANG_LEAF_LIST)
840 else IF_KW("af", 2, YANG_LEAF)
841 else IF_KW("ngth", 4, YANG_LENGTH)
842 IF_KW_PREFIX_END
843 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200844 break;
845 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200846 MOVE_INPUT(ctx, data, 1);
847 IF_KW_PREFIX("a", 1)
848 IF_KW("ndatory", 7, YANG_MANDATORY)
849 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
850 IF_KW_PREFIX_END
851 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
852 else IF_KW("ust", 3, YANG_MUST)
853 else IF_KW_PREFIX("od", 2)
854 IF_KW("ule", 3, YANG_MODULE)
855 else IF_KW("ifier", 5, YANG_MODIFIER)
856 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200857 break;
858 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200859 MOVE_INPUT(ctx, data, 1);
860 IF_KW("amespace", 8, YANG_NAMESPACE)
861 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200862 break;
863 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200864 MOVE_INPUT(ctx, data, 1);
865 IF_KW_PREFIX("r", 1)
866 IF_KW("dered-by", 8, YANG_ORDERED_BY)
867 else IF_KW("ganization", 10, YANG_ORGANIZATION)
868 IF_KW_PREFIX_END
869 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200870 break;
871 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200872 MOVE_INPUT(ctx, data, 1);
873 IF_KW("ath", 3, YANG_PATH)
874 else IF_KW("attern", 6, YANG_PATTERN)
875 else IF_KW("osition", 7, YANG_POSITION)
876 else IF_KW_PREFIX("re", 2)
877 IF_KW("fix", 3, YANG_PREFIX)
878 else IF_KW("sence", 5, YANG_PRESENCE)
879 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200880 break;
881 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200882 MOVE_INPUT(ctx, data, 1);
883 IF_KW("ange", 4, YANG_RANGE)
884 else IF_KW_PREFIX("e", 1)
885 IF_KW_PREFIX("f", 1)
886 IF_KW("erence", 6, YANG_REFERENCE)
887 else IF_KW("ine", 3, YANG_REFINE)
888 IF_KW_PREFIX_END
889 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
890 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
891 else IF_KW("vision", 6, YANG_REVISION)
892 IF_KW_PREFIX_END
893 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200894 break;
895 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200896 MOVE_INPUT(ctx, data, 1);
897 IF_KW("tatus", 5, YANG_STATUS)
898 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200899 break;
900 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200901 MOVE_INPUT(ctx, data, 1);
902 IF_KW("ypedef", 6, YANG_TYPEDEF)
903 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200904 break;
905 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200906 MOVE_INPUT(ctx, data, 1);
907 IF_KW_PREFIX("ni", 2)
908 IF_KW("que", 3, YANG_UNIQUE)
909 else IF_KW("ts", 2, YANG_UNITS)
910 IF_KW_PREFIX_END
911 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200912 break;
913 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200914 MOVE_INPUT(ctx, data, 1);
915 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200916 break;
917 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200918 MOVE_INPUT(ctx, data, 1);
919 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200920 break;
921 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200922 MOVE_INPUT(ctx, data, 1);
923 IF_KW("ang-version", 11, YANG_YANG_VERSION)
924 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200925 break;
926 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200927 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200928 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200929 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200930 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200931 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200932 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200933 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200934 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200935 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200936 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200937 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200938 default:
939 break;
940 }
941
Radek Krejci0904c162019-01-02 15:03:59 +0100942#undef IF_KW
943#undef IF_KW_PREFIX
944#undef IF_KW_PREFIX_END
945
Michal Vasko7fbc8162018-09-17 10:35:16 +0200946 if (*kw != YANG_NONE) {
947 /* make sure we have the whole keyword */
948 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200949 case '\n':
950 ++ctx->line;
951 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200952 case ' ':
953 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200954 /* mandatory "sep" */
955 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200956 case ':':
957 /* keyword is not actually a keyword, but prefix of an extension.
958 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
959 * and we will be checking the keyword (extension instance) itself */
960 prefix = 1;
961 MOVE_INPUT(ctx, data, 1);
962 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200963 case '{':
964 /* allowed only for input and output statements which can be without arguments */
965 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
966 break;
967 }
968 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200969 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200970 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200971 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
972 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200973 return LY_EVALID;
974 }
975 } else {
976 /* still can be an extension */
977 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200978extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200979 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200980 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
981 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200982 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200983 /* check character validity */
984 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200985 }
986 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200987 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200988 return LY_EVALID;
989 }
990
991 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200992 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200993 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200994 return LY_EVALID;
995 }
996
997 *kw = YANG_CUSTOM;
998 }
Radek Krejci626df482018-10-11 15:06:31 +0200999success:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001000 if (word_p) {
1001 *word_p = (char *)word_start;
1002 *word_len = *data - word_start;
1003 }
1004
1005 return LY_SUCCESS;
1006}
1007
Michal Vaskoea5abea2018-09-18 13:10:54 +02001008/**
1009 * @brief Parse extension instance substatements.
1010 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001011 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001012 * @param[in,out] data Data to read from, always moved to currently handled character.
1013 * @param[in] word Extension instance substatement name (keyword).
1014 * @param[in] word_len Extension instance substatement name length.
1015 * @param[in,out] child Children of this extension instance to add to.
1016 *
1017 * @return LY_ERR values.
1018 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001019static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001020parse_ext_substmt(struct lys_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001021 struct lysp_stmt **child)
1022{
1023 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001024 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001025 enum yang_keyword kw;
1026 struct lysp_stmt *stmt, *par_child;
1027
1028 stmt = calloc(1, sizeof *stmt);
1029 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
1030
Radek Krejcibb9b1982019-04-08 14:24:59 +02001031 /* insert into parent statements */
1032 if (!*child) {
1033 *child = stmt;
1034 } else {
1035 for (par_child = *child; par_child->next; par_child = par_child->next);
1036 par_child->next = stmt;
1037 }
1038
Radek Krejci44ceedc2018-10-02 15:54:31 +02001039 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001040
1041 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001042 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001043
Radek Krejci0ae092d2018-09-20 16:43:19 +02001044 if (word) {
1045 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001046 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001047 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001048 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001049 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001050 }
1051
Radek Krejci6d6556c2018-11-08 09:37:45 +01001052 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001053 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001054 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001055 return ret;
1056}
1057
Michal Vaskoea5abea2018-09-18 13:10:54 +02001058/**
1059 * @brief Parse extension instance.
1060 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001061 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001062 * @param[in,out] data Data to read from, always moved to currently handled character.
1063 * @param[in] ext_name Extension instance substatement name (keyword).
1064 * @param[in] ext_name_len Extension instance substatement name length.
1065 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1066 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1067 * @param[in,out] exts Extension instances to add to.
1068 *
1069 * @return LY_ERR values.
1070 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001071static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001072parse_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 +02001073 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1074{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001075 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001076 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001077 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001078 struct lysp_ext_instance *e;
1079 enum yang_keyword kw;
1080
Radek Krejci2c4e7172018-10-19 15:56:26 +02001081 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001082
1083 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001084 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001085 e->insubstmt = insubstmt;
1086 e->insubstmt_index = insubstmt_index;
1087
1088 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001089 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001090
Radek Krejci0ae092d2018-09-20 16:43:19 +02001091 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001092 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001093 }
1094
Radek Krejci6d6556c2018-11-08 09:37:45 +01001095 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001096 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001097 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001098 return ret;
1099}
1100
Michal Vaskoea5abea2018-09-18 13:10:54 +02001101/**
1102 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1103 * description, etc...
1104 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001105 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001106 * @param[in,out] data Data to read from, always moved to currently handled character.
1107 * @param[in] substmt Type of this substatement.
1108 * @param[in] substmt_index Index of this substatement.
1109 * @param[in,out] value Place to store the parsed value.
1110 * @param[in] arg Type of the YANG keyword argument (of the value).
1111 * @param[in,out] exts Extension instances to add to.
1112 *
1113 * @return LY_ERR values.
1114 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001115static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001116parse_text_field(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001117 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1118{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001119 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001120 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001121 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001122 enum yang_keyword kw;
1123
1124 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001125 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001126 return LY_EVALID;
1127 }
1128
1129 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001130 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131
1132 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001133 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001134
Radek Krejci6d6556c2018-11-08 09:37:45 +01001135 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001136 switch (kw) {
1137 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001138 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001139 break;
1140 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001141 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001142 return LY_EVALID;
1143 }
1144 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001145 return ret;
1146}
1147
Michal Vaskoea5abea2018-09-18 13:10:54 +02001148/**
1149 * @brief Parse the yang-version statement.
1150 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001151 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001152 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001153 * @param[out] version Storage for the parsed information.
1154 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001155 *
1156 * @return LY_ERR values.
1157 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001158static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001159parse_yangversion(struct lys_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001160{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001161 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001162 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001163 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001164 enum yang_keyword kw;
1165
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001166 if (*version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001167 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001168 return LY_EVALID;
1169 }
1170
1171 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001172 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001173
1174 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001175 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001176 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001177 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001178 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001179 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001180 free(buf);
1181 return LY_EVALID;
1182 }
1183 free(buf);
1184
Radek Krejci6d6556c2018-11-08 09:37:45 +01001185 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001186 switch (kw) {
1187 case YANG_CUSTOM:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001188 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 break;
1190 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001191 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001192 return LY_EVALID;
1193 }
1194 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001195 return ret;
1196}
1197
Michal Vaskoea5abea2018-09-18 13:10:54 +02001198/**
1199 * @brief Parse the belongs-to statement.
1200 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001201 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001202 * @param[in,out] data Data to read from, always moved to currently handled character.
1203 * @param[in,out] belongsto Place to store the parsed value.
1204 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1205 * @param[in,out] exts Extension instances to add to.
1206 *
1207 * @return LY_ERR values.
1208 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001209static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001210parse_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 +02001211{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001212 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001213 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001214 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001215 enum yang_keyword kw;
1216
1217 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001218 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001219 return LY_EVALID;
1220 }
1221
1222 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001223 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001224
Radek Krejci44ceedc2018-10-02 15:54:31 +02001225 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001226 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001227 switch (kw) {
1228 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001229 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001230 break;
1231 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001232 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001233 break;
1234 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001235 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001236 return LY_EVALID;
1237 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001238 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001239 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001240checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001241 /* mandatory substatements */
1242 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001243 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001244 return LY_EVALID;
1245 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001246 return ret;
1247}
1248
Michal Vaskoea5abea2018-09-18 13:10:54 +02001249/**
1250 * @brief Parse the revision-date statement.
1251 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001252 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001253 * @param[in,out] data Data to read from, always moved to currently handled character.
1254 * @param[in,out] rev Array to store the parsed value in.
1255 * @param[in,out] exts Extension instances to add to.
1256 *
1257 * @return LY_ERR values.
1258 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001259static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001260parse_revisiondate(struct lys_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001261{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001262 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001263 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001264 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001265 enum yang_keyword kw;
1266
1267 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001268 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001269 return LY_EVALID;
1270 }
1271
1272 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001273 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001274
1275 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001276 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001277 free(buf);
1278 return LY_EVALID;
1279 }
1280
1281 /* store value and spend buf if allocated */
1282 strncpy(rev, word, word_len);
1283 free(buf);
1284
Radek Krejci6d6556c2018-11-08 09:37:45 +01001285 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001286 switch (kw) {
1287 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001288 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001289 break;
1290 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001291 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001292 return LY_EVALID;
1293 }
1294 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001295 return ret;
1296}
1297
Michal Vaskoea5abea2018-09-18 13:10:54 +02001298/**
1299 * @brief Parse the include statement.
1300 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001301 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001302 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001303 * @param[in,out] data Data to read from, always moved to currently handled character.
1304 * @param[in,out] includes Parsed includes to add to.
1305 *
1306 * @return LY_ERR values.
1307 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001308static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001309parse_include(struct lys_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001310{
Radek Krejcid33273d2018-10-25 14:55:52 +02001311 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001312 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001313 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001314 enum yang_keyword kw;
1315 struct lysp_include *inc;
1316
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001317 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001318
1319 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001320 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001321
Radek Krejci086c7132018-10-26 15:29:04 +02001322 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1323
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001324 /* submodules share the namespace with the module names, so there must not be
1325 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001326 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001327 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1328 return LY_EVALID;
1329 }
1330
Radek Krejci6d6556c2018-11-08 09:37:45 +01001331 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001332 switch (kw) {
1333 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001334 YANG_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001335 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 +02001336 break;
1337 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001338 YANG_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001339 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 +02001340 break;
1341 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001342 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001343 break;
1344 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001345 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001346 break;
1347 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001348 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001349 return LY_EVALID;
1350 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001351 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001352 return ret;
1353}
1354
Michal Vaskoea5abea2018-09-18 13:10:54 +02001355/**
1356 * @brief Parse the import statement.
1357 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001358 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001359 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001360 * @param[in,out] data Data to read from, always moved to currently handled character.
1361 * @param[in,out] imports Parsed imports to add to.
1362 *
1363 * @return LY_ERR values.
1364 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001365static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001366parse_import(struct lys_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001367{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001368 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001369 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001370 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001371 enum yang_keyword kw;
1372 struct lysp_import *imp;
1373
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001374 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001375
1376 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001377 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001378 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001379
Radek Krejci6d6556c2018-11-08 09:37:45 +01001380 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001381 switch (kw) {
1382 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001383 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 +01001384 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001385 break;
1386 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001387 YANG_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001388 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 +02001389 break;
1390 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001391 YANG_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001392 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 +02001393 break;
1394 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001395 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001396 break;
1397 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001398 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001399 break;
1400 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001401 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001402 return LY_EVALID;
1403 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001404 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001405 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001406checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001407 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001408 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001409
1410 return ret;
1411}
1412
Michal Vaskoea5abea2018-09-18 13:10:54 +02001413/**
1414 * @brief Parse the revision statement.
1415 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001416 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001417 * @param[in,out] data Data to read from, always moved to currently handled character.
1418 * @param[in,out] revs Parsed revisions to add to.
1419 *
1420 * @return LY_ERR values.
1421 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001422static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001423parse_revision(struct lys_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001424{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001425 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001426 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001427 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001428 enum yang_keyword kw;
1429 struct lysp_revision *rev;
1430
Radek Krejci2c4e7172018-10-19 15:56:26 +02001431 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001432
1433 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001434 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001435
1436 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001437 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438 return LY_EVALID;
1439 }
1440
Radek Krejcib7db73a2018-10-24 14:18:40 +02001441 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001442 free(buf);
1443
Radek Krejci6d6556c2018-11-08 09:37:45 +01001444 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001445 switch (kw) {
1446 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001447 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 +02001448 break;
1449 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001450 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 +02001451 break;
1452 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001453 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001454 break;
1455 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001456 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001457 return LY_EVALID;
1458 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001459 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001460 return ret;
1461}
1462
Michal Vaskoea5abea2018-09-18 13:10:54 +02001463/**
1464 * @brief Parse a generic text field that can have more instances such as base.
1465 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001466 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001467 * @param[in,out] data Data to read from, always moved to currently handled character.
1468 * @param[in] substmt Type of this substatement.
1469 * @param[in,out] texts Parsed values to add to.
1470 * @param[in] arg Type of the expected argument.
1471 * @param[in,out] exts Extension instances to add to.
1472 *
1473 * @return LY_ERR values.
1474 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001475static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001476parse_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 +02001477 struct lysp_ext_instance **exts)
1478{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001479 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001480 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001481 const char **item;
1482 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001483 enum yang_keyword kw;
1484
1485 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001486 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001487
1488 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001489 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001490
Radek Krejci151a5b72018-10-19 14:21:44 +02001491 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001492 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001493 switch (kw) {
1494 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001495 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001496 break;
1497 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001498 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001499 return LY_EVALID;
1500 }
1501 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001502 return ret;
1503}
1504
Michal Vaskoea5abea2018-09-18 13:10:54 +02001505/**
1506 * @brief Parse the config statement.
1507 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001508 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001509 * @param[in,out] data Data to read from, always moved to currently handled character.
1510 * @param[in,out] flags Flags to add to.
1511 * @param[in,out] exts Extension instances to add to.
1512 *
1513 * @return LY_ERR values.
1514 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001515static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001516parse_config(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001517{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001518 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001519 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001520 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001521 enum yang_keyword kw;
1522
1523 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001524 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001525 return LY_EVALID;
1526 }
1527
1528 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001529 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001530
1531 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1532 *flags |= LYS_CONFIG_W;
1533 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1534 *flags |= LYS_CONFIG_R;
1535 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001536 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001537 free(buf);
1538 return LY_EVALID;
1539 }
1540 free(buf);
1541
Radek Krejci6d6556c2018-11-08 09:37:45 +01001542 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001543 switch (kw) {
1544 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001545 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001546 break;
1547 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001548 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001549 return LY_EVALID;
1550 }
1551 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001552 return ret;
1553}
1554
Michal Vaskoea5abea2018-09-18 13:10:54 +02001555/**
1556 * @brief Parse the mandatory statement.
1557 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001558 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001559 * @param[in,out] data Data to read from, always moved to currently handled character.
1560 * @param[in,out] flags Flags to add to.
1561 * @param[in,out] exts Extension instances to add to.
1562 *
1563 * @return LY_ERR values.
1564 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001565static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001566parse_mandatory(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001567{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001568 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001569 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001570 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001571 enum yang_keyword kw;
1572
1573 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001574 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001575 return LY_EVALID;
1576 }
1577
1578 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001579 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001580
1581 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1582 *flags |= LYS_MAND_TRUE;
1583 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1584 *flags |= LYS_MAND_FALSE;
1585 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001586 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001587 free(buf);
1588 return LY_EVALID;
1589 }
1590 free(buf);
1591
Radek Krejci6d6556c2018-11-08 09:37:45 +01001592 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001593 switch (kw) {
1594 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001595 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001596 break;
1597 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001598 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001599 return LY_EVALID;
1600 }
1601 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001602 return ret;
1603}
1604
Michal Vaskoea5abea2018-09-18 13:10:54 +02001605/**
1606 * @brief Parse a restriction such as range or length.
1607 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001608 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001609 * @param[in,out] data Data to read from, always moved to currently handled character.
1610 * @param[in] restr_kw Type of this particular restriction.
1611 * @param[in,out] exts Extension instances to add to.
1612 *
1613 * @return LY_ERR values.
1614 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001615static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001616parse_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 +02001617{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001618 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001619 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001620 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001621 enum yang_keyword kw;
1622
1623 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001624 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001625
Radek Krejci44ceedc2018-10-02 15:54:31 +02001626 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001627 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001628 switch (kw) {
1629 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001630 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 +02001631 break;
1632 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001633 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 +02001634 break;
1635 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001636 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 +02001637 break;
1638 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001639 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 +02001640 break;
1641 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001642 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001643 break;
1644 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001645 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001646 return LY_EVALID;
1647 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001648 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001649 return ret;
1650}
1651
Michal Vaskoea5abea2018-09-18 13:10:54 +02001652/**
1653 * @brief Parse a restriction that can have more instances such as must.
1654 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001655 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001656 * @param[in,out] data Data to read from, always moved to currently handled character.
1657 * @param[in] restr_kw Type of this particular restriction.
1658 * @param[in,out] restrs Restrictions to add to.
1659 *
1660 * @return LY_ERR values.
1661 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001662static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001663parse_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 +02001664{
1665 struct lysp_restr *restr;
1666
Radek Krejci2c4e7172018-10-19 15:56:26 +02001667 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001668 return parse_restr(ctx, data, restr_kw, restr);
1669}
1670
Michal Vaskoea5abea2018-09-18 13:10:54 +02001671/**
1672 * @brief Parse the status statement.
1673 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001674 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001675 * @param[in,out] data Data to read from, always moved to currently handled character.
1676 * @param[in,out] flags Flags to add to.
1677 * @param[in,out] exts Extension instances to add to.
1678 *
1679 * @return LY_ERR values.
1680 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001681static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001682parse_status(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001683{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001684 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001685 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001686 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001687 enum yang_keyword kw;
1688
1689 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001690 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001691 return LY_EVALID;
1692 }
1693
1694 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001695 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001696
1697 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1698 *flags |= LYS_STATUS_CURR;
1699 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1700 *flags |= LYS_STATUS_DEPRC;
1701 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1702 *flags |= LYS_STATUS_OBSLT;
1703 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001704 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001705 free(buf);
1706 return LY_EVALID;
1707 }
1708 free(buf);
1709
Radek Krejci6d6556c2018-11-08 09:37:45 +01001710 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001711 switch (kw) {
1712 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001713 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001714 break;
1715 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001716 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001717 return LY_EVALID;
1718 }
1719 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001720 return ret;
1721}
1722
Michal Vaskoea5abea2018-09-18 13:10:54 +02001723/**
1724 * @brief Parse the when statement.
1725 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001726 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001727 * @param[in,out] data Data to read from, always moved to currently handled character.
1728 * @param[in,out] when_p When pointer to parse to.
1729 *
1730 * @return LY_ERR values.
1731 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001732static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001733parse_when(struct lys_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001734{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001735 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001736 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001737 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001738 enum yang_keyword kw;
1739 struct lysp_when *when;
1740
1741 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001742 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001743 return LY_EVALID;
1744 }
1745
1746 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001747 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001748 *when_p = when;
1749
1750 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001751 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001752 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001753
Radek Krejci6d6556c2018-11-08 09:37:45 +01001754 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001755 switch (kw) {
1756 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001757 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 +02001758 break;
1759 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001760 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 +02001761 break;
1762 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001763 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001764 break;
1765 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001766 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001767 return LY_EVALID;
1768 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001769 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001770 return ret;
1771}
1772
Michal Vaskoea5abea2018-09-18 13:10:54 +02001773/**
1774 * @brief Parse the anydata or anyxml statement.
1775 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001776 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001777 * @param[in,out] data Data to read from, always moved to currently handled character.
1778 * @param[in] kw Type of this particular keyword.
1779 * @param[in,out] siblings Siblings to add to.
1780 *
1781 * @return LY_ERR values.
1782 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001783LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001784parse_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 +02001785{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001786 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001787 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001788 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001789 struct lysp_node *iter;
1790 struct lysp_node_anydata *any;
1791
1792 /* create structure */
1793 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001794 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001795 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001796 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001797
1798 /* insert into siblings */
1799 if (!*siblings) {
1800 *siblings = (struct lysp_node *)any;
1801 } else {
1802 for (iter = *siblings; iter->next; iter = iter->next);
1803 iter->next = (struct lysp_node *)any;
1804 }
1805
1806 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001807 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001808 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001809
1810 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001811 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001812 switch (kw) {
1813 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001814 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001815 break;
1816 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001817 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 +02001818 break;
1819 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001820 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 +02001821 break;
1822 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001823 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001824 break;
1825 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001826 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001827 break;
1828 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001829 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 +02001830 break;
1831 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001832 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833 break;
1834 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001835 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001836 break;
1837 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001838 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001839 break;
1840 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001841 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001842 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001843 return LY_EVALID;
1844 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001845 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001846 return ret;
1847}
1848
Michal Vaskoea5abea2018-09-18 13:10:54 +02001849/**
1850 * @brief Parse the value or position statement. Substatement of type enum statement.
1851 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001852 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001853 * @param[in,out] data Data to read from, always moved to currently handled character.
1854 * @param[in] val_kw Type of this particular keyword.
1855 * @param[in,out] value Value to write to.
1856 * @param[in,out] flags Flags to write to.
1857 * @param[in,out] exts Extension instances to add to.
1858 *
1859 * @return LY_ERR values.
1860 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001861static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001862parse_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 +02001863 struct lysp_ext_instance **exts)
1864{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001865 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001866 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001867 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001868 long int num;
1869 unsigned long int unum;
1870 enum yang_keyword kw;
1871
1872 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001873 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001874 return LY_EVALID;
1875 }
1876 *flags |= LYS_SET_VALUE;
1877
1878 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001879 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001880
1881 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 +02001882 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001883 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001884 }
1885
1886 errno = 0;
1887 if (val_kw == YANG_VALUE) {
1888 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001889 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
1890 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1891 goto error;
1892 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001893 } else {
1894 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001895 if (unum > UINT64_C(4294967295)) {
1896 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1897 goto error;
1898 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001899 }
1900 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001901 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001902 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001903 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001904 }
1905 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001906 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001907 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001908 }
1909 if (val_kw == YANG_VALUE) {
1910 *value = num;
1911 } else {
1912 *value = unum;
1913 }
1914 free(buf);
1915
Radek Krejci6d6556c2018-11-08 09:37:45 +01001916 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001917 switch (kw) {
1918 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001919 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 +02001920 break;
1921 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001922 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001923 return LY_EVALID;
1924 }
1925 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001926 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001927
1928error:
1929 free(buf);
1930 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001931}
1932
Michal Vaskoea5abea2018-09-18 13:10:54 +02001933/**
1934 * @brief Parse the enum or bit statement. Substatement of type statement.
1935 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001936 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001937 * @param[in,out] data Data to read from, always moved to currently handled character.
1938 * @param[in] enum_kw Type of this particular keyword.
1939 * @param[in,out] enums Enums or bits to add to.
1940 *
1941 * @return LY_ERR values.
1942 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001943static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001944parse_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 +02001945{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001946 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001947 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001948 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949 enum yang_keyword kw;
1950 struct lysp_type_enum *enm;
1951
Radek Krejci2c4e7172018-10-19 15:56:26 +02001952 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001953
1954 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001955 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 +01001956 if (enum_kw == YANG_ENUM) {
1957 if (!word_len) {
1958 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
1959 free(buf);
1960 return LY_EVALID;
1961 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
1962 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
1963 word_len, word);
1964 free(buf);
1965 return LY_EVALID;
1966 } else {
1967 for (u = 0; u < word_len; ++u) {
1968 if (iscntrl(word[u])) {
1969 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1970 word_len, word, u + 1);
1971 break;
1972 }
1973 }
1974 }
1975 } else { /* YANG_BIT */
1976
1977 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001978 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001979 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1980
Radek Krejci6d6556c2018-11-08 09:37:45 +01001981 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001982 switch (kw) {
1983 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001984 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 +02001985 break;
1986 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001987 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001988 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 +02001989 break;
1990 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001991 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 +02001992 break;
1993 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001994 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001995 break;
1996 case YANG_VALUE:
1997 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001998 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001999 break;
2000 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002001 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002002 break;
2003 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002004 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002005 return LY_EVALID;
2006 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002007 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002008 return ret;
2009}
2010
Michal Vaskoea5abea2018-09-18 13:10:54 +02002011/**
2012 * @brief Parse the fraction-digits statement. Substatement of type statement.
2013 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002014 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002015 * @param[in,out] data Data to read from, always moved to currently handled character.
2016 * @param[in,out] fracdig Value to write to.
2017 * @param[in,out] exts Extension instances to add to.
2018 *
2019 * @return LY_ERR values.
2020 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002021static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002022parse_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 +02002023{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002024 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002025 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002026 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002027 unsigned long int num;
2028 enum yang_keyword kw;
2029
2030 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002031 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002032 return LY_EVALID;
2033 }
2034
2035 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002036 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002037
2038 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002039 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002040 free(buf);
2041 return LY_EVALID;
2042 }
2043
2044 errno = 0;
2045 num = strtoul(word, &ptr, 10);
2046 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002047 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002048 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002049 free(buf);
2050 return LY_EVALID;
2051 }
2052 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002053 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002054 free(buf);
2055 return LY_EVALID;
2056 }
2057 *fracdig = num;
2058 free(buf);
2059
Radek Krejci6d6556c2018-11-08 09:37:45 +01002060 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002061 switch (kw) {
2062 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002063 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002064 break;
2065 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002066 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002067 return LY_EVALID;
2068 }
2069 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002070 return ret;
2071}
2072
Michal Vaskoea5abea2018-09-18 13:10:54 +02002073/**
2074 * @brief Parse the require-instance statement. Substatement of type statement.
2075 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002076 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002077 * @param[in,out] data Data to read from, always moved to currently handled character.
2078 * @param[in,out] reqinst Value to write to.
2079 * @param[in,out] flags Flags to write to.
2080 * @param[in,out] exts Extension instances to add to.
2081 *
2082 * @return LY_ERR values.
2083 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002084static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002085parse_type_reqinstance(struct lys_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002086 struct lysp_ext_instance **exts)
2087{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002088 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002089 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002090 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002091 enum yang_keyword kw;
2092
2093 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002094 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002095 return LY_EVALID;
2096 }
2097 *flags |= LYS_SET_REQINST;
2098
2099 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002100 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002101
2102 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2103 *reqinst = 1;
2104 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002105 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002106 free(buf);
2107 return LY_EVALID;
2108 }
2109 free(buf);
2110
Radek Krejci6d6556c2018-11-08 09:37:45 +01002111 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002112 switch (kw) {
2113 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002114 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002115 break;
2116 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002117 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002118 return LY_EVALID;
2119 }
2120 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002121 return ret;
2122}
2123
Michal Vaskoea5abea2018-09-18 13:10:54 +02002124/**
2125 * @brief Parse the modifier statement. Substatement of type pattern statement.
2126 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002127 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002128 * @param[in,out] data Data to read from, always moved to currently handled character.
2129 * @param[in,out] pat Value to write to.
2130 * @param[in,out] exts Extension instances to add to.
2131 *
2132 * @return LY_ERR values.
2133 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002134static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002135parse_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 +02002136{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002137 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002138 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002139 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002140 enum yang_keyword kw;
2141
2142 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002143 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002144 return LY_EVALID;
2145 }
2146
2147 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002148 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002149
2150 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002151 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002152 free(buf);
2153 return LY_EVALID;
2154 }
2155 free(buf);
2156
2157 /* replace the value in the dictionary */
2158 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002159 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002160 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002161 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002162
2163 assert(buf[0] == 0x06);
2164 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002165 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002166
Radek Krejci6d6556c2018-11-08 09:37:45 +01002167 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002168 switch (kw) {
2169 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002170 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002171 break;
2172 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002173 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002174 return LY_EVALID;
2175 }
2176 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002177 return ret;
2178}
2179
Michal Vaskoea5abea2018-09-18 13:10:54 +02002180/**
2181 * @brief Parse the pattern statement. Substatement of type statement.
2182 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002183 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002184 * @param[in,out] data Data to read from, always moved to currently handled character.
2185 * @param[in,out] patterns Restrictions to add to.
2186 *
2187 * @return LY_ERR values.
2188 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002190parse_type_pattern(struct lys_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002191{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002192 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002193 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002194 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002195 enum yang_keyword kw;
2196 struct lysp_restr *restr;
2197
Radek Krejci2c4e7172018-10-19 15:56:26 +02002198 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002199
2200 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002201 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002202
2203 /* add special meaning first byte */
2204 if (buf) {
2205 buf = realloc(buf, word_len + 2);
2206 word = buf;
2207 } else {
2208 buf = malloc(word_len + 2);
2209 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002210 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002211 memmove(buf + 1, word, word_len);
2212 buf[0] = 0x06; /* pattern's default regular-match flag */
2213 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2214 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002215
Radek Krejci6d6556c2018-11-08 09:37:45 +01002216 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002217 switch (kw) {
2218 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002219 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 +02002220 break;
2221 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002222 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 +02002223 break;
2224 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002225 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 +02002226 break;
2227 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002228 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 +02002229 break;
2230 case YANG_MODIFIER:
Radek Krejciceaf2122019-01-02 15:03:26 +01002231 YANG_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002232 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002233 break;
2234 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002235 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002236 break;
2237 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002238 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002239 return LY_EVALID;
2240 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002241 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002242 return ret;
2243}
2244
Michal Vaskoea5abea2018-09-18 13:10:54 +02002245/**
2246 * @brief Parse the type statement.
2247 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002248 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002249 * @param[in,out] data Data to read from, always moved to currently handled character.
2250 * @param[in,out] type Type to wrote to.
2251 *
2252 * @return LY_ERR values.
2253 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002254static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002255parse_type(struct lys_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002256{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002257 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002258 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002259 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002260 enum yang_keyword kw;
2261 struct lysp_type *nest_type;
2262
2263 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002264 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265 return LY_EVALID;
2266 }
2267
2268 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002269 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002270 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002271
Radek Krejci6d6556c2018-11-08 09:37:45 +01002272 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002273 switch (kw) {
2274 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002275 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 +01002276 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002277 break;
2278 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002279 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002280 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002281 break;
2282 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002283 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002284 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002285 break;
2286 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002287 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002288 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002289 break;
2290 case YANG_LENGTH:
2291 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002292 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002293 return LY_EVALID;
2294 }
2295 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002296 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002297
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002298 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002299 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002300 break;
2301 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002302 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 +01002303 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002304 break;
2305 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002306 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002307 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002308 break;
2309 case YANG_RANGE:
2310 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002311 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002312 return LY_EVALID;
2313 }
2314 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002315 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002316
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002317 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002318 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002319 break;
2320 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002321 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002322 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002323 break;
2324 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002325 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2326 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002327 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002328 break;
2329 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002330 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002331 break;
2332 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002333 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002334 return LY_EVALID;
2335 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002336 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002337 return ret;
2338}
2339
Michal Vaskoea5abea2018-09-18 13:10:54 +02002340/**
2341 * @brief Parse the leaf statement.
2342 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002343 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002344 * @param[in,out] data Data to read from, always moved to currently handled character.
2345 * @param[in,out] siblings Siblings to add to.
2346 *
2347 * @return LY_ERR values.
2348 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002349LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002350parse_leaf(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002351{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002352 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002353 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002354 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002355 enum yang_keyword kw;
2356 struct lysp_node *iter;
2357 struct lysp_node_leaf *leaf;
2358
2359 /* create structure */
2360 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002361 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002362 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002363 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002364
2365 /* insert into siblings */
2366 if (!*siblings) {
2367 *siblings = (struct lysp_node *)leaf;
2368 } else {
2369 for (iter = *siblings; iter->next; iter = iter->next);
2370 iter->next = (struct lysp_node *)leaf;
2371 }
2372
2373 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002374 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002375 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002376
2377 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002378 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002379 switch (kw) {
2380 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002381 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002382 break;
2383 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002384 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 +02002385 break;
2386 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002387 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 +02002388 break;
2389 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002390 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 +02002391 break;
2392 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002393 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002394 break;
2395 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002396 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002397 break;
2398 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002399 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 +02002400 break;
2401 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002402 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002403 break;
2404 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002405 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002406 break;
2407 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002408 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 +02002409 break;
2410 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002411 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002412 break;
2413 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002414 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002415 break;
2416 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002417 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002418 return LY_EVALID;
2419 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002420 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002421 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002422checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002423 /* mandatory substatements */
2424 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002425 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002426 return LY_EVALID;
2427 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002428 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
2429 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
2430 return LY_EVALID;
2431 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002432
2433 return ret;
2434}
2435
Michal Vaskoea5abea2018-09-18 13:10:54 +02002436/**
2437 * @brief Parse the max-elements statement.
2438 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002439 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002440 * @param[in,out] data Data to read from, always moved to currently handled character.
2441 * @param[in,out] max Value to write to.
2442 * @param[in,out] flags Flags to write to.
2443 * @param[in,out] exts Extension instances to add to.
2444 *
2445 * @return LY_ERR values.
2446 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002447LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002448parse_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 +02002449{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002450 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002451 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002452 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002453 unsigned long int num;
2454 enum yang_keyword kw;
2455
2456 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002457 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002458 return LY_EVALID;
2459 }
2460 *flags |= LYS_SET_MAX;
2461
2462 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002463 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002464
2465 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002466 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002467 free(buf);
2468 return LY_EVALID;
2469 }
2470
2471 if (strncmp(word, "unbounded", word_len)) {
2472 errno = 0;
2473 num = strtoul(word, &ptr, 10);
2474 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002475 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002476 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002477 free(buf);
2478 return LY_EVALID;
2479 }
2480 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002481 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002482 free(buf);
2483 return LY_EVALID;
2484 }
2485
2486 *max = num;
2487 }
2488 free(buf);
2489
Radek Krejci6d6556c2018-11-08 09:37:45 +01002490 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002491 switch (kw) {
2492 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002493 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002494 break;
2495 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002496 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002497 return LY_EVALID;
2498 }
2499 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002500 return ret;
2501}
2502
Michal Vaskoea5abea2018-09-18 13:10:54 +02002503/**
2504 * @brief Parse the min-elements statement.
2505 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002506 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002507 * @param[in,out] data Data to read from, always moved to currently handled character.
2508 * @param[in,out] min Value to write to.
2509 * @param[in,out] flags Flags to write to.
2510 * @param[in,out] exts Extension instances to add to.
2511 *
2512 * @return LY_ERR values.
2513 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002514LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002515parse_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 +02002516{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002517 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002518 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002519 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002520 unsigned long int num;
2521 enum yang_keyword kw;
2522
2523 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002524 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002525 return LY_EVALID;
2526 }
2527 *flags |= LYS_SET_MIN;
2528
2529 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002530 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002531
2532 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002533 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002534 free(buf);
2535 return LY_EVALID;
2536 }
2537
2538 errno = 0;
2539 num = strtoul(word, &ptr, 10);
2540 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002541 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002542 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002543 free(buf);
2544 return LY_EVALID;
2545 }
2546 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002547 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002548 free(buf);
2549 return LY_EVALID;
2550 }
2551 *min = num;
2552 free(buf);
2553
Radek Krejci6d6556c2018-11-08 09:37:45 +01002554 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002555 switch (kw) {
2556 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002557 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002558 break;
2559 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002560 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002561 return LY_EVALID;
2562 }
2563 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002564 return ret;
2565}
2566
Michal Vaskoea5abea2018-09-18 13:10:54 +02002567/**
2568 * @brief Parse the ordered-by statement.
2569 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002570 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002571 * @param[in,out] data Data to read from, always moved to currently handled character.
2572 * @param[in,out] flags Flags to write to.
2573 * @param[in,out] exts Extension instances to add to.
2574 *
2575 * @return LY_ERR values.
2576 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002577static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002578parse_orderedby(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002579{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002580 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002581 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002582 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002583 enum yang_keyword kw;
2584
2585 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002586 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002587 return LY_EVALID;
2588 }
2589
2590 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002591 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002592
2593 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2594 *flags |= LYS_ORDBY_SYSTEM;
2595 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2596 *flags |= LYS_ORDBY_USER;
2597 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002598 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002599 free(buf);
2600 return LY_EVALID;
2601 }
2602 free(buf);
2603
Radek Krejci6d6556c2018-11-08 09:37:45 +01002604 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002605 switch (kw) {
2606 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002607 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002608 break;
2609 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002610 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002611 return LY_EVALID;
2612 }
2613 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002614 return ret;
2615}
2616
Michal Vaskoea5abea2018-09-18 13:10:54 +02002617/**
2618 * @brief Parse the leaf-list statement.
2619 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002620 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002621 * @param[in,out] data Data to read from, always moved to currently handled character.
2622 * @param[in,out] siblings Siblings to add to.
2623 *
2624 * @return LY_ERR values.
2625 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002626LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002627parse_leaflist(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002629 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002630 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002631 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002632 enum yang_keyword kw;
2633 struct lysp_node *iter;
2634 struct lysp_node_leaflist *llist;
2635
2636 /* create structure */
2637 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002638 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002639 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002640 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002641
2642 /* insert into siblings */
2643 if (!*siblings) {
2644 *siblings = (struct lysp_node *)llist;
2645 } else {
2646 for (iter = *siblings; iter->next; iter = iter->next);
2647 iter->next = (struct lysp_node *)llist;
2648 }
2649
2650 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002651 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002652 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002653
2654 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002655 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002656 switch (kw) {
2657 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002658 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002659 break;
2660 case YANG_DEFAULT:
Radek Krejciceaf2122019-01-02 15:03:26 +01002661 YANG_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002662 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 +02002663 break;
2664 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002665 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 +02002666 break;
2667 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002668 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 +02002669 break;
2670 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002671 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002672 break;
2673 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002674 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002675 break;
2676 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002677 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002678 break;
2679 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002680 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002681 break;
2682 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002683 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 +02002684 break;
2685 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002686 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002687 break;
2688 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002689 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002690 break;
2691 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002692 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 +02002693 break;
2694 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002695 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002696 break;
2697 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002698 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002699 break;
2700 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002701 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002702 return LY_EVALID;
2703 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002704 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002705 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002706checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002707 /* mandatory substatements */
2708 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002709 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002710 return LY_EVALID;
2711 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002712 if ((llist->min) && (llist->dflts)) {
2713 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
2714 return LY_EVALID;
2715 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002716 if (llist->max && llist->min > llist->max) {
2717 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
2718 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2719 llist->min, llist->max);
2720 return LY_EVALID;
2721 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002722
2723 return ret;
2724}
2725
Michal Vaskoea5abea2018-09-18 13:10:54 +02002726/**
2727 * @brief Parse the refine statement.
2728 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002729 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002730 * @param[in,out] data Data to read from, always moved to currently handled character.
2731 * @param[in,out] refines Refines to add to.
2732 *
2733 * @return LY_ERR values.
2734 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002735static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002736parse_refine(struct lys_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002737{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002738 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002739 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002740 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002741 enum yang_keyword kw;
2742 struct lysp_refine *rf;
2743
Radek Krejci2c4e7172018-10-19 15:56:26 +02002744 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002745
2746 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002747 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002748 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002749
Radek Krejci6d6556c2018-11-08 09:37:45 +01002750 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002751 switch (kw) {
2752 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002753 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002754 break;
2755 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002756 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 +02002757 break;
2758 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002759 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 +02002760 break;
2761 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01002762 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002763 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 +02002764 break;
2765 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002766 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002767 break;
2768 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002769 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002770 break;
2771 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002772 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002773 break;
2774 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002775 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002776 break;
2777 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002778 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 +02002779 break;
2780 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002781 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 +02002782 break;
2783 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002784 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002785 break;
2786 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002787 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002788 return LY_EVALID;
2789 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002791 return ret;
2792}
2793
Michal Vaskoea5abea2018-09-18 13:10:54 +02002794/**
2795 * @brief Parse the typedef statement.
2796 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002797 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002798 * @param[in,out] data Data to read from, always moved to currently handled character.
2799 * @param[in,out] typedefs Typedefs to add to.
2800 *
2801 * @return LY_ERR values.
2802 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002803static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002804parse_typedef(struct lys_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002805{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002806 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002807 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002808 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809 enum yang_keyword kw;
2810 struct lysp_tpdf *tpdf;
2811
Radek Krejci2c4e7172018-10-19 15:56:26 +02002812 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002813
2814 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002815 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002816 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002817
2818 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002819 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002820 switch (kw) {
2821 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002822 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 +02002823 break;
2824 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002825 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 +02002826 break;
2827 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002828 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 +02002829 break;
2830 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002831 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002832 break;
2833 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002834 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002835 break;
2836 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002837 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 +02002838 break;
2839 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002840 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002841 break;
2842 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002843 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002844 return LY_EVALID;
2845 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002847 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002848checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002849 /* mandatory substatements */
2850 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002851 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002852 return LY_EVALID;
2853 }
2854
Radek Krejcibbe09a92018-11-08 09:36:54 +01002855 /* store data for collision check */
2856 if (parent) {
2857 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2858 }
2859
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 return ret;
2861}
2862
Michal Vaskoea5abea2018-09-18 13:10:54 +02002863/**
2864 * @brief Parse the input or output statement.
2865 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002866 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002867 * @param[in,out] data Data to read from, always moved to currently handled character.
2868 * @param[in] kw Type of this particular keyword
2869 * @param[in,out] inout_p Input/output pointer to write to.
2870 *
2871 * @return LY_ERR values.
2872 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002873static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002874parse_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 +02002875{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002876 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002877 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002878 size_t word_len;
Radek Krejci10113652018-11-14 16:56:50 +01002879 enum yang_keyword kw;
Radek Krejcie86bf772018-12-14 11:39:53 +01002880 unsigned int u;
2881 struct lysp_node *child;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002882
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002883 if (inout_p->nodetype) {
Radek Krejci10113652018-11-14 16:56:50 +01002884 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002885 return LY_EVALID;
2886 }
2887
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002888 /* initiate structure */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002889 inout_p->nodetype = &((struct lysp_action*)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002890 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891
2892 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002893 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002894 switch (kw) {
2895 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002896 YANG_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002897 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002898 case YANG_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002899 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002900 break;
2901 case YANG_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002902 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002903 break;
2904 case YANG_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002905 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002906 break;
2907 case YANG_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002908 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002909 break;
2910 case YANG_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002911 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002912 break;
2913 case YANG_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002914 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002915 break;
2916 case YANG_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002917 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002919 case YANG_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002920 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002921 break;
2922 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002923 YANG_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002924 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002925 break;
2926 case YANG_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002927 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002928 break;
2929 case YANG_CUSTOM:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002930 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002931 break;
2932 default:
Radek Krejci10113652018-11-14 16:56:50 +01002933 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002934 return LY_EVALID;
2935 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002936 }
Radek Krejcie86bf772018-12-14 11:39:53 +01002937 /* finalize parent pointers to the reallocated items */
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002938 LY_ARRAY_FOR(inout_p->groupings, u) {
2939 LY_LIST_FOR(inout_p->groupings[u].data, child) {
2940 child->parent = (struct lysp_node*)&inout_p->groupings[u];
Radek Krejcie86bf772018-12-14 11:39:53 +01002941 }
2942 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002943 return ret;
2944}
2945
Michal Vaskoea5abea2018-09-18 13:10:54 +02002946/**
2947 * @brief Parse the action statement.
2948 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002949 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002950 * @param[in,out] data Data to read from, always moved to currently handled character.
2951 * @param[in,out] actions Actions to add to.
2952 *
2953 * @return LY_ERR values.
2954 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002955LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002956parse_action(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002957{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002958 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002959 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002960 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002961 enum yang_keyword kw;
2962 struct lysp_action *act;
Radek Krejcie86bf772018-12-14 11:39:53 +01002963 struct lysp_node *child;
2964 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002965
Radek Krejci2c4e7172018-10-19 15:56:26 +02002966 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002967
2968 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002969 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002970 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002971 act->nodetype = LYS_ACTION;
2972 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002973
Radek Krejci6d6556c2018-11-08 09:37:45 +01002974 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975 switch (kw) {
2976 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002977 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 +02002978 break;
2979 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002980 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 +02002981 break;
2982 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002983 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 +02002984 break;
2985 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002986 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002987 break;
2988
2989 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002990 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002991 break;
2992 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002993 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002994 break;
2995
2996 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002997 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002998 break;
2999 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003000 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003001 break;
3002 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003003 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003004 break;
3005 default:
Radek Krejcif538ce52019-03-05 10:46:14 +01003006 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003007 return LY_EVALID;
3008 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003009 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003010 /* finalize parent pointers to the reallocated items */
3011 LY_ARRAY_FOR(act->groupings, u) {
3012 LY_LIST_FOR(act->groupings[u].data, child) {
3013 child->parent = (struct lysp_node*)&act->groupings[u];
3014 }
3015 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003016 return ret;
3017}
3018
Michal Vaskoea5abea2018-09-18 13:10:54 +02003019/**
3020 * @brief Parse the notification statement.
3021 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003022 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003023 * @param[in,out] data Data to read from, always moved to currently handled character.
3024 * @param[in,out] notifs Notifications to add to.
3025 *
3026 * @return LY_ERR values.
3027 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003028LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003029parse_notif(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003030{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003031 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003033 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003034 enum yang_keyword kw;
3035 struct lysp_notif *notif;
Radek Krejcie86bf772018-12-14 11:39:53 +01003036 struct lysp_node *child;
3037 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003038
Radek Krejci2c4e7172018-10-19 15:56:26 +02003039 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003040
3041 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003042 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003043 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003044 notif->nodetype = LYS_NOTIF;
3045 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003046
Radek Krejci6d6556c2018-11-08 09:37:45 +01003047 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003048 switch (kw) {
3049 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003050 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 +02003051 break;
3052 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003053 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 +02003054 break;
3055 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003056 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 +02003057 break;
3058 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003059 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003060 break;
3061
3062 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003063 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01003064 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003065 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003066 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003067 break;
3068 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003069 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003070 break;
3071 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003072 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003073 break;
3074 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003075 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076 break;
3077 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003078 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079 break;
3080 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003081 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003082 break;
3083 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003084 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003085 break;
3086
3087 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01003088 YANG_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003089 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003090 break;
3091 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003092 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003093 break;
3094 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003095 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003096 break;
3097 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003098 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003099 break;
3100 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003101 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003102 return LY_EVALID;
3103 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003104 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003105 /* finalize parent pointers to the reallocated items */
3106 LY_ARRAY_FOR(notif->groupings, u) {
3107 LY_LIST_FOR(notif->groupings[u].data, child) {
3108 child->parent = (struct lysp_node*)&notif->groupings[u];
3109 }
3110 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003111 return ret;
3112}
3113
Michal Vaskoea5abea2018-09-18 13:10:54 +02003114/**
3115 * @brief Parse the grouping statement.
3116 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003117 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003118 * @param[in,out] data Data to read from, always moved to currently handled character.
3119 * @param[in,out] groupings Groupings to add to.
3120 *
3121 * @return LY_ERR values.
3122 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003123LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003124parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003125{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003126 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003127 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003128 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003129 enum yang_keyword kw;
3130 struct lysp_grp *grp;
Radek Krejcie86bf772018-12-14 11:39:53 +01003131 struct lysp_node *child;
3132 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003133
Radek Krejci2c4e7172018-10-19 15:56:26 +02003134 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135
3136 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003137 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003138 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003139 grp->nodetype = LYS_GROUPING;
3140 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003141
Radek Krejci6d6556c2018-11-08 09:37:45 +01003142 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003143 switch (kw) {
3144 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003145 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003146 break;
3147 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003148 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003149 break;
3150 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003151 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003152 break;
3153
3154 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003155 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01003156 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003157 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003158 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003159 break;
3160 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003161 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003162 break;
3163 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003164 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003165 break;
3166 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003167 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003168 break;
3169 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003170 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003171 break;
3172 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003174 break;
3175 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003176 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003177 break;
3178
3179 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003180 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003181 break;
3182 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003183 YANG_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003184 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003185 break;
3186 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003187 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003188 break;
3189 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003190 YANG_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003191 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003192 break;
3193 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003194 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003195 break;
3196 default:
Radek Krejci10113652018-11-14 16:56:50 +01003197 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003198 return LY_EVALID;
3199 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003200 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003201 /* finalize parent pointers to the reallocated items */
3202 LY_ARRAY_FOR(grp->groupings, u) {
3203 LY_LIST_FOR(grp->groupings[u].data, child) {
3204 child->parent = (struct lysp_node*)&grp->groupings[u];
3205 }
3206 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003207 return ret;
3208}
3209
Michal Vaskoea5abea2018-09-18 13:10:54 +02003210/**
3211 * @brief Parse the refine statement.
3212 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003213 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003214 * @param[in,out] data Data to read from, always moved to currently handled character.
3215 * @param[in,out] augments Augments to add to.
3216 *
3217 * @return LY_ERR values.
3218 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003219LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003220parse_augment(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003221{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003222 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003223 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003224 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003225 enum yang_keyword kw;
3226 struct lysp_augment *aug;
3227
Radek Krejci2c4e7172018-10-19 15:56:26 +02003228 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003229
3230 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003231 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003232 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003233 aug->nodetype = LYS_AUGMENT;
3234 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003235
Radek Krejci6d6556c2018-11-08 09:37:45 +01003236 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003237 switch (kw) {
3238 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003239 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 +02003240 break;
3241 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003242 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 +02003243 break;
3244 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003245 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 +02003246 break;
3247 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003248 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003249 break;
3250 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003251 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003252 break;
3253
3254 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003255 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01003256 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003257 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003258 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003259 break;
3260 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003261 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003262 break;
3263 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003264 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003265 break;
3266 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003267 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003268 break;
3269 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003270 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003271 break;
3272 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003273 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003274 break;
3275 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003276 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003277 break;
3278 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003279 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003280 break;
3281
3282 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003283 YANG_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003284 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003285 break;
3286 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003287 YANG_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003288 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003289 break;
3290 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003291 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003292 break;
3293 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003294 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003295 return LY_EVALID;
3296 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003298 return ret;
3299}
3300
Michal Vaskoea5abea2018-09-18 13:10:54 +02003301/**
3302 * @brief Parse the uses statement.
3303 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003304 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003305 * @param[in,out] data Data to read from, always moved to currently handled character.
3306 * @param[in,out] siblings Siblings to add to.
3307 *
3308 * @return LY_ERR values.
3309 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003310LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003311parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003312{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003313 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003314 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003315 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003316 enum yang_keyword kw;
3317 struct lysp_node *iter;
3318 struct lysp_node_uses *uses;
3319
3320 /* create structure */
3321 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003322 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003323 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003324 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003325
3326 /* insert into siblings */
3327 if (!*siblings) {
3328 *siblings = (struct lysp_node *)uses;
3329 } else {
3330 for (iter = *siblings; iter->next; iter = iter->next);
3331 iter->next = (struct lysp_node *)uses;
3332 }
3333
3334 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003335 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003336 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003337
3338 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003339 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003340 switch (kw) {
3341 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003342 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 +02003343 break;
3344 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003345 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 +02003346 break;
3347 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003348 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 +02003349 break;
3350 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003351 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003352 break;
3353 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003354 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003355 break;
3356
3357 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003358 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003359 break;
3360 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003361 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003362 break;
3363 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003364 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003365 break;
3366 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003367 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003368 return LY_EVALID;
3369 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003370 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003371 return ret;
3372}
3373
Michal Vaskoea5abea2018-09-18 13:10:54 +02003374/**
3375 * @brief Parse the case statement.
3376 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003377 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003378 * @param[in,out] data Data to read from, always moved to currently handled character.
3379 * @param[in,out] siblings Siblings to add to.
3380 *
3381 * @return LY_ERR values.
3382 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003383LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003384parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003385{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003386 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003387 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003388 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003389 enum yang_keyword kw;
3390 struct lysp_node *iter;
3391 struct lysp_node_case *cas;
3392
3393 /* create structure */
3394 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003395 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003396 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003397 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003398
3399 /* insert into siblings */
3400 if (!*siblings) {
3401 *siblings = (struct lysp_node *)cas;
3402 } else {
3403 for (iter = *siblings; iter->next; iter = iter->next);
3404 iter->next = (struct lysp_node *)cas;
3405 }
3406
3407 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003408 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003409 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003410
3411 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003412 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003413 switch (kw) {
3414 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003415 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 +02003416 break;
3417 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003418 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 +02003419 break;
3420 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003421 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 +02003422 break;
3423 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003424 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003425 break;
3426 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003427 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003428 break;
3429
3430 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003431 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003432 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003433 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003434 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003435 break;
3436 case YANG_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003437 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003438 break;
3439 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003440 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003441 break;
3442 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003443 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003444 break;
3445 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003446 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003447 break;
3448 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003449 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003450 break;
3451 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003452 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003453 break;
3454 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003455 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003456 break;
3457 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003458 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003459 return LY_EVALID;
3460 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003461 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003462 return ret;
3463}
3464
Michal Vaskoea5abea2018-09-18 13:10:54 +02003465/**
3466 * @brief Parse the choice statement.
3467 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003468 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003469 * @param[in,out] data Data to read from, always moved to currently handled character.
3470 * @param[in,out] siblings Siblings to add to.
3471 *
3472 * @return LY_ERR values.
3473 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003474LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003475parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003476{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003477 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003478 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003479 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003480 enum yang_keyword kw;
3481 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003482 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483
3484 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003485 choice = calloc(1, sizeof *choice);
3486 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3487 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003488 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003489
3490 /* insert into siblings */
3491 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003492 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003493 } else {
3494 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003495 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003496 }
3497
3498 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003499 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003500 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003501
3502 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003503 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003504 switch (kw) {
3505 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003506 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003507 break;
3508 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003509 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 +02003510 break;
3511 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003512 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 +02003513 break;
3514 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003515 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003516 break;
3517 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003518 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 +02003519 break;
3520 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003521 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003522 break;
3523 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003524 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003525 break;
3526 case YANG_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003527 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 +02003528 break;
3529
3530 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003531 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003532 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003533 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003534 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003535 break;
3536 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003537 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003538 break;
3539 case YANG_CHOICE:
Radek Krejciceaf2122019-01-02 15:03:26 +01003540 YANG_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003541 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003542 break;
3543 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003544 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003545 break;
3546 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003547 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003548 break;
3549 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003550 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003551 break;
3552 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003553 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003554 break;
3555 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003556 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003557 break;
3558 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003559 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003560 return LY_EVALID;
3561 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003562 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003563 LY_CHECK_RET(ret);
3564checks:
3565 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
3566 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
3567 return LY_EVALID;
3568 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569 return ret;
3570}
3571
Michal Vaskoea5abea2018-09-18 13:10:54 +02003572/**
3573 * @brief Parse the container statement.
3574 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003575 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003576 * @param[in,out] data Data to read from, always moved to currently handled character.
3577 * @param[in,out] siblings Siblings to add to.
3578 *
3579 * @return LY_ERR values.
3580 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003581LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003582parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003583{
3584 LY_ERR ret = 0;
3585 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003586 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003587 enum yang_keyword kw;
3588 struct lysp_node *iter;
3589 struct lysp_node_container *cont;
Radek Krejcie86bf772018-12-14 11:39:53 +01003590 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003591
3592 /* create structure */
3593 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003594 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003595 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003596 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003597
3598 /* insert into siblings */
3599 if (!*siblings) {
3600 *siblings = (struct lysp_node *)cont;
3601 } else {
3602 for (iter = *siblings; iter->next; iter = iter->next);
3603 iter->next = (struct lysp_node *)cont;
3604 }
3605
3606 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003607 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003608 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003609
3610 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003611 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003612 switch (kw) {
3613 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003614 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003615 break;
3616 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003617 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003618 break;
3619 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003620 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003621 break;
3622 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003623 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 +02003624 break;
3625 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003626 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003627 break;
3628 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003629 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003630 break;
3631 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003632 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 +02003633 break;
3634
3635 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003636 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003637 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003638 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003639 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003640 break;
3641 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003642 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643 break;
3644 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003645 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003646 break;
3647 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003648 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003649 break;
3650 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003651 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003652 break;
3653 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003654 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003655 break;
3656 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003657 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003658 break;
3659
3660 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003661 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003662 break;
3663 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003664 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003665 break;
3666 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003667 YANG_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003668 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003669 break;
3670 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003671 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003672 break;
3673 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003674 YANG_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003675 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003676 break;
3677 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003678 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003679 break;
3680 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003681 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003682 return LY_EVALID;
3683 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003684 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003685 /* finalize parent pointers to the reallocated items */
3686 LY_ARRAY_FOR(cont->groupings, u) {
3687 LY_LIST_FOR(cont->groupings[u].data, iter) {
3688 iter->parent = (struct lysp_node*)&cont->groupings[u];
3689 }
3690 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003691 return ret;
3692}
3693
Michal Vaskoea5abea2018-09-18 13:10:54 +02003694/**
3695 * @brief Parse the list statement.
3696 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003697 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003698 * @param[in,out] data Data to read from, always moved to currently handled character.
3699 * @param[in,out] siblings Siblings to add to.
3700 *
3701 * @return LY_ERR values.
3702 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003703LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003704parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003705{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003706 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003707 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003708 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003709 enum yang_keyword kw;
3710 struct lysp_node *iter;
3711 struct lysp_node_list *list;
Radek Krejcie86bf772018-12-14 11:39:53 +01003712 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003713
3714 /* create structure */
3715 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003716 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003717 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003718 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003719
3720 /* insert into siblings */
3721 if (!*siblings) {
3722 *siblings = (struct lysp_node *)list;
3723 } else {
3724 for (iter = *siblings; iter->next; iter = iter->next);
3725 iter->next = (struct lysp_node *)list;
3726 }
3727
3728 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003729 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003730 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003731
3732 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003733 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003734 switch (kw) {
3735 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003736 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003737 break;
3738 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003739 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 +02003740 break;
3741 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003742 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 +02003743 break;
3744 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003745 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 +02003746 break;
3747 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003748 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003749 break;
3750 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003751 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003752 break;
3753 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003754 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 +02003755 break;
3756 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003757 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003758 break;
3759 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003760 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003761 break;
3762 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003763 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003764 break;
3765 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003766 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 +02003767 break;
3768
3769 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003770 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003771 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003772 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003773 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003774 break;
3775 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003776 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003777 break;
3778 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003779 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003780 break;
3781 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003782 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003783 break;
3784 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003785 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003786 break;
3787 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003788 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003789 break;
3790 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003791 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003792 break;
3793
3794 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003795 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003796 break;
3797 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003798 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003799 break;
3800 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003801 YANG_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003802 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003803 break;
3804 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003805 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003806 break;
3807 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003808 YANG_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003809 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003810 break;
3811 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003812 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003813 break;
3814 default:
Radek Krejci10113652018-11-14 16:56:50 +01003815 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003816 return LY_EVALID;
3817 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003818 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003819 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01003820 /* finalize parent pointers to the reallocated items */
3821 LY_ARRAY_FOR(list->groupings, u) {
3822 LY_LIST_FOR(list->groupings[u].data, iter) {
3823 iter->parent = (struct lysp_node*)&list->groupings[u];
3824 }
3825 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003826checks:
3827 if (list->max && list->min > list->max) {
3828 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
3829 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3830 list->min, list->max);
3831 return LY_EVALID;
3832 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003833
3834 return ret;
3835}
3836
Michal Vaskoea5abea2018-09-18 13:10:54 +02003837/**
3838 * @brief Parse the yin-element statement.
3839 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003840 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003841 * @param[in,out] data Data to read from, always moved to currently handled character.
3842 * @param[in,out] flags Flags to write to.
3843 * @param[in,out] exts Extension instances to add to.
3844 *
3845 * @return LY_ERR values.
3846 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003847static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003848parse_yinelement(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003849{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003850 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003851 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003852 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003853 enum yang_keyword kw;
3854
3855 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003856 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857 return LY_EVALID;
3858 }
3859
3860 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003861 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003862
3863 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3864 *flags |= LYS_YINELEM_TRUE;
3865 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3866 *flags |= LYS_YINELEM_FALSE;
3867 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003868 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003869 free(buf);
3870 return LY_EVALID;
3871 }
3872 free(buf);
3873
Radek Krejci6d6556c2018-11-08 09:37:45 +01003874 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875 switch (kw) {
3876 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003877 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3878 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003879 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003880 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003881 return LY_EVALID;
3882 }
3883 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003884 return ret;
3885}
3886
Michal Vaskoea5abea2018-09-18 13:10:54 +02003887/**
3888 * @brief Parse the yin-element statement.
3889 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003890 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003891 * @param[in,out] data Data to read from, always moved to currently handled character.
3892 * @param[in,out] argument Value to write to.
3893 * @param[in,out] flags Flags to write to.
3894 * @param[in,out] exts Extension instances to add to.
3895 *
3896 * @return LY_ERR values.
3897 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003898static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003899parse_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 +02003900{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003901 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003902 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003903 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003904 enum yang_keyword kw;
3905
3906 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003907 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908 return LY_EVALID;
3909 }
3910
3911 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003912 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003913 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003914
Radek Krejci6d6556c2018-11-08 09:37:45 +01003915 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003916 switch (kw) {
3917 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003918 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003919 break;
3920 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003921 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 break;
3923 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003924 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003925 return LY_EVALID;
3926 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003927 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003928 return ret;
3929}
3930
Michal Vaskoea5abea2018-09-18 13:10:54 +02003931/**
3932 * @brief Parse the extension statement.
3933 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003934 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003935 * @param[in,out] data Data to read from, always moved to currently handled character.
3936 * @param[in,out] extensions Extensions to add to.
3937 *
3938 * @return LY_ERR values.
3939 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003940static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003941parse_extension(struct lys_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003942{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003943 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003944 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003945 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003946 enum yang_keyword kw;
3947 struct lysp_ext *ex;
3948
Radek Krejci2c4e7172018-10-19 15:56:26 +02003949 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003950
3951 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003952 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003953 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003954
Radek Krejci6d6556c2018-11-08 09:37:45 +01003955 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003956 switch (kw) {
3957 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003958 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 +02003959 break;
3960 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003961 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 +02003962 break;
3963 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003964 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003965 break;
3966 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003967 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003968 break;
3969 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003970 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003971 break;
3972 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003973 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003974 return LY_EVALID;
3975 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003976 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003977 return ret;
3978}
3979
Michal Vaskoea5abea2018-09-18 13:10:54 +02003980/**
3981 * @brief Parse the deviate statement.
3982 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003983 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003984 * @param[in,out] data Data to read from, always moved to currently handled character.
3985 * @param[in,out] deviates Deviates to add to.
3986 *
3987 * @return LY_ERR values.
3988 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003989LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003990parse_deviate(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003991{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003992 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003993 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003994 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003995 enum yang_keyword kw;
3996 struct lysp_deviate *iter, *d;
3997 struct lysp_deviate_add *d_add = NULL;
3998 struct lysp_deviate_rpl *d_rpl = NULL;
3999 struct lysp_deviate_del *d_del = NULL;
4000 const char **d_units, ***d_uniques, ***d_dflts;
4001 struct lysp_restr **d_musts;
4002 uint16_t *d_flags;
4003 uint32_t *d_min, *d_max;
4004
4005 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004006 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004007
4008 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4009 dev_mod = LYS_DEV_NOT_SUPPORTED;
4010 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4011 dev_mod = LYS_DEV_ADD;
4012 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4013 dev_mod = LYS_DEV_REPLACE;
4014 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4015 dev_mod = LYS_DEV_DELETE;
4016 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004017 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004018 free(buf);
4019 return LY_EVALID;
4020 }
4021 free(buf);
4022
4023 /* create structure */
4024 switch (dev_mod) {
4025 case LYS_DEV_NOT_SUPPORTED:
4026 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004027 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004028 break;
4029 case LYS_DEV_ADD:
4030 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004031 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004032 d = (struct lysp_deviate *)d_add;
4033 d_units = &d_add->units;
4034 d_uniques = &d_add->uniques;
4035 d_dflts = &d_add->dflts;
4036 d_musts = &d_add->musts;
4037 d_flags = &d_add->flags;
4038 d_min = &d_add->min;
4039 d_max = &d_add->max;
4040 break;
4041 case LYS_DEV_REPLACE:
4042 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004043 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004044 d = (struct lysp_deviate *)d_rpl;
4045 d_units = &d_rpl->units;
4046 d_flags = &d_rpl->flags;
4047 d_min = &d_rpl->min;
4048 d_max = &d_rpl->max;
4049 break;
4050 case LYS_DEV_DELETE:
4051 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004052 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004053 d = (struct lysp_deviate *)d_del;
4054 d_units = &d_del->units;
4055 d_uniques = &d_del->uniques;
4056 d_dflts = &d_del->dflts;
4057 d_musts = &d_del->musts;
4058 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004059 break;
4060 default:
4061 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004062 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004063 }
4064 d->mod = dev_mod;
4065
4066 /* insert into siblings */
4067 if (!*deviates) {
4068 *deviates = d;
4069 } else {
4070 for (iter = *deviates; iter->next; iter = iter->next);
4071 iter->next = d;
4072 }
4073
Radek Krejci6d6556c2018-11-08 09:37:45 +01004074 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004075 switch (kw) {
4076 case YANG_CONFIG:
4077 switch (dev_mod) {
4078 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004079 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004080 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004081 return LY_EVALID;
4082 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004083 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004084 break;
4085 }
4086 break;
4087 case YANG_DEFAULT:
4088 switch (dev_mod) {
4089 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004090 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004091 return LY_EVALID;
4092 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004093 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 +02004094 break;
4095 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004096 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 +02004097 break;
4098 }
4099 break;
4100 case YANG_MANDATORY:
4101 switch (dev_mod) {
4102 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004103 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004104 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004105 return LY_EVALID;
4106 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004107 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004108 break;
4109 }
4110 break;
4111 case YANG_MAX_ELEMENTS:
4112 switch (dev_mod) {
4113 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004114 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004115 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004116 return LY_EVALID;
4117 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004118 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004119 break;
4120 }
4121 break;
4122 case YANG_MIN_ELEMENTS:
4123 switch (dev_mod) {
4124 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004125 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004126 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004127 return LY_EVALID;
4128 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004129 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004130 break;
4131 }
4132 break;
4133 case YANG_MUST:
4134 switch (dev_mod) {
4135 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004136 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004137 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004138 return LY_EVALID;
4139 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004140 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004141 break;
4142 }
4143 break;
4144 case YANG_TYPE:
4145 switch (dev_mod) {
4146 case LYS_DEV_NOT_SUPPORTED:
4147 case LYS_DEV_ADD:
4148 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004149 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004150 return LY_EVALID;
4151 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004152 if (d_rpl->type) {
4153 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4154 return LY_EVALID;
4155 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004156 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004157 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004158 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004159 break;
4160 }
4161 break;
4162 case YANG_UNIQUE:
4163 switch (dev_mod) {
4164 case LYS_DEV_NOT_SUPPORTED:
4165 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004166 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004167 return LY_EVALID;
4168 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004169 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 +02004170 break;
4171 }
4172 break;
4173 case YANG_UNITS:
4174 switch (dev_mod) {
4175 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004176 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004177 return LY_EVALID;
4178 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004179 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 +02004180 break;
4181 }
4182 break;
4183 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004184 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004185 break;
4186 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004187 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004188 return LY_EVALID;
4189 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004190 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004191 return ret;
4192}
4193
Michal Vaskoea5abea2018-09-18 13:10:54 +02004194/**
4195 * @brief Parse the deviation statement.
4196 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004197 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004198 * @param[in,out] data Data to read from, always moved to currently handled character.
4199 * @param[in,out] deviations Deviations to add to.
4200 *
4201 * @return LY_ERR values.
4202 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004203LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004204parse_deviation(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004205{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004206 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004207 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004208 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004209 enum yang_keyword kw;
4210 struct lysp_deviation *dev;
4211
Radek Krejci2c4e7172018-10-19 15:56:26 +02004212 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004213
4214 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004215 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004216 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004217
Radek Krejci6d6556c2018-11-08 09:37:45 +01004218 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004219 switch (kw) {
4220 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004221 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 +02004222 break;
4223 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004224 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004225 break;
4226 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004227 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 +02004228 break;
4229 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004230 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004231 break;
4232 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004233 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004234 return LY_EVALID;
4235 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004237 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004238checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004239 /* mandatory substatements */
4240 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004241 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004242 return LY_EVALID;
4243 }
4244
4245 return ret;
4246}
4247
Michal Vaskoea5abea2018-09-18 13:10:54 +02004248/**
4249 * @brief Parse the feature statement.
4250 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004251 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004252 * @param[in,out] data Data to read from, always moved to currently handled character.
4253 * @param[in,out] features Features to add to.
4254 *
4255 * @return LY_ERR values.
4256 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004257LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004258parse_feature(struct lys_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004259{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004260 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004261 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004262 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004263 enum yang_keyword kw;
4264 struct lysp_feature *feat;
4265
Radek Krejci2c4e7172018-10-19 15:56:26 +02004266 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004267
4268 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004269 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004270 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004271
Radek Krejci6d6556c2018-11-08 09:37:45 +01004272 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004273 switch (kw) {
4274 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004275 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 +02004276 break;
4277 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004278 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 +02004279 break;
4280 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004281 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 +02004282 break;
4283 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004284 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004285 break;
4286 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004287 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004288 break;
4289 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004290 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004291 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004292 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004293 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004294 return ret;
4295}
4296
Michal Vaskoea5abea2018-09-18 13:10:54 +02004297/**
4298 * @brief Parse the identity statement.
4299 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004300 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004301 * @param[in,out] data Data to read from, always moved to currently handled character.
4302 * @param[in,out] identities Identities to add to.
4303 *
4304 * @return LY_ERR values.
4305 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004306LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004307parse_identity(struct lys_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004308{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004309 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004310 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004311 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004312 enum yang_keyword kw;
4313 struct lysp_ident *ident;
4314
Radek Krejci2c4e7172018-10-19 15:56:26 +02004315 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316
4317 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004318 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004319 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004320
Radek Krejci6d6556c2018-11-08 09:37:45 +01004321 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004322 switch (kw) {
4323 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004324 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 +02004325 break;
4326 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01004327 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004328 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 +02004329 break;
4330 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004331 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 +02004332 break;
4333 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004334 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004335 break;
4336 case YANG_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004337 if (ident->bases && ctx->mod_version < 2) {
Radek Krejci10113652018-11-14 16:56:50 +01004338 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4339 return LY_EVALID;
4340 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004341 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 +02004342 break;
4343 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004344 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004345 break;
4346 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004347 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004348 return LY_EVALID;
4349 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004350 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004351 return ret;
4352}
4353
Michal Vaskoea5abea2018-09-18 13:10:54 +02004354/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004355 * @brief Finalize some of the (sub)module structure after parsing.
4356 *
4357 * Update parent pointers in the nodes inside grouping/RPC/Notification, which could be reallocated.
4358 *
4359 * @param[in] mod Parsed module to be updated.
4360 * @return LY_ERR value (currently only LY_SUCCESS, but it can change in future).
4361 */
4362static LY_ERR
4363parse_sub_module_finalize(struct lysp_module *mod)
4364{
4365 unsigned int u;
4366 struct lysp_node *child;
4367
4368 /* finalize parent pointers to the reallocated items */
4369 LY_ARRAY_FOR(mod->groupings, u) {
4370 LY_LIST_FOR(mod->groupings[u].data, child) {
4371 child->parent = (struct lysp_node*)&mod->groupings[u];
4372 }
4373 }
4374
4375 /* TODO the same finalization for rpcs and notifications, do also in the relevant nodes */
4376
4377 return LY_SUCCESS;
4378}
4379
4380/**
4381 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004382 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004383 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004384 * @param[in,out] data Data to read from, always moved to currently handled character.
4385 * @param[in,out] mod Module to write to.
4386 *
4387 * @return LY_ERR values.
4388 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004389LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004390parse_module(struct lys_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004391{
4392 LY_ERR ret = 0;
4393 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004394 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004395 enum yang_keyword kw, prev_kw = 0;
4396 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004397 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004398
4399 /* (sub)module name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004400 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004401 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004402
Radek Krejci6d6556c2018-11-08 09:37:45 +01004403 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004404
Radek Krejcie3846472018-10-15 15:24:51 +02004405#define CHECK_ORDER(SECTION) \
4406 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4407
Michal Vasko7fbc8162018-09-17 10:35:16 +02004408 switch (kw) {
4409 /* module header */
4410 case YANG_NAMESPACE:
4411 case YANG_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004412 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4413 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004414 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004415 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004416 break;
4417 /* linkage */
4418 case YANG_INCLUDE:
4419 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004420 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004421 break;
4422 /* meta */
4423 case YANG_ORGANIZATION:
4424 case YANG_CONTACT:
4425 case YANG_DESCRIPTION:
4426 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004427 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428 break;
4429
4430 /* revision */
4431 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004432 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004433 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004434 /* body */
4435 case YANG_ANYDATA:
4436 case YANG_ANYXML:
4437 case YANG_AUGMENT:
4438 case YANG_CHOICE:
4439 case YANG_CONTAINER:
4440 case YANG_DEVIATION:
4441 case YANG_EXTENSION:
4442 case YANG_FEATURE:
4443 case YANG_GROUPING:
4444 case YANG_IDENTITY:
4445 case YANG_LEAF:
4446 case YANG_LEAF_LIST:
4447 case YANG_LIST:
4448 case YANG_NOTIFICATION:
4449 case YANG_RPC:
4450 case YANG_TYPEDEF:
4451 case YANG_USES:
4452 case YANG_CUSTOM:
4453 mod_stmt = Y_MOD_BODY;
4454 break;
4455 default:
4456 /* error handled in the next switch */
4457 break;
4458 }
Radek Krejcie3846472018-10-15 15:24:51 +02004459#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004460
Radek Krejcie3846472018-10-15 15:24:51 +02004461 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004462 switch (kw) {
4463 /* module header */
4464 case YANG_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004465 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4466 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004467 break;
4468 case YANG_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004469 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 +02004470 break;
4471 case YANG_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004472 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 +02004473 break;
4474
4475 /* linkage */
4476 case YANG_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004477 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004478 break;
4479 case YANG_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004480 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004481 break;
4482
4483 /* meta */
4484 case YANG_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004485 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 +02004486 break;
4487 case YANG_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004488 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 +02004489 break;
4490 case YANG_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004491 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 +02004492 break;
4493 case YANG_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004494 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 +02004495 break;
4496
4497 /* revision */
4498 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004499 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004500 break;
4501
4502 /* body */
4503 case YANG_ANYDATA:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004504 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004505 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004506 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004507 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004508 break;
4509 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004510 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004511 break;
4512 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004513 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004514 break;
4515 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004516 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004517 break;
4518 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004519 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004520 break;
4521 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004522 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004523 break;
4524 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004525 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004526 break;
4527
4528 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004529 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004530 break;
4531 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004532 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004533 break;
4534 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004535 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004536 break;
4537 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004538 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004539 break;
4540 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004541 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004542 break;
4543 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004544 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004545 break;
4546 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004547 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004548 break;
4549 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004550 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004551 break;
4552 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004553 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004554 break;
4555 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004556 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004557 break;
4558
4559 default:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004560 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004561 return LY_EVALID;
4562 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004563 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004564 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004565
Radek Krejci6d6556c2018-11-08 09:37:45 +01004566checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004567 /* finalize parent pointers to the reallocated items */
4568 LY_CHECK_RET(parse_sub_module_finalize(mod));
4569
Michal Vasko7fbc8162018-09-17 10:35:16 +02004570 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004571 if (!mod->mod->ns) {
4572 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
4573 return LY_EVALID;
4574 } else if (!mod->mod->prefix) {
4575 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
4576 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004577 }
4578
Radek Krejcie9e987e2018-10-31 12:50:27 +01004579 /* submodules share the namespace with the module names, so there must not be
4580 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004581 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4582 if (dup) {
4583 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
4584 return LY_EVALID;
4585 }
4586
4587 return ret;
4588}
4589
4590/**
4591 * @brief Parse submodule substatements.
4592 *
4593 * @param[in] ctx yang parser context for logging.
4594 * @param[in,out] data Data to read from, always moved to currently handled character.
4595 * @param[out] submod Parsed submodule structure.
4596 *
4597 * @return LY_ERR values.
4598 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004599LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004600parse_submodule(struct lys_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004601{
4602 LY_ERR ret = 0;
4603 char *buf, *word;
4604 size_t word_len;
4605 enum yang_keyword kw, prev_kw = 0;
4606 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4607 struct lysp_submodule *dup;
4608
4609 /* submodule name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004610 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004611 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4612
4613 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4614
4615#define CHECK_ORDER(SECTION) \
4616 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4617
4618 switch (kw) {
4619 /* module header */
4620 case YANG_BELONGS_TO:
4621 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4622 break;
4623 case YANG_YANG_VERSION:
4624 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4625 break;
4626 /* linkage */
4627 case YANG_INCLUDE:
4628 case YANG_IMPORT:
4629 CHECK_ORDER(Y_MOD_LINKAGE);
4630 break;
4631 /* meta */
4632 case YANG_ORGANIZATION:
4633 case YANG_CONTACT:
4634 case YANG_DESCRIPTION:
4635 case YANG_REFERENCE:
4636 CHECK_ORDER(Y_MOD_META);
4637 break;
4638
4639 /* revision */
4640 case YANG_REVISION:
4641 CHECK_ORDER(Y_MOD_REVISION);
4642 break;
4643 /* body */
4644 case YANG_ANYDATA:
4645 case YANG_ANYXML:
4646 case YANG_AUGMENT:
4647 case YANG_CHOICE:
4648 case YANG_CONTAINER:
4649 case YANG_DEVIATION:
4650 case YANG_EXTENSION:
4651 case YANG_FEATURE:
4652 case YANG_GROUPING:
4653 case YANG_IDENTITY:
4654 case YANG_LEAF:
4655 case YANG_LEAF_LIST:
4656 case YANG_LIST:
4657 case YANG_NOTIFICATION:
4658 case YANG_RPC:
4659 case YANG_TYPEDEF:
4660 case YANG_USES:
4661 case YANG_CUSTOM:
4662 mod_stmt = Y_MOD_BODY;
4663 break;
4664 default:
4665 /* error handled in the next switch */
4666 break;
4667 }
4668#undef CHECK_ORDER
4669
4670 prev_kw = kw;
4671 switch (kw) {
4672 /* module header */
4673 case YANG_YANG_VERSION:
4674 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4675 ctx->mod_version = submod->version;
4676 break;
4677 case YANG_BELONGS_TO:
4678 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4679 break;
4680
4681 /* linkage */
4682 case YANG_INCLUDE:
4683 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4684 break;
4685 case YANG_IMPORT:
4686 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4687 break;
4688
4689 /* meta */
4690 case YANG_ORGANIZATION:
4691 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4692 break;
4693 case YANG_CONTACT:
4694 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4695 break;
4696 case YANG_DESCRIPTION:
4697 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4698 break;
4699 case YANG_REFERENCE:
4700 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4701 break;
4702
4703 /* revision */
4704 case YANG_REVISION:
4705 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4706 break;
4707
4708 /* body */
4709 case YANG_ANYDATA:
4710 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
4711 /* fall through */
4712 case YANG_ANYXML:
4713 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4714 break;
4715 case YANG_CHOICE:
4716 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4717 break;
4718 case YANG_CONTAINER:
4719 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4720 break;
4721 case YANG_LEAF:
4722 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4723 break;
4724 case YANG_LEAF_LIST:
4725 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4726 break;
4727 case YANG_LIST:
4728 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4729 break;
4730 case YANG_USES:
4731 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4732 break;
4733
4734 case YANG_AUGMENT:
4735 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4736 break;
4737 case YANG_DEVIATION:
4738 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4739 break;
4740 case YANG_EXTENSION:
4741 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4742 break;
4743 case YANG_FEATURE:
4744 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4745 break;
4746 case YANG_GROUPING:
4747 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4748 break;
4749 case YANG_IDENTITY:
4750 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4751 break;
4752 case YANG_NOTIFICATION:
4753 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4754 break;
4755 case YANG_RPC:
4756 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4757 break;
4758 case YANG_TYPEDEF:
4759 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4760 break;
4761 case YANG_CUSTOM:
4762 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4763 break;
4764
4765 default:
4766 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
4767 return LY_EVALID;
4768 }
4769 }
4770 LY_CHECK_RET(ret);
4771
4772checks:
4773 /* finalize parent pointers to the reallocated items */
4774 LY_CHECK_RET(parse_sub_module_finalize((struct lysp_module*)submod));
4775
4776 /* mandatory substatements */
4777 if (!submod->belongsto) {
4778 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
4779 return LY_EVALID;
4780 }
4781
4782 /* submodules share the namespace with the module names, so there must not be
4783 * a submodule of the same name in the context, no need for revision matching */
4784 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4785 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
4786 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004787 return LY_EVALID;
4788 }
4789
Michal Vasko7fbc8162018-09-17 10:35:16 +02004790 return ret;
4791}
4792
Radek Krejcid4557c62018-09-17 11:42:09 +02004793LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004794yang_parse_submodule(struct lys_parser_ctx *context, const char *data, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004795{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004796 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004797 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004798 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004799 enum yang_keyword kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004800 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004801
4802 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004803 ret = get_keyword(context, &data, &kw, &word, &word_len);
4804 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004805
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004806 if (kw == YANG_MODULE) {
4807 LOGERR(context->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
4808 ret = LY_EINVAL;
4809 goto cleanup;
4810 } else if (kw != YANG_SUBMODULE) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004811 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004812 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004813 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004814 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004815 }
4816
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004817 mod_p = calloc(1, sizeof *mod_p);
4818 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4819 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004820
4821 /* substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004822 ret = parse_submodule(context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004823 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004824
4825 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004826 while(*data && isspace(*data)) {
4827 data++;
4828 }
4829 if (*data) {
4830 LOGVAL_YANG(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
4831 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004832 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004833 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004834 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004835
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004836 mod_p->parsing = 0;
4837 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004838
Radek Krejcibbe09a92018-11-08 09:36:54 +01004839cleanup:
4840 if (ret) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004841 lysp_submodule_free(context->ctx, mod_p);
4842 }
4843
4844 return ret;
4845}
4846
4847LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004848yang_parse_module(struct lys_parser_ctx *context, const char *data, struct lys_module *mod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004849{
4850 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004851 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004852 size_t word_len;
4853 enum yang_keyword kw;
4854 struct lysp_module *mod_p = NULL;
4855
4856 /* "module"/"submodule" */
4857 ret = get_keyword(context, &data, &kw, &word, &word_len);
4858 LY_CHECK_GOTO(ret, cleanup);
4859
4860 if (kw == YANG_SUBMODULE) {
4861 LOGERR(context->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
4862 ret = LY_EINVAL;
4863 goto cleanup;
4864 } else if (kw != YANG_MODULE) {
4865 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
4866 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004867 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004868 goto cleanup;
4869 }
4870
4871 mod_p = calloc(1, sizeof *mod_p);
4872 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4873 mod_p->mod = mod;
4874 mod_p->parsing = 1;
4875
4876 /* substatements */
4877 ret = parse_module(context, &data, mod_p);
4878 LY_CHECK_GOTO(ret, cleanup);
4879
4880 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004881 while(*data && isspace(*data)) {
4882 data++;
4883 }
4884 if (*data) {
4885 LOGVAL_YANG(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
4886 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004887 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004888 goto cleanup;
4889 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004890
4891 mod_p->parsing = 0;
4892 mod->parsed = mod_p;
4893
4894cleanup:
4895 if (ret) {
4896 lysp_module_free(mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004897 }
4898
Michal Vasko7fbc8162018-09-17 10:35:16 +02004899 return ret;
4900}