blob: a45a979cae24a085cd4b58f69072450ac34203fe [file] [log] [blame]
Michal Vasko7fbc8162018-09-17 10:35:16 +02001/**
2 * @file parser_yang.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YANG parser
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <errno.h>
22#include <ctype.h>
23#include <string.h>
24#include <dirent.h>
25#include <assert.h>
26
27#include "common.h"
28#include "context.h"
29#include "libyang.h"
Radek Krejci70853c52018-10-15 14:46:16 +020030#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020031
32/* Macro to check YANG's yang-char grammar rule */
33#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
34 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
35 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
36 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
37 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
38 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
39 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
40 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
41 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
42 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
43
Radek Krejciceaf2122019-01-02 15:03:26 +010044/**
45 * @brief Try to find object with MEMBER string matching the IDENT in the given ARRAY.
46 * Macro logs an error message and returns LY_EVALID in case of existence of a matching object.
47 *
48 * @param[in] CTX yang parser context for logging.
49 * @param[in] ARRAY [sized array](@ref sizedarrays) of a generic objects with member named MEMBER to search.
50 * @param[in] MEMBER Name of the member of the objects in the ARRAY to compare.
51 * @param[in] STMT Name of the compared YANG statements for logging.
52 * @param[in] IDENT String trying to find in the ARRAY's objects inside the MEMBER member.
53 */
Radek Krejcifaa1eac2018-10-30 14:34:55 +010054#define CHECK_UNIQUENESS(CTX, ARRAY, MEMBER, STMT, IDENT) \
55 if (ARRAY) { \
56 for (unsigned int u = 0; u < LY_ARRAY_SIZE(ARRAY) - 1; ++u) { \
57 if (!strcmp((ARRAY)[u].MEMBER, IDENT)) { \
58 LOGVAL_YANG(CTX, LY_VCODE_DUPIDENT, IDENT, STMT); \
59 return LY_EVALID; \
60 } \
61 } \
62 }
63
Radek Krejciceaf2122019-01-02 15:03:26 +010064/**
65 * @brief Insert WORD into the libyang context's dictionary and store as TARGET.
66 * @param[in] CTX yang parser context to access libyang context.
67 * @param[in] BUF buffer in case the word is not a constant and can be inserted directly (zero-copy)
68 * @param[out] TARGET variable where to store the pointer to the inserted value.
69 * @param[in] WORD string to store.
70 * @param[in] LEN length of the string in WORD to store.
71 */
Radek Krejci9fcacc12018-10-11 15:59:11 +020072#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
73 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
74 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020075
Radek Krejciceaf2122019-01-02 15:03:26 +010076/**
77 * @brief Move the DATA pointer by COUNT items. Also updates the indent value in yang parser context
78 * @param[in] CTX yang parser context to update its indent value.
79 * @param[in,out] DATA pointer to move
80 * @param[in] COUNT number of items for which the DATA pointer is supposed to move on.
81 */
Radek Krejci2b610482019-01-02 13:36:09 +010082#define MOVE_INPUT(CTX, DATA, COUNT) (*(DATA))+=COUNT;(CTX)->indent+=COUNT
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020083
Michal Vaskoea5abea2018-09-18 13:10:54 +020084/**
85 * @brief Loop through all substatements providing, return if there are none.
86 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020087 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020088 * @param[in] DATA Raw data to read from.
89 * @param[out] KW YANG keyword read.
90 * @param[out] WORD Pointer to the keyword itself.
91 * @param[out] WORD_LEN Length of the keyword.
92 * @param[out] ERR Variable for error storing.
93 *
94 * @return In case there are no substatements or a fatal error encountered.
95 */
Radek Krejci6d6556c2018-11-08 09:37:45 +010096#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010097 LY_CHECK_RET(get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020098 if (KW == YANG_SEMICOLON) { \
Radek Krejci6d6556c2018-11-08 09:37:45 +010099 CHECKGOTO; \
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100100 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +0200101 } \
102 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +0200103 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +0200104 return LY_EVALID; \
105 } \
106 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
107 !ERR && (KW != YANG_RIGHT_BRACE); \
108 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
109
Radek Krejciceaf2122019-01-02 15:03:26 +0100110/**
111 * @brief Check module version is at least 2 (YANG 1.1) because of the keyword presence.
112 * Logs error message and returns LY_EVALID in case of module in YANG version 1.0.
113 * @param[in] CTX yang parser context to get current module and for logging.
114 * @param[in] KW keyword allowed only in YANG version 1.1 (or later) - for logging.
115 * @param[in] PARENT parent statement where the KW is present - for logging.
116 */
117#define YANG_CHECK_STMTVER2_RET(CTX, KW, PARENT) \
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100118 if ((CTX)->mod_version < 2) {LOGVAL_YANG((CTX), LY_VCODE_INCHILDSTMT2, KW, PARENT); return LY_EVALID;}
Radek Krejci10113652018-11-14 16:56:50 +0100119
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100120static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
121static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
122static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
123static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
124static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
125static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200126
Michal Vaskoea5abea2018-09-18 13:10:54 +0200127/**
128 * @brief Add another character to dynamic buffer, a low-level function.
129 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200130 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200131 *
Radek Krejci404251e2018-10-09 12:06:44 +0200132 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200133 * @param[in, out] input Input string to process.
134 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200135 * @param[in,out] buf Buffer to use, can be moved by realloc().
136 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200137 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200138 *
139 * @return LY_ERR values.
140 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200141static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200142buf_add_char(struct ly_ctx *ctx, const char **input, size_t len, char **buf, size_t *buf_len, size_t *buf_used)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200143{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200144 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200145 *buf_len += 16;
146 *buf = ly_realloc(*buf, *buf_len);
147 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
148 }
Radek Krejcic0917392019-04-10 13:04:04 +0200149 if (*buf_used) {
150 memcpy(&(*buf)[*buf_used], *input, len);
151 } else {
152 memcpy(*buf, *input, len);
153 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200154
Radek Krejci44ceedc2018-10-02 15:54:31 +0200155 (*buf_used) += len;
156 (*input) += len;
157
Michal Vasko7fbc8162018-09-17 10:35:16 +0200158 return LY_SUCCESS;
159}
160
Michal Vaskoea5abea2018-09-18 13:10:54 +0200161/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200162 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200163 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200164 * @param[in] ctx yang parser context for logging.
165 * @param[in] c UTF8 code point of a character to check.
166 * @return LY_ERR values.
167 */
168static LY_ERR
169check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
170{
171 if (!is_yangutf8char(c)) {
172 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
173 return LY_EVALID;
174 }
175 return LY_SUCCESS;
176}
177
178/**
179 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
180 *
181 * @param[in] ctx yang parser context for logging.
182 * @param[in] c UTF8 code point of a character to check.
183 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200184 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
185 * 0 - colon not yet found (no prefix)
186 * 1 - \p c is the colon character
187 * 2 - prefix already processed, now processing the identifier
188 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200189 * If the identifier cannot be prefixed, NULL is expected.
190 * @return LY_ERR values.
191 */
192static LY_ERR
193check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
194{
195 if (first || (prefix && (*prefix) == 1)) {
196 if (!is_yangidentstartchar(c)) {
197 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
198 return LY_EVALID;
199 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200200 if (prefix) {
201 if (first) {
202 (*prefix) = 0;
203 } else {
204 (*prefix) = 2;
205 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200206 }
207 } else if (c == ':' && prefix && (*prefix) == 0) {
208 (*prefix) = 1;
209 } else if (!is_yangidentchar(c)) {
210 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
211 return LY_EVALID;
212 }
213
214 return LY_SUCCESS;
215}
216
217/**
218 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
219 *
220 * @param[in] ctx yang parser context for logging.
221 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
222 * when function returns.
223 * @param[in] arg Type of the input string to select method of checking character validity.
224 * @param[in,out] word_p Word pointer. If buffer (\p word_b) was not yet needed, it is just a pointer to the first
Michal Vaskoea5abea2018-09-18 13:10:54 +0200225 * stored character. If buffer was needed (\p word_b is non-NULL or \p need_buf is set), it is pointing to the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200226 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
227 * @param[in,out] word_b Word buffer. Is kept NULL as long as it is not requested (word is a substring of the data).
Michal Vaskoea5abea2018-09-18 13:10:54 +0200228 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200229 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200230 *
231 * @return LY_ERR values.
232 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200233static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200234buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
235 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200236{
Radek Krejci404251e2018-10-09 12:06:44 +0200237 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200238 unsigned int c;
239 size_t len;
240
Radek Krejcif29b7c32019-04-09 16:17:49 +0200241 /* check valid combination of input paremeters - if need_buf specified, word_b must be provided */
242 assert(!need_buf || (need_buf && word_b));
243
Radek Krejci44ceedc2018-10-02 15:54:31 +0200244 /* get UTF8 code point (and number of bytes coding the character) */
245 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
246 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
247 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200248 if (c == '\n') {
249 ctx->indent = 0;
250 } else {
251 /* note - even the multibyte character is count as 1 */
252 ++ctx->indent;
253 }
254
Radek Krejci44ceedc2018-10-02 15:54:31 +0200255 /* check character validity */
256 switch (arg) {
257 case Y_IDENTIF_ARG:
258 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
259 break;
260 case Y_PREF_IDENTIF_ARG:
261 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
262 break;
263 case Y_STR_ARG:
264 case Y_MAYBE_STR_ARG:
265 LY_CHECK_RET(check_stringchar(ctx, c));
266 break;
267 }
268
Michal Vasko7fbc8162018-09-17 10:35:16 +0200269 if (word_b && *word_b) {
270 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200271 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200272 return LY_EMEM;
273 }
274
275 /* in case of realloc */
276 *word_p = *word_b;
Radek Krejcif29b7c32019-04-09 16:17:49 +0200277 } else if (word_b && need_buf) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200278 /* first time we need a buffer, copy everything read up to now */
279 if (*word_len) {
280 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200281 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200282 *buf_len = *word_len;
283 memcpy(*word_b, *word_p, *word_len);
284 }
285
286 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200287 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200288 return LY_EMEM;
289 }
290
291 /* in case of realloc */
292 *word_p = *word_b;
293 } else {
294 /* just remember the first character pointer */
295 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200296 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200297 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200298 /* ... and update the word's length */
299 (*word_len) += len;
300 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200301 }
302
303 return LY_SUCCESS;
304}
305
Michal Vaskoea5abea2018-09-18 13:10:54 +0200306/**
307 * @brief Skip YANG comment in data.
308 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200309 * @param[in] ctx yang parser context for logging.
310 * @param[in,out] data Data to read from, automatically moved after the comment.
311 * @param[in] comment Type of the comment to process:
312 * 1 for a one-line comment,
313 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200314 *
315 * @return LY_ERR values.
316 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200317static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200318skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200319{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200320 /* internal statuses: 0 - comment ended,
321 * 1 - in line comment,
322 * 2 - in block comment,
323 * 3 - in block comment with last read character '*'
324 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200325 while (**data && comment) {
326 switch (comment) {
327 case 1:
328 if (**data == '\n') {
329 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200330 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200331 }
332 break;
333 case 2:
334 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200335 comment = 3;
336 } else if (**data == '\n') {
337 ++ctx->line;
338 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200339 break;
340 case 3:
341 if (**data == '/') {
342 comment = 0;
343 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200344 if (**data == '\n') {
345 ++ctx->line;
346 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200347 comment = 2;
348 }
349 break;
350 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200351 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200352 }
353
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200354 if (**data == '\n') {
355 ctx->indent = 0;
356 } else {
357 ++ctx->indent;
358 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200359 ++(*data);
360 }
361
362 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200363 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200364 return LY_EVALID;
365 }
366
367 return LY_SUCCESS;
368}
369
Michal Vaskoea5abea2018-09-18 13:10:54 +0200370/**
371 * @brief Read a quoted string from data.
372 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200373 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200374 * @param[in,out] data Data to read from, always moved to currently handled character.
375 * @param[in] arg Type of YANG keyword argument expected.
376 * @param[out] word_p Pointer to the read quoted string.
377 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
378 * set to NULL. Otherwise equal to \p word_p.
379 * @param[out] word_len Length of the read quoted string.
380 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
381 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
382 * indenation in the final quoted string.
383 *
384 * @return LY_ERR values.
385 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200386static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200387read_qstring(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len,
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200388 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200389{
390 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
391 * 4 - string finished, now skipping whitespaces looking for +,
392 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200393 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200394 const char *c;
395
396 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200397 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200398 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200399 } else {
400 assert(**data == '\'');
401 string = 1;
402 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200403 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200404
405 while (**data && string) {
406 switch (string) {
407 case 1:
408 switch (**data) {
409 case '\'':
410 /* string may be finished, but check for + */
411 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200412 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200413 break;
414 default:
415 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200416 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200417 break;
418 }
419 break;
420 case 2:
421 switch (**data) {
422 case '\"':
423 /* string may be finished, but check for + */
424 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200425 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200426 break;
427 case '\\':
428 /* special character following */
429 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200430 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200431 break;
432 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200433 if (current_indent < block_indent) {
434 ++current_indent;
435 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200436 } else {
437 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200438 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200439 }
440 break;
441 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200442 if (current_indent < block_indent) {
443 assert(need_buf);
444 current_indent += 8;
445 ctx->indent += 8;
446 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
447 /* store leftover spaces from the tab */
448 c = " ";
449 LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200450 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200451 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200452 } else {
453 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200454 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200455 /* additional characters for indentation - only 1 was count in buf_store_char */
456 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200457 }
458 break;
459 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200460 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200461 /* we will be removing the indents so we need our own buffer */
462 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200463
464 /* remove trailing tabs and spaces */
465 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
466 --(*word_len);
467 }
468
469 /* start indentation */
470 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200471 }
472
473 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200474 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
475
476 /* maintain line number */
477 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200478
479 /* reset context indentation counter for possible string after this one */
480 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200481 break;
482 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200483 /* first non-whitespace character, stop eating indentation */
484 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200485
486 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200487 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200488 break;
489 }
490 break;
491 case 3:
492 /* string encoded characters */
493 switch (**data) {
494 case 'n':
495 c = "\n";
496 break;
497 case 't':
498 c = "\t";
499 break;
500 case '\"':
501 c = *data;
502 break;
503 case '\\':
504 c = *data;
505 break;
506 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200507 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200508 return LY_EVALID;
509 }
510
511 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200512 LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200513
514 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200515 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200516 break;
517 case 4:
518 switch (**data) {
519 case '+':
520 /* string continues */
521 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200522 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200523 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200524 case '\n':
525 ++ctx->line;
526 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200527 case ' ':
528 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200529 /* just skip */
530 break;
531 default:
532 /* string is finished */
533 goto string_end;
534 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200535 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200536 break;
537 case 5:
538 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200539 case '\n':
540 ++ctx->line;
541 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200542 case ' ':
543 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200544 /* skip */
545 break;
546 case '\'':
547 string = 1;
548 break;
549 case '\"':
550 string = 2;
551 break;
552 default:
553 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200554 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200555 return LY_EVALID;
556 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200557 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200558 break;
559 default:
560 return LY_EINT;
561 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200562 }
563
564string_end:
565 return LY_SUCCESS;
566}
567
Michal Vaskoea5abea2018-09-18 13:10:54 +0200568/**
569 * @brief Get another YANG string from the raw data.
570 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200571 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200572 * @param[in,out] data Data to read from, always moved to currently handled character.
573 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200574 * @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 +0200575 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
576 * set to NULL. Otherwise equal to \p word_p.
577 * @param[out] word_len Length of the read string.
578 *
579 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200580 */
581static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200582get_argument(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200583{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200584 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200585
586 /* word buffer - dynamically allocated */
587 *word_b = NULL;
588
589 /* word pointer - just a pointer to data */
590 *word_p = NULL;
591
592 *word_len = 0;
593 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200594 switch (**data) {
595 case '\'':
596 case '\"':
597 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200598 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
599 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
600 "unquoted string character, optsep, semicolon or opening brace");
601 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200602 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100603 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200604 goto str_end;
605 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200606 if ((*data)[1] == '/') {
607 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200608 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100609 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200610 } else if ((*data)[1] == '*') {
611 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200612 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100613 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200614 } else {
615 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100616 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 +0200617 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200618 break;
619 case ' ':
620 if (*word_len) {
621 /* word is finished */
622 goto str_end;
623 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200624 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200625 break;
626 case '\t':
627 if (*word_len) {
628 /* word is finished */
629 goto str_end;
630 }
631 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200632 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200633
634 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200635 break;
636 case '\n':
637 if (*word_len) {
638 /* word is finished */
639 goto str_end;
640 }
641 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200642 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200643
644 /* track line numbers */
645 ++ctx->line;
646
647 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200648 break;
649 case ';':
650 case '{':
651 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
652 /* word is finished */
653 goto str_end;
654 }
655
Radek Krejci44ceedc2018-10-02 15:54:31 +0200656 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200657 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200658 case '}':
659 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
660 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
661 "unquoted string character, optsep, semicolon or opening brace");
662 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200663 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200664 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 +0200665 break;
666 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200667 }
668
669str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200670 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200671 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200672 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
673 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
674 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200675 *word_p = *word_b;
676 }
677
678 return LY_SUCCESS;
679}
680
Michal Vaskoea5abea2018-09-18 13:10:54 +0200681/**
682 * @brief Get another YANG keyword from the raw data.
683 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200684 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200685 * @param[in,out] data Data to read from, always moved to currently handled character.
686 * @param[out] kw YANG keyword read.
687 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
688 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
689 *
690 * @return LY_ERR values.
691 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200692static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200693get_keyword(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200694{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200695 int prefix;
696 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200697 unsigned int c;
698 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200699
700 if (word_p) {
701 *word_p = NULL;
702 *word_len = 0;
703 }
704
705 /* first skip "optsep", comments */
706 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200707 switch (**data) {
708 case '/':
709 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200710 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200711 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100712 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200713 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200714 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200715 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100716 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200717 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200718 /* error - not a comment after all, keyword cannot start with slash */
719 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
720 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200721 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200722 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200723 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200724 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200725 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200726 ctx->indent = 0;
727 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200728 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200729 /* skip whitespaces (optsep) */
730 ++ctx->indent;
731 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200732 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200733 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200734 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200735 break;
736 default:
737 /* either a keyword start or an invalid character */
738 goto keyword_start;
739 }
740
741 ++(*data);
742 }
743
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200744#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
745#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
746#define IF_KW_PREFIX_END }
747
Michal Vasko7fbc8162018-09-17 10:35:16 +0200748keyword_start:
749 word_start = *data;
750 *kw = YANG_NONE;
751
752 /* read the keyword itself */
753 switch (**data) {
754 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200755 MOVE_INPUT(ctx, data, 1);
756 IF_KW("rgument", 7, YANG_ARGUMENT)
757 else IF_KW("ugment", 6, YANG_AUGMENT)
758 else IF_KW("ction", 5, YANG_ACTION)
759 else IF_KW_PREFIX("ny", 2)
760 IF_KW("data", 4, YANG_ANYDATA)
761 else IF_KW("xml", 3, YANG_ANYXML)
762 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200763 break;
764 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200765 MOVE_INPUT(ctx, data, 1);
766 IF_KW("ase", 3, YANG_BASE)
767 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
768 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200769 break;
770 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200771 MOVE_INPUT(ctx, data, 1);
772 IF_KW("ase", 3, YANG_CASE)
773 else IF_KW("hoice", 5, YANG_CHOICE)
774 else IF_KW_PREFIX("on", 2)
775 IF_KW("fig", 3, YANG_CONFIG)
776 else IF_KW_PREFIX("ta", 2)
777 IF_KW("ct", 2, YANG_CONTACT)
778 else IF_KW("iner", 4, YANG_CONTAINER)
779 IF_KW_PREFIX_END
780 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200781 break;
782 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200783 MOVE_INPUT(ctx, data, 1);
784 IF_KW_PREFIX("e", 1)
785 IF_KW("fault", 5, YANG_DEFAULT)
786 else IF_KW("scription", 9, YANG_DESCRIPTION)
787 else IF_KW_PREFIX("viat", 4)
788 IF_KW("e", 1, YANG_DEVIATE)
789 else IF_KW("ion", 3, YANG_DEVIATION)
790 IF_KW_PREFIX_END
791 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200792 break;
793 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200794 MOVE_INPUT(ctx, data, 1);
795 IF_KW("num", 3, YANG_ENUM)
796 else IF_KW_PREFIX("rror-", 5)
797 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
798 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
799 IF_KW_PREFIX_END
800 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200801 break;
802 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200803 MOVE_INPUT(ctx, data, 1);
804 IF_KW("eature", 6, YANG_FEATURE)
805 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200806 break;
807 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200808 MOVE_INPUT(ctx, data, 1);
809 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200810 break;
811 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200812 MOVE_INPUT(ctx, data, 1);
813 IF_KW("dentity", 7, YANG_IDENTITY)
814 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
815 else IF_KW("mport", 5, YANG_IMPORT)
816 else IF_KW_PREFIX("n", 1)
817 IF_KW("clude", 5, YANG_INCLUDE)
818 else IF_KW("put", 3, YANG_INPUT)
819 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200820 break;
821 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200822 MOVE_INPUT(ctx, data, 1);
823 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200824 break;
825 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200826 MOVE_INPUT(ctx, data, 1);
827 IF_KW_PREFIX("e", 1)
828 IF_KW("af-list", 7, YANG_LEAF_LIST)
829 else IF_KW("af", 2, YANG_LEAF)
830 else IF_KW("ngth", 4, YANG_LENGTH)
831 IF_KW_PREFIX_END
832 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200833 break;
834 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200835 MOVE_INPUT(ctx, data, 1);
836 IF_KW_PREFIX("a", 1)
837 IF_KW("ndatory", 7, YANG_MANDATORY)
838 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
839 IF_KW_PREFIX_END
840 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
841 else IF_KW("ust", 3, YANG_MUST)
842 else IF_KW_PREFIX("od", 2)
843 IF_KW("ule", 3, YANG_MODULE)
844 else IF_KW("ifier", 5, YANG_MODIFIER)
845 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200846 break;
847 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200848 MOVE_INPUT(ctx, data, 1);
849 IF_KW("amespace", 8, YANG_NAMESPACE)
850 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200851 break;
852 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200853 MOVE_INPUT(ctx, data, 1);
854 IF_KW_PREFIX("r", 1)
855 IF_KW("dered-by", 8, YANG_ORDERED_BY)
856 else IF_KW("ganization", 10, YANG_ORGANIZATION)
857 IF_KW_PREFIX_END
858 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200859 break;
860 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200861 MOVE_INPUT(ctx, data, 1);
862 IF_KW("ath", 3, YANG_PATH)
863 else IF_KW("attern", 6, YANG_PATTERN)
864 else IF_KW("osition", 7, YANG_POSITION)
865 else IF_KW_PREFIX("re", 2)
866 IF_KW("fix", 3, YANG_PREFIX)
867 else IF_KW("sence", 5, YANG_PRESENCE)
868 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200869 break;
870 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200871 MOVE_INPUT(ctx, data, 1);
872 IF_KW("ange", 4, YANG_RANGE)
873 else IF_KW_PREFIX("e", 1)
874 IF_KW_PREFIX("f", 1)
875 IF_KW("erence", 6, YANG_REFERENCE)
876 else IF_KW("ine", 3, YANG_REFINE)
877 IF_KW_PREFIX_END
878 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
879 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
880 else IF_KW("vision", 6, YANG_REVISION)
881 IF_KW_PREFIX_END
882 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200883 break;
884 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200885 MOVE_INPUT(ctx, data, 1);
886 IF_KW("tatus", 5, YANG_STATUS)
887 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200888 break;
889 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200890 MOVE_INPUT(ctx, data, 1);
891 IF_KW("ypedef", 6, YANG_TYPEDEF)
892 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200893 break;
894 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200895 MOVE_INPUT(ctx, data, 1);
896 IF_KW_PREFIX("ni", 2)
897 IF_KW("que", 3, YANG_UNIQUE)
898 else IF_KW("ts", 2, YANG_UNITS)
899 IF_KW_PREFIX_END
900 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200901 break;
902 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200903 MOVE_INPUT(ctx, data, 1);
904 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200905 break;
906 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200907 MOVE_INPUT(ctx, data, 1);
908 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200909 break;
910 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200911 MOVE_INPUT(ctx, data, 1);
912 IF_KW("ang-version", 11, YANG_YANG_VERSION)
913 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200914 break;
915 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200916 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200917 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200918 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200919 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200920 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200921 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200922 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200923 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200924 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200925 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200926 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200927 default:
928 break;
929 }
930
Radek Krejci0904c162019-01-02 15:03:59 +0100931#undef IF_KW
932#undef IF_KW_PREFIX
933#undef IF_KW_PREFIX_END
934
Michal Vasko7fbc8162018-09-17 10:35:16 +0200935 if (*kw != YANG_NONE) {
936 /* make sure we have the whole keyword */
937 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200938 case '\n':
939 ++ctx->line;
940 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200941 case ' ':
942 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200943 /* mandatory "sep" */
944 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200945 case ':':
946 /* keyword is not actually a keyword, but prefix of an extension.
947 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
948 * and we will be checking the keyword (extension instance) itself */
949 prefix = 1;
950 MOVE_INPUT(ctx, data, 1);
951 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200952 case '{':
953 /* allowed only for input and output statements which can be without arguments */
954 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
955 break;
956 }
957 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200958 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200959 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200960 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
961 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200962 return LY_EVALID;
963 }
964 } else {
965 /* still can be an extension */
966 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200967extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200968 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200969 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
970 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200971 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200972 /* check character validity */
973 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200974 }
975 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200976 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200977 return LY_EVALID;
978 }
979
980 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200981 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200982 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200983 return LY_EVALID;
984 }
985
986 *kw = YANG_CUSTOM;
987 }
Radek Krejci626df482018-10-11 15:06:31 +0200988success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200989 if (word_p) {
990 *word_p = (char *)word_start;
991 *word_len = *data - word_start;
992 }
993
994 return LY_SUCCESS;
995}
996
Michal Vaskoea5abea2018-09-18 13:10:54 +0200997/**
998 * @brief Parse extension instance substatements.
999 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001000 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001001 * @param[in,out] data Data to read from, always moved to currently handled character.
1002 * @param[in] word Extension instance substatement name (keyword).
1003 * @param[in] word_len Extension instance substatement name length.
1004 * @param[in,out] child Children of this extension instance to add to.
1005 *
1006 * @return LY_ERR values.
1007 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001008static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001009parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001010 struct lysp_stmt **child)
1011{
1012 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001013 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001014 enum yang_keyword kw;
1015 struct lysp_stmt *stmt, *par_child;
1016
1017 stmt = calloc(1, sizeof *stmt);
1018 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
1019
Radek Krejcibb9b1982019-04-08 14:24:59 +02001020 /* insert into parent statements */
1021 if (!*child) {
1022 *child = stmt;
1023 } else {
1024 for (par_child = *child; par_child->next; par_child = par_child->next);
1025 par_child->next = stmt;
1026 }
1027
Radek Krejci44ceedc2018-10-02 15:54:31 +02001028 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001029
1030 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001031 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001032
Radek Krejci0ae092d2018-09-20 16:43:19 +02001033 if (word) {
1034 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001035 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001036 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001037 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001038 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001039 }
1040
Radek Krejci6d6556c2018-11-08 09:37:45 +01001041 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001042 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001043 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001044 return ret;
1045}
1046
Michal Vaskoea5abea2018-09-18 13:10:54 +02001047/**
1048 * @brief Parse extension instance.
1049 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001050 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001051 * @param[in,out] data Data to read from, always moved to currently handled character.
1052 * @param[in] ext_name Extension instance substatement name (keyword).
1053 * @param[in] ext_name_len Extension instance substatement name length.
1054 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1055 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1056 * @param[in,out] exts Extension instances to add to.
1057 *
1058 * @return LY_ERR values.
1059 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001060static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001061parse_ext(struct ly_parser_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001062 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1063{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001064 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001065 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001066 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001067 struct lysp_ext_instance *e;
1068 enum yang_keyword kw;
1069
Radek Krejci2c4e7172018-10-19 15:56:26 +02001070 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001071
1072 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001073 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001074 e->insubstmt = insubstmt;
1075 e->insubstmt_index = insubstmt_index;
1076
1077 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001078 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001079
Radek Krejci0ae092d2018-09-20 16:43:19 +02001080 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001081 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001082 }
1083
Radek Krejci6d6556c2018-11-08 09:37:45 +01001084 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001085 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001086 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001087 return ret;
1088}
1089
Michal Vaskoea5abea2018-09-18 13:10:54 +02001090/**
1091 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1092 * description, etc...
1093 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001094 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001095 * @param[in,out] data Data to read from, always moved to currently handled character.
1096 * @param[in] substmt Type of this substatement.
1097 * @param[in] substmt_index Index of this substatement.
1098 * @param[in,out] value Place to store the parsed value.
1099 * @param[in] arg Type of the YANG keyword argument (of the value).
1100 * @param[in,out] exts Extension instances to add to.
1101 *
1102 * @return LY_ERR values.
1103 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001104static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001105parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001106 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1107{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001108 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001109 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001110 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001111 enum yang_keyword kw;
1112
1113 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001114 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001115 return LY_EVALID;
1116 }
1117
1118 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001119 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001120
1121 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001122 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001123
Radek Krejci6d6556c2018-11-08 09:37:45 +01001124 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001125 switch (kw) {
1126 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001127 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001128 break;
1129 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001130 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131 return LY_EVALID;
1132 }
1133 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001134 return ret;
1135}
1136
Michal Vaskoea5abea2018-09-18 13:10:54 +02001137/**
1138 * @brief Parse the yang-version statement.
1139 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001140 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001141 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001142 * @param[out] version Storage for the parsed information.
1143 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001144 *
1145 * @return LY_ERR values.
1146 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001147static LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001148parse_yangversion(struct ly_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001149{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001150 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001151 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001152 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001153 enum yang_keyword kw;
1154
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001155 if (*version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001156 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001157 return LY_EVALID;
1158 }
1159
1160 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001161 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001162
1163 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001164 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001165 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001166 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001167 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001168 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001169 free(buf);
1170 return LY_EVALID;
1171 }
1172 free(buf);
1173
Radek Krejci6d6556c2018-11-08 09:37:45 +01001174 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175 switch (kw) {
1176 case YANG_CUSTOM:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001177 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001178 break;
1179 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001180 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001181 return LY_EVALID;
1182 }
1183 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184 return ret;
1185}
1186
Michal Vaskoea5abea2018-09-18 13:10:54 +02001187/**
1188 * @brief Parse the belongs-to statement.
1189 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001190 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001191 * @param[in,out] data Data to read from, always moved to currently handled character.
1192 * @param[in,out] belongsto Place to store the parsed value.
1193 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1194 * @param[in,out] exts Extension instances to add to.
1195 *
1196 * @return LY_ERR values.
1197 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001198static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001199parse_belongsto(struct ly_parser_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001200{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001201 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001202 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001203 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001204 enum yang_keyword kw;
1205
1206 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001207 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001208 return LY_EVALID;
1209 }
1210
1211 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001212 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001213
Radek Krejci44ceedc2018-10-02 15:54:31 +02001214 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001215 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001216 switch (kw) {
1217 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001218 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001219 break;
1220 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001221 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001222 break;
1223 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001224 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001225 return LY_EVALID;
1226 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001227 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001228 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001229checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001230 /* mandatory substatements */
1231 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001232 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001233 return LY_EVALID;
1234 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001235 return ret;
1236}
1237
Michal Vaskoea5abea2018-09-18 13:10:54 +02001238/**
1239 * @brief Parse the revision-date statement.
1240 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001241 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001242 * @param[in,out] data Data to read from, always moved to currently handled character.
1243 * @param[in,out] rev Array to store the parsed value in.
1244 * @param[in,out] exts Extension instances to add to.
1245 *
1246 * @return LY_ERR values.
1247 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001248static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001249parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001250{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001251 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001252 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001253 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001254 enum yang_keyword kw;
1255
1256 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001257 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001258 return LY_EVALID;
1259 }
1260
1261 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001262 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001263
1264 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001265 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001266 free(buf);
1267 return LY_EVALID;
1268 }
1269
1270 /* store value and spend buf if allocated */
1271 strncpy(rev, word, word_len);
1272 free(buf);
1273
Radek Krejci6d6556c2018-11-08 09:37:45 +01001274 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001275 switch (kw) {
1276 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001277 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001278 break;
1279 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001280 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001281 return LY_EVALID;
1282 }
1283 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001284 return ret;
1285}
1286
Michal Vaskoea5abea2018-09-18 13:10:54 +02001287/**
1288 * @brief Parse the include statement.
1289 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001290 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001291 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001292 * @param[in,out] data Data to read from, always moved to currently handled character.
1293 * @param[in,out] includes Parsed includes to add to.
1294 *
1295 * @return LY_ERR values.
1296 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001297static LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001298parse_include(struct ly_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001299{
Radek Krejcid33273d2018-10-25 14:55:52 +02001300 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001301 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001302 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001303 enum yang_keyword kw;
1304 struct lysp_include *inc;
1305
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001306 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001307
1308 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001309 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001310
Radek Krejci086c7132018-10-26 15:29:04 +02001311 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1312
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001313 /* submodules share the namespace with the module names, so there must not be
1314 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001315 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001316 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1317 return LY_EVALID;
1318 }
1319
Radek Krejci6d6556c2018-11-08 09:37:45 +01001320 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001321 switch (kw) {
1322 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001323 YANG_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001324 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 +02001325 break;
1326 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001327 YANG_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001328 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 +02001329 break;
1330 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001331 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001332 break;
1333 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001334 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001335 break;
1336 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001337 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001338 return LY_EVALID;
1339 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001340 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001341 return ret;
1342}
1343
Michal Vaskoea5abea2018-09-18 13:10:54 +02001344/**
1345 * @brief Parse the import statement.
1346 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001347 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001348 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001349 * @param[in,out] data Data to read from, always moved to currently handled character.
1350 * @param[in,out] imports Parsed imports to add to.
1351 *
1352 * @return LY_ERR values.
1353 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001354static LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001355parse_import(struct ly_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001356{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001357 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001358 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001359 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001360 enum yang_keyword kw;
1361 struct lysp_import *imp;
1362
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001363 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001364
1365 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001366 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001367 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001368
Radek Krejci6d6556c2018-11-08 09:37:45 +01001369 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001370 switch (kw) {
1371 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001372 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 +01001373 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001374 break;
1375 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001376 YANG_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001377 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 +02001378 break;
1379 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001380 YANG_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001381 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 +02001382 break;
1383 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001384 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001385 break;
1386 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001387 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001388 break;
1389 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001390 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001391 return LY_EVALID;
1392 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001393 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001394 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001395checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001396 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001397 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001398
1399 return ret;
1400}
1401
Michal Vaskoea5abea2018-09-18 13:10:54 +02001402/**
1403 * @brief Parse the revision statement.
1404 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001405 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001406 * @param[in,out] data Data to read from, always moved to currently handled character.
1407 * @param[in,out] revs Parsed revisions to add to.
1408 *
1409 * @return LY_ERR values.
1410 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001411static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001412parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001413{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001414 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001415 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001416 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001417 enum yang_keyword kw;
1418 struct lysp_revision *rev;
1419
Radek Krejci2c4e7172018-10-19 15:56:26 +02001420 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001421
1422 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001423 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001424
1425 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001426 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001427 return LY_EVALID;
1428 }
1429
Radek Krejcib7db73a2018-10-24 14:18:40 +02001430 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001431 free(buf);
1432
Radek Krejci6d6556c2018-11-08 09:37:45 +01001433 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001434 switch (kw) {
1435 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001436 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 +02001437 break;
1438 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001439 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 +02001440 break;
1441 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001442 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001443 break;
1444 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001445 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001446 return LY_EVALID;
1447 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001448 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001449 return ret;
1450}
1451
Michal Vaskoea5abea2018-09-18 13:10:54 +02001452/**
1453 * @brief Parse a generic text field that can have more instances such as base.
1454 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001455 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001456 * @param[in,out] data Data to read from, always moved to currently handled character.
1457 * @param[in] substmt Type of this substatement.
1458 * @param[in,out] texts Parsed values to add to.
1459 * @param[in] arg Type of the expected argument.
1460 * @param[in,out] exts Extension instances to add to.
1461 *
1462 * @return LY_ERR values.
1463 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001464static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001465parse_text_fields(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001466 struct lysp_ext_instance **exts)
1467{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001468 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001469 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001470 const char **item;
1471 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001472 enum yang_keyword kw;
1473
1474 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001475 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001476
1477 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001478 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001479
Radek Krejci151a5b72018-10-19 14:21:44 +02001480 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001481 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001482 switch (kw) {
1483 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001484 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001485 break;
1486 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001487 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001488 return LY_EVALID;
1489 }
1490 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001491 return ret;
1492}
1493
Michal Vaskoea5abea2018-09-18 13:10:54 +02001494/**
1495 * @brief Parse the config statement.
1496 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001497 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001498 * @param[in,out] data Data to read from, always moved to currently handled character.
1499 * @param[in,out] flags Flags to add to.
1500 * @param[in,out] exts Extension instances to add to.
1501 *
1502 * @return LY_ERR values.
1503 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001504static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001505parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001506{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001507 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001508 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001509 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001510 enum yang_keyword kw;
1511
1512 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001513 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001514 return LY_EVALID;
1515 }
1516
1517 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001518 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001519
1520 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1521 *flags |= LYS_CONFIG_W;
1522 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1523 *flags |= LYS_CONFIG_R;
1524 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001525 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001526 free(buf);
1527 return LY_EVALID;
1528 }
1529 free(buf);
1530
Radek Krejci6d6556c2018-11-08 09:37:45 +01001531 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001532 switch (kw) {
1533 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001534 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001535 break;
1536 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001537 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001538 return LY_EVALID;
1539 }
1540 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001541 return ret;
1542}
1543
Michal Vaskoea5abea2018-09-18 13:10:54 +02001544/**
1545 * @brief Parse the mandatory statement.
1546 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001547 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001548 * @param[in,out] data Data to read from, always moved to currently handled character.
1549 * @param[in,out] flags Flags to add to.
1550 * @param[in,out] exts Extension instances to add to.
1551 *
1552 * @return LY_ERR values.
1553 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001554static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001555parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001556{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001557 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001558 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001559 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001560 enum yang_keyword kw;
1561
1562 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001563 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001564 return LY_EVALID;
1565 }
1566
1567 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001568 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001569
1570 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1571 *flags |= LYS_MAND_TRUE;
1572 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1573 *flags |= LYS_MAND_FALSE;
1574 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001575 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001576 free(buf);
1577 return LY_EVALID;
1578 }
1579 free(buf);
1580
Radek Krejci6d6556c2018-11-08 09:37:45 +01001581 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001582 switch (kw) {
1583 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001584 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001585 break;
1586 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001587 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001588 return LY_EVALID;
1589 }
1590 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001591 return ret;
1592}
1593
Michal Vaskoea5abea2018-09-18 13:10:54 +02001594/**
1595 * @brief Parse a restriction such as range or length.
1596 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001597 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001598 * @param[in,out] data Data to read from, always moved to currently handled character.
1599 * @param[in] restr_kw Type of this particular restriction.
1600 * @param[in,out] exts Extension instances to add to.
1601 *
1602 * @return LY_ERR values.
1603 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001604static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001605parse_restr(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr *restr)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001606{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001607 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001608 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001609 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001610 enum yang_keyword kw;
1611
1612 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001613 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001614
Radek Krejci44ceedc2018-10-02 15:54:31 +02001615 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001616 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001617 switch (kw) {
1618 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001619 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 +02001620 break;
1621 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001622 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 +02001623 break;
1624 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001625 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 +02001626 break;
1627 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001628 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 +02001629 break;
1630 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001631 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001632 break;
1633 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001634 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001635 return LY_EVALID;
1636 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001637 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001638 return ret;
1639}
1640
Michal Vaskoea5abea2018-09-18 13:10:54 +02001641/**
1642 * @brief Parse a restriction that can have more instances such as must.
1643 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001644 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001645 * @param[in,out] data Data to read from, always moved to currently handled character.
1646 * @param[in] restr_kw Type of this particular restriction.
1647 * @param[in,out] restrs Restrictions to add to.
1648 *
1649 * @return LY_ERR values.
1650 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001651static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001652parse_restrs(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr **restrs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001653{
1654 struct lysp_restr *restr;
1655
Radek Krejci2c4e7172018-10-19 15:56:26 +02001656 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001657 return parse_restr(ctx, data, restr_kw, restr);
1658}
1659
Michal Vaskoea5abea2018-09-18 13:10:54 +02001660/**
1661 * @brief Parse the status statement.
1662 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001663 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001664 * @param[in,out] data Data to read from, always moved to currently handled character.
1665 * @param[in,out] flags Flags to add to.
1666 * @param[in,out] exts Extension instances to add to.
1667 *
1668 * @return LY_ERR values.
1669 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001670static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001671parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001672{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001673 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001674 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001675 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001676 enum yang_keyword kw;
1677
1678 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001679 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001680 return LY_EVALID;
1681 }
1682
1683 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001684 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001685
1686 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1687 *flags |= LYS_STATUS_CURR;
1688 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1689 *flags |= LYS_STATUS_DEPRC;
1690 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1691 *flags |= LYS_STATUS_OBSLT;
1692 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001693 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001694 free(buf);
1695 return LY_EVALID;
1696 }
1697 free(buf);
1698
Radek Krejci6d6556c2018-11-08 09:37:45 +01001699 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001700 switch (kw) {
1701 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001702 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001703 break;
1704 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001705 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001706 return LY_EVALID;
1707 }
1708 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001709 return ret;
1710}
1711
Michal Vaskoea5abea2018-09-18 13:10:54 +02001712/**
1713 * @brief Parse the when statement.
1714 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001715 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001716 * @param[in,out] data Data to read from, always moved to currently handled character.
1717 * @param[in,out] when_p When pointer to parse to.
1718 *
1719 * @return LY_ERR values.
1720 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001721static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001722parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001723{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001724 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001725 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001726 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001727 enum yang_keyword kw;
1728 struct lysp_when *when;
1729
1730 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001731 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001732 return LY_EVALID;
1733 }
1734
1735 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001736 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001737 *when_p = when;
1738
1739 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001740 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001741 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001742
Radek Krejci6d6556c2018-11-08 09:37:45 +01001743 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001744 switch (kw) {
1745 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001746 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 +02001747 break;
1748 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001749 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 +02001750 break;
1751 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001752 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001753 break;
1754 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001755 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001756 return LY_EVALID;
1757 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001758 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001759 return ret;
1760}
1761
Michal Vaskoea5abea2018-09-18 13:10:54 +02001762/**
1763 * @brief Parse the anydata or anyxml statement.
1764 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001765 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001766 * @param[in,out] data Data to read from, always moved to currently handled character.
1767 * @param[in] kw Type of this particular keyword.
1768 * @param[in,out] siblings Siblings to add to.
1769 *
1770 * @return LY_ERR values.
1771 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001772static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001773parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001774{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001775 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001776 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001777 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001778 struct lysp_node *iter;
1779 struct lysp_node_anydata *any;
1780
1781 /* create structure */
1782 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001783 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001784 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001785 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001786
1787 /* insert into siblings */
1788 if (!*siblings) {
1789 *siblings = (struct lysp_node *)any;
1790 } else {
1791 for (iter = *siblings; iter->next; iter = iter->next);
1792 iter->next = (struct lysp_node *)any;
1793 }
1794
1795 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001796 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001797 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001798
1799 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001800 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001801 switch (kw) {
1802 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001803 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001804 break;
1805 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001806 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 +02001807 break;
1808 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001809 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 +02001810 break;
1811 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001812 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001813 break;
1814 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001815 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001816 break;
1817 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001818 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 +02001819 break;
1820 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001821 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001822 break;
1823 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001824 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001825 break;
1826 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001827 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001828 break;
1829 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001830 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001831 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001832 return LY_EVALID;
1833 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001834 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001835 return ret;
1836}
1837
Michal Vaskoea5abea2018-09-18 13:10:54 +02001838/**
1839 * @brief Parse the value or position statement. Substatement of type enum statement.
1840 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001841 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001842 * @param[in,out] data Data to read from, always moved to currently handled character.
1843 * @param[in] val_kw Type of this particular keyword.
1844 * @param[in,out] value Value to write to.
1845 * @param[in,out] flags Flags to write to.
1846 * @param[in,out] exts Extension instances to add to.
1847 *
1848 * @return LY_ERR values.
1849 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001850static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001851parse_type_enum_value_pos(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword val_kw, int64_t *value, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001852 struct lysp_ext_instance **exts)
1853{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001854 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001855 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001856 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001857 long int num;
1858 unsigned long int unum;
1859 enum yang_keyword kw;
1860
1861 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001862 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001863 return LY_EVALID;
1864 }
1865 *flags |= LYS_SET_VALUE;
1866
1867 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001868 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001869
1870 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 +02001871 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001872 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001873 }
1874
1875 errno = 0;
1876 if (val_kw == YANG_VALUE) {
1877 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001878 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
1879 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1880 goto error;
1881 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001882 } else {
1883 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001884 if (unum > UINT64_C(4294967295)) {
1885 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1886 goto error;
1887 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001888 }
1889 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001890 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001891 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001892 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001893 }
1894 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001895 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001896 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001897 }
1898 if (val_kw == YANG_VALUE) {
1899 *value = num;
1900 } else {
1901 *value = unum;
1902 }
1903 free(buf);
1904
Radek Krejci6d6556c2018-11-08 09:37:45 +01001905 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001906 switch (kw) {
1907 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001908 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 +02001909 break;
1910 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001911 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001912 return LY_EVALID;
1913 }
1914 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001915 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001916
1917error:
1918 free(buf);
1919 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001920}
1921
Michal Vaskoea5abea2018-09-18 13:10:54 +02001922/**
1923 * @brief Parse the enum or bit statement. Substatement of type statement.
1924 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001925 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001926 * @param[in,out] data Data to read from, always moved to currently handled character.
1927 * @param[in] enum_kw Type of this particular keyword.
1928 * @param[in,out] enums Enums or bits to add to.
1929 *
1930 * @return LY_ERR values.
1931 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001932static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001933parse_type_enum(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword enum_kw, struct lysp_type_enum **enums)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001934{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001935 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001936 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001937 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001938 enum yang_keyword kw;
1939 struct lysp_type_enum *enm;
1940
Radek Krejci2c4e7172018-10-19 15:56:26 +02001941 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001942
1943 /* get value */
Radek Krejci8b764662018-11-14 14:15:13 +01001944 LY_CHECK_RET(get_argument(ctx, data, enum_kw == YANG_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, &word, &buf, &word_len));
1945 if (enum_kw == YANG_ENUM) {
1946 if (!word_len) {
1947 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
1948 free(buf);
1949 return LY_EVALID;
1950 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
1951 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
1952 word_len, word);
1953 free(buf);
1954 return LY_EVALID;
1955 } else {
1956 for (u = 0; u < word_len; ++u) {
1957 if (iscntrl(word[u])) {
1958 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1959 word_len, word, u + 1);
1960 break;
1961 }
1962 }
1963 }
1964 } else { /* YANG_BIT */
1965
1966 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001967 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001968 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1969
Radek Krejci6d6556c2018-11-08 09:37:45 +01001970 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001971 switch (kw) {
1972 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001973 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 +02001974 break;
1975 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001976 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001977 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 +02001978 break;
1979 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001980 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 +02001981 break;
1982 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001983 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001984 break;
1985 case YANG_VALUE:
1986 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001987 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001988 break;
1989 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001990 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001991 break;
1992 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001993 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001994 return LY_EVALID;
1995 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001996 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001997 return ret;
1998}
1999
Michal Vaskoea5abea2018-09-18 13:10:54 +02002000/**
2001 * @brief Parse the fraction-digits statement. Substatement of type statement.
2002 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002003 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002004 * @param[in,out] data Data to read from, always moved to currently handled character.
2005 * @param[in,out] fracdig Value to write to.
2006 * @param[in,out] exts Extension instances to add to.
2007 *
2008 * @return LY_ERR values.
2009 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002010static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002011parse_type_fracdigits(struct ly_parser_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002012{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002013 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002014 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002015 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002016 unsigned long int num;
2017 enum yang_keyword kw;
2018
2019 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002020 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002021 return LY_EVALID;
2022 }
2023
2024 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002025 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002026
2027 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002028 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002029 free(buf);
2030 return LY_EVALID;
2031 }
2032
2033 errno = 0;
2034 num = strtoul(word, &ptr, 10);
2035 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002036 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002037 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002038 free(buf);
2039 return LY_EVALID;
2040 }
2041 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002042 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002043 free(buf);
2044 return LY_EVALID;
2045 }
2046 *fracdig = num;
2047 free(buf);
2048
Radek Krejci6d6556c2018-11-08 09:37:45 +01002049 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002050 switch (kw) {
2051 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002052 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002053 break;
2054 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002055 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002056 return LY_EVALID;
2057 }
2058 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002059 return ret;
2060}
2061
Michal Vaskoea5abea2018-09-18 13:10:54 +02002062/**
2063 * @brief Parse the require-instance statement. Substatement of type statement.
2064 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002065 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002066 * @param[in,out] data Data to read from, always moved to currently handled character.
2067 * @param[in,out] reqinst Value to write to.
2068 * @param[in,out] flags Flags to write to.
2069 * @param[in,out] exts Extension instances to add to.
2070 *
2071 * @return LY_ERR values.
2072 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002073static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002074parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075 struct lysp_ext_instance **exts)
2076{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002077 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002078 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002079 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002080 enum yang_keyword kw;
2081
2082 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002083 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002084 return LY_EVALID;
2085 }
2086 *flags |= LYS_SET_REQINST;
2087
2088 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002089 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002090
2091 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2092 *reqinst = 1;
2093 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002094 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002095 free(buf);
2096 return LY_EVALID;
2097 }
2098 free(buf);
2099
Radek Krejci6d6556c2018-11-08 09:37:45 +01002100 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002101 switch (kw) {
2102 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002103 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002104 break;
2105 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002106 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002107 return LY_EVALID;
2108 }
2109 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002110 return ret;
2111}
2112
Michal Vaskoea5abea2018-09-18 13:10:54 +02002113/**
2114 * @brief Parse the modifier statement. Substatement of type pattern statement.
2115 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002116 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002117 * @param[in,out] data Data to read from, always moved to currently handled character.
2118 * @param[in,out] pat Value to write to.
2119 * @param[in,out] exts Extension instances to add to.
2120 *
2121 * @return LY_ERR values.
2122 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002123static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002124parse_type_pattern_modifier(struct ly_parser_ctx *ctx, const char **data, const char **pat, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002125{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002126 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002127 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002128 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002129 enum yang_keyword kw;
2130
2131 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002132 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002133 return LY_EVALID;
2134 }
2135
2136 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002137 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002138
2139 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002140 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002141 free(buf);
2142 return LY_EVALID;
2143 }
2144 free(buf);
2145
2146 /* replace the value in the dictionary */
2147 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002148 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002149 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002150 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002151
2152 assert(buf[0] == 0x06);
2153 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002154 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002155
Radek Krejci6d6556c2018-11-08 09:37:45 +01002156 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002157 switch (kw) {
2158 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002159 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002160 break;
2161 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002162 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002163 return LY_EVALID;
2164 }
2165 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002166 return ret;
2167}
2168
Michal Vaskoea5abea2018-09-18 13:10:54 +02002169/**
2170 * @brief Parse the pattern statement. Substatement of type statement.
2171 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002172 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002173 * @param[in,out] data Data to read from, always moved to currently handled character.
2174 * @param[in,out] patterns Restrictions to add to.
2175 *
2176 * @return LY_ERR values.
2177 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002178static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002179parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002180{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002181 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002182 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002183 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002184 enum yang_keyword kw;
2185 struct lysp_restr *restr;
2186
Radek Krejci2c4e7172018-10-19 15:56:26 +02002187 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002188
2189 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002190 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002191
2192 /* add special meaning first byte */
2193 if (buf) {
2194 buf = realloc(buf, word_len + 2);
2195 word = buf;
2196 } else {
2197 buf = malloc(word_len + 2);
2198 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002199 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002200 memmove(buf + 1, word, word_len);
2201 buf[0] = 0x06; /* pattern's default regular-match flag */
2202 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2203 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002204
Radek Krejci6d6556c2018-11-08 09:37:45 +01002205 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002206 switch (kw) {
2207 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002208 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 +02002209 break;
2210 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002211 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 +02002212 break;
2213 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002214 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 +02002215 break;
2216 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002217 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 +02002218 break;
2219 case YANG_MODIFIER:
Radek Krejciceaf2122019-01-02 15:03:26 +01002220 YANG_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002221 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002222 break;
2223 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002224 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002225 break;
2226 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002227 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002228 return LY_EVALID;
2229 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002230 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002231 return ret;
2232}
2233
Michal Vaskoea5abea2018-09-18 13:10:54 +02002234/**
2235 * @brief Parse the type statement.
2236 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002237 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002238 * @param[in,out] data Data to read from, always moved to currently handled character.
2239 * @param[in,out] type Type to wrote to.
2240 *
2241 * @return LY_ERR values.
2242 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002243static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002244parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002245{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002246 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002247 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002248 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002249 enum yang_keyword kw;
2250 struct lysp_type *nest_type;
2251
2252 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002253 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002254 return LY_EVALID;
2255 }
2256
2257 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002258 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002259 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002260
Radek Krejci6d6556c2018-11-08 09:37:45 +01002261 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002262 switch (kw) {
2263 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002264 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 +01002265 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002266 break;
2267 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002268 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002269 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002270 break;
2271 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002272 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002273 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002274 break;
2275 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002276 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002277 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002278 break;
2279 case YANG_LENGTH:
2280 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002281 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002282 return LY_EVALID;
2283 }
2284 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002285 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002286
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002287 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002288 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002289 break;
2290 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002291 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 +01002292 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002293 break;
2294 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002295 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002296 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002297 break;
2298 case YANG_RANGE:
2299 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002300 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002301 return LY_EVALID;
2302 }
2303 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002304 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002305
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002306 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002307 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002308 break;
2309 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002310 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002311 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002312 break;
2313 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002314 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2315 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002316 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002317 break;
2318 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002319 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002320 break;
2321 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002322 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002323 return LY_EVALID;
2324 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002325 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002326 return ret;
2327}
2328
Michal Vaskoea5abea2018-09-18 13:10:54 +02002329/**
2330 * @brief Parse the leaf statement.
2331 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002332 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002333 * @param[in,out] data Data to read from, always moved to currently handled character.
2334 * @param[in,out] siblings Siblings to add to.
2335 *
2336 * @return LY_ERR values.
2337 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002338static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002339parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002340{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002341 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002342 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002343 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002344 enum yang_keyword kw;
2345 struct lysp_node *iter;
2346 struct lysp_node_leaf *leaf;
2347
2348 /* create structure */
2349 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002350 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002351 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002352 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002353
2354 /* insert into siblings */
2355 if (!*siblings) {
2356 *siblings = (struct lysp_node *)leaf;
2357 } else {
2358 for (iter = *siblings; iter->next; iter = iter->next);
2359 iter->next = (struct lysp_node *)leaf;
2360 }
2361
2362 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002363 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002364 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002365
2366 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002367 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002368 switch (kw) {
2369 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002370 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002371 break;
2372 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002373 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 +02002374 break;
2375 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002376 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 +02002377 break;
2378 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002379 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 +02002380 break;
2381 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002382 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002383 break;
2384 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002385 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002386 break;
2387 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002388 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 +02002389 break;
2390 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002391 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002392 break;
2393 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002394 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002395 break;
2396 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002397 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 +02002398 break;
2399 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002400 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002401 break;
2402 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002403 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002404 break;
2405 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002406 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002407 return LY_EVALID;
2408 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002409 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002410 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002411checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002412 /* mandatory substatements */
2413 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002414 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002415 return LY_EVALID;
2416 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002417 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
2418 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
2419 return LY_EVALID;
2420 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002421
2422 return ret;
2423}
2424
Michal Vaskoea5abea2018-09-18 13:10:54 +02002425/**
2426 * @brief Parse the max-elements statement.
2427 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002428 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002429 * @param[in,out] data Data to read from, always moved to currently handled character.
2430 * @param[in,out] max Value to write to.
2431 * @param[in,out] flags Flags to write to.
2432 * @param[in,out] exts Extension instances to add to.
2433 *
2434 * @return LY_ERR values.
2435 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002436static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002437parse_maxelements(struct ly_parser_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002438{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002439 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002440 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002441 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002442 unsigned long int num;
2443 enum yang_keyword kw;
2444
2445 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002446 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002447 return LY_EVALID;
2448 }
2449 *flags |= LYS_SET_MAX;
2450
2451 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002452 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002453
2454 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002455 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002456 free(buf);
2457 return LY_EVALID;
2458 }
2459
2460 if (strncmp(word, "unbounded", word_len)) {
2461 errno = 0;
2462 num = strtoul(word, &ptr, 10);
2463 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002464 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002465 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002466 free(buf);
2467 return LY_EVALID;
2468 }
2469 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002470 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002471 free(buf);
2472 return LY_EVALID;
2473 }
2474
2475 *max = num;
2476 }
2477 free(buf);
2478
Radek Krejci6d6556c2018-11-08 09:37:45 +01002479 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002480 switch (kw) {
2481 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002482 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002483 break;
2484 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002485 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002486 return LY_EVALID;
2487 }
2488 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002489 return ret;
2490}
2491
Michal Vaskoea5abea2018-09-18 13:10:54 +02002492/**
2493 * @brief Parse the min-elements statement.
2494 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002495 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002496 * @param[in,out] data Data to read from, always moved to currently handled character.
2497 * @param[in,out] min Value to write to.
2498 * @param[in,out] flags Flags to write to.
2499 * @param[in,out] exts Extension instances to add to.
2500 *
2501 * @return LY_ERR values.
2502 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002503static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002504parse_minelements(struct ly_parser_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002505{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002506 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002507 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002508 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002509 unsigned long int num;
2510 enum yang_keyword kw;
2511
2512 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002513 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002514 return LY_EVALID;
2515 }
2516 *flags |= LYS_SET_MIN;
2517
2518 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002519 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002520
2521 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002522 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002523 free(buf);
2524 return LY_EVALID;
2525 }
2526
2527 errno = 0;
2528 num = strtoul(word, &ptr, 10);
2529 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002530 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002531 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002532 free(buf);
2533 return LY_EVALID;
2534 }
2535 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002536 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002537 free(buf);
2538 return LY_EVALID;
2539 }
2540 *min = num;
2541 free(buf);
2542
Radek Krejci6d6556c2018-11-08 09:37:45 +01002543 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002544 switch (kw) {
2545 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002546 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002547 break;
2548 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002549 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002550 return LY_EVALID;
2551 }
2552 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002553 return ret;
2554}
2555
Michal Vaskoea5abea2018-09-18 13:10:54 +02002556/**
2557 * @brief Parse the ordered-by statement.
2558 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002559 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002560 * @param[in,out] data Data to read from, always moved to currently handled character.
2561 * @param[in,out] flags Flags to write to.
2562 * @param[in,out] exts Extension instances to add to.
2563 *
2564 * @return LY_ERR values.
2565 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002566static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002567parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002568{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002569 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002570 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002571 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002572 enum yang_keyword kw;
2573
2574 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002575 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002576 return LY_EVALID;
2577 }
2578
2579 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002580 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002581
2582 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2583 *flags |= LYS_ORDBY_SYSTEM;
2584 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2585 *flags |= LYS_ORDBY_USER;
2586 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002587 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002588 free(buf);
2589 return LY_EVALID;
2590 }
2591 free(buf);
2592
Radek Krejci6d6556c2018-11-08 09:37:45 +01002593 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002594 switch (kw) {
2595 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002596 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002597 break;
2598 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002599 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002600 return LY_EVALID;
2601 }
2602 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002603 return ret;
2604}
2605
Michal Vaskoea5abea2018-09-18 13:10:54 +02002606/**
2607 * @brief Parse the leaf-list statement.
2608 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002609 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002610 * @param[in,out] data Data to read from, always moved to currently handled character.
2611 * @param[in,out] siblings Siblings to add to.
2612 *
2613 * @return LY_ERR values.
2614 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002615static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002616parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002617{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002618 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002620 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002621 enum yang_keyword kw;
2622 struct lysp_node *iter;
2623 struct lysp_node_leaflist *llist;
2624
2625 /* create structure */
2626 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002627 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002629 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002630
2631 /* insert into siblings */
2632 if (!*siblings) {
2633 *siblings = (struct lysp_node *)llist;
2634 } else {
2635 for (iter = *siblings; iter->next; iter = iter->next);
2636 iter->next = (struct lysp_node *)llist;
2637 }
2638
2639 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002640 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002641 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002642
2643 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002644 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002645 switch (kw) {
2646 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002647 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002648 break;
2649 case YANG_DEFAULT:
Radek Krejciceaf2122019-01-02 15:03:26 +01002650 YANG_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002651 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 +02002652 break;
2653 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002654 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 +02002655 break;
2656 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002657 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 +02002658 break;
2659 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002660 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002661 break;
2662 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002663 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002664 break;
2665 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002666 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002667 break;
2668 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002669 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002670 break;
2671 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002672 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 +02002673 break;
2674 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002675 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002676 break;
2677 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002678 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002679 break;
2680 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002681 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 +02002682 break;
2683 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002684 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002685 break;
2686 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002687 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002688 break;
2689 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002690 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002691 return LY_EVALID;
2692 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002693 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002694 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002695checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002696 /* mandatory substatements */
2697 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002698 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002699 return LY_EVALID;
2700 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002701 if ((llist->min) && (llist->dflts)) {
2702 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
2703 return LY_EVALID;
2704 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002705 if (llist->max && llist->min > llist->max) {
2706 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
2707 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2708 llist->min, llist->max);
2709 return LY_EVALID;
2710 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002711
2712 return ret;
2713}
2714
Michal Vaskoea5abea2018-09-18 13:10:54 +02002715/**
2716 * @brief Parse the refine statement.
2717 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002718 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002719 * @param[in,out] data Data to read from, always moved to currently handled character.
2720 * @param[in,out] refines Refines to add to.
2721 *
2722 * @return LY_ERR values.
2723 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002724static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002725parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002726{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002727 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002728 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002729 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002730 enum yang_keyword kw;
2731 struct lysp_refine *rf;
2732
Radek Krejci2c4e7172018-10-19 15:56:26 +02002733 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002734
2735 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002736 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002737 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002738
Radek Krejci6d6556c2018-11-08 09:37:45 +01002739 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002740 switch (kw) {
2741 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002742 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002743 break;
2744 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002745 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 +02002746 break;
2747 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002748 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 +02002749 break;
2750 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01002751 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002752 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 +02002753 break;
2754 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002755 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002756 break;
2757 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002758 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002759 break;
2760 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002761 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002762 break;
2763 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002764 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765 break;
2766 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002767 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 +02002768 break;
2769 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002770 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 +02002771 break;
2772 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002773 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002774 break;
2775 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002776 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002777 return LY_EVALID;
2778 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002779 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002780 return ret;
2781}
2782
Michal Vaskoea5abea2018-09-18 13:10:54 +02002783/**
2784 * @brief Parse the typedef statement.
2785 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002786 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002787 * @param[in,out] data Data to read from, always moved to currently handled character.
2788 * @param[in,out] typedefs Typedefs to add to.
2789 *
2790 * @return LY_ERR values.
2791 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002792static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002793parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002794{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002795 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002797 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002798 enum yang_keyword kw;
2799 struct lysp_tpdf *tpdf;
2800
Radek Krejci2c4e7172018-10-19 15:56:26 +02002801 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002802
2803 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002804 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002805 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002806
2807 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002808 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809 switch (kw) {
2810 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002811 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 +02002812 break;
2813 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002814 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 +02002815 break;
2816 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002817 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 +02002818 break;
2819 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002820 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002821 break;
2822 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002823 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002824 break;
2825 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002826 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 +02002827 break;
2828 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002829 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002830 break;
2831 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002832 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002833 return LY_EVALID;
2834 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002835 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002836 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002837checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002838 /* mandatory substatements */
2839 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002840 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002841 return LY_EVALID;
2842 }
2843
Radek Krejcibbe09a92018-11-08 09:36:54 +01002844 /* store data for collision check */
2845 if (parent) {
2846 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2847 }
2848
Michal Vasko7fbc8162018-09-17 10:35:16 +02002849 return ret;
2850}
2851
Michal Vaskoea5abea2018-09-18 13:10:54 +02002852/**
2853 * @brief Parse the input or output statement.
2854 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002855 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002856 * @param[in,out] data Data to read from, always moved to currently handled character.
2857 * @param[in] kw Type of this particular keyword
2858 * @param[in,out] inout_p Input/output pointer to write to.
2859 *
2860 * @return LY_ERR values.
2861 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002862static LY_ERR
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002863parse_inout(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword inout_kw, struct lysp_node *parent, struct lysp_action_inout *inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002864{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002865 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002866 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002867 size_t word_len;
Radek Krejci10113652018-11-14 16:56:50 +01002868 enum yang_keyword kw;
Radek Krejcie86bf772018-12-14 11:39:53 +01002869 unsigned int u;
2870 struct lysp_node *child;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002871
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002872 if (inout_p->nodetype) {
Radek Krejci10113652018-11-14 16:56:50 +01002873 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002874 return LY_EVALID;
2875 }
2876
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002877 /* initiate structure */
2878 inout_p->nodetype = LYS_INOUT;
2879 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002880
2881 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002882 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002883 switch (kw) {
2884 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002885 YANG_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002886 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002887 case YANG_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002888 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002889 break;
2890 case YANG_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002891 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002892 break;
2893 case YANG_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002894 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002895 break;
2896 case YANG_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002897 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002898 break;
2899 case YANG_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002900 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002901 break;
2902 case YANG_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002903 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002904 break;
2905 case YANG_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002906 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002907 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002908 case YANG_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002909 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002910 break;
2911 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002912 YANG_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002913 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002914 break;
2915 case YANG_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002916 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002917 break;
2918 case YANG_CUSTOM:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002919 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002920 break;
2921 default:
Radek Krejci10113652018-11-14 16:56:50 +01002922 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002923 return LY_EVALID;
2924 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002925 }
Radek Krejcie86bf772018-12-14 11:39:53 +01002926 /* finalize parent pointers to the reallocated items */
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002927 LY_ARRAY_FOR(inout_p->groupings, u) {
2928 LY_LIST_FOR(inout_p->groupings[u].data, child) {
2929 child->parent = (struct lysp_node*)&inout_p->groupings[u];
Radek Krejcie86bf772018-12-14 11:39:53 +01002930 }
2931 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932 return ret;
2933}
2934
Michal Vaskoea5abea2018-09-18 13:10:54 +02002935/**
2936 * @brief Parse the action statement.
2937 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002938 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002939 * @param[in,out] data Data to read from, always moved to currently handled character.
2940 * @param[in,out] actions Actions to add to.
2941 *
2942 * @return LY_ERR values.
2943 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002944static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002945parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002946{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002947 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002948 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002949 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002950 enum yang_keyword kw;
2951 struct lysp_action *act;
Radek Krejcie86bf772018-12-14 11:39:53 +01002952 struct lysp_node *child;
2953 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002954
Radek Krejci2c4e7172018-10-19 15:56:26 +02002955 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002956
2957 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002958 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002959 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002960 act->nodetype = LYS_ACTION;
2961 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002962
Radek Krejci6d6556c2018-11-08 09:37:45 +01002963 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002964 switch (kw) {
2965 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002966 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 +02002967 break;
2968 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002969 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 +02002970 break;
2971 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002972 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 +02002973 break;
2974 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002975 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002976 break;
2977
2978 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002979 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002980 break;
2981 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002982 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002983 break;
2984
2985 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002986 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002987 break;
2988 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002989 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002990 break;
2991 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002992 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002993 break;
2994 default:
Radek Krejcif538ce52019-03-05 10:46:14 +01002995 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002996 return LY_EVALID;
2997 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002998 }
Radek Krejcie86bf772018-12-14 11:39:53 +01002999 /* finalize parent pointers to the reallocated items */
3000 LY_ARRAY_FOR(act->groupings, u) {
3001 LY_LIST_FOR(act->groupings[u].data, child) {
3002 child->parent = (struct lysp_node*)&act->groupings[u];
3003 }
3004 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003005 return ret;
3006}
3007
Michal Vaskoea5abea2018-09-18 13:10:54 +02003008/**
3009 * @brief Parse the notification statement.
3010 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003011 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003012 * @param[in,out] data Data to read from, always moved to currently handled character.
3013 * @param[in,out] notifs Notifications to add to.
3014 *
3015 * @return LY_ERR values.
3016 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003017static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003018parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003019{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003020 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003021 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003022 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003023 enum yang_keyword kw;
3024 struct lysp_notif *notif;
Radek Krejcie86bf772018-12-14 11:39:53 +01003025 struct lysp_node *child;
3026 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003027
Radek Krejci2c4e7172018-10-19 15:56:26 +02003028 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003029
3030 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003031 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003032 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003033 notif->nodetype = LYS_NOTIF;
3034 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003035
Radek Krejci6d6556c2018-11-08 09:37:45 +01003036 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003037 switch (kw) {
3038 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003039 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 +02003040 break;
3041 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003042 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 +02003043 break;
3044 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003045 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 +02003046 break;
3047 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003048 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003049 break;
3050
3051 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003052 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01003053 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003054 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003055 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003056 break;
3057 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003058 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003059 break;
3060 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003061 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003062 break;
3063 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003064 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003065 break;
3066 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003067 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003068 break;
3069 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003070 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071 break;
3072 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003073 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003074 break;
3075
3076 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01003077 YANG_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003078 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079 break;
3080 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003081 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003082 break;
3083 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003084 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003085 break;
3086 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003087 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003088 break;
3089 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003090 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003091 return LY_EVALID;
3092 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003093 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003094 /* finalize parent pointers to the reallocated items */
3095 LY_ARRAY_FOR(notif->groupings, u) {
3096 LY_LIST_FOR(notif->groupings[u].data, child) {
3097 child->parent = (struct lysp_node*)&notif->groupings[u];
3098 }
3099 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003100 return ret;
3101}
3102
Michal Vaskoea5abea2018-09-18 13:10:54 +02003103/**
3104 * @brief Parse the grouping statement.
3105 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003106 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003107 * @param[in,out] data Data to read from, always moved to currently handled character.
3108 * @param[in,out] groupings Groupings to add to.
3109 *
3110 * @return LY_ERR values.
3111 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003112static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003113parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003114{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003115 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003116 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003117 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003118 enum yang_keyword kw;
3119 struct lysp_grp *grp;
Radek Krejcie86bf772018-12-14 11:39:53 +01003120 struct lysp_node *child;
3121 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003122
Radek Krejci2c4e7172018-10-19 15:56:26 +02003123 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003124
3125 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003126 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003127 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003128 grp->nodetype = LYS_GROUPING;
3129 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003130
Radek Krejci6d6556c2018-11-08 09:37:45 +01003131 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003132 switch (kw) {
3133 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003134 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 +02003135 break;
3136 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003137 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 +02003138 break;
3139 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003140 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003141 break;
3142
3143 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003144 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01003145 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003146 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003147 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003148 break;
3149 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003150 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003151 break;
3152 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003153 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003154 break;
3155 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003156 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003157 break;
3158 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003159 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003160 break;
3161 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003162 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003163 break;
3164 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003165 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003166 break;
3167
3168 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003169 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003170 break;
3171 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003172 YANG_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003174 break;
3175 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003176 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003177 break;
3178 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003179 YANG_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003180 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003181 break;
3182 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003183 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003184 break;
3185 default:
Radek Krejci10113652018-11-14 16:56:50 +01003186 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003187 return LY_EVALID;
3188 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003189 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003190 /* finalize parent pointers to the reallocated items */
3191 LY_ARRAY_FOR(grp->groupings, u) {
3192 LY_LIST_FOR(grp->groupings[u].data, child) {
3193 child->parent = (struct lysp_node*)&grp->groupings[u];
3194 }
3195 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003196 return ret;
3197}
3198
Michal Vaskoea5abea2018-09-18 13:10:54 +02003199/**
3200 * @brief Parse the refine statement.
3201 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003202 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003203 * @param[in,out] data Data to read from, always moved to currently handled character.
3204 * @param[in,out] augments Augments to add to.
3205 *
3206 * @return LY_ERR values.
3207 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003208static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003209parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003210{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003211 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003212 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003213 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003214 enum yang_keyword kw;
3215 struct lysp_augment *aug;
3216
Radek Krejci2c4e7172018-10-19 15:56:26 +02003217 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003218
3219 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003220 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003221 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003222 aug->nodetype = LYS_AUGMENT;
3223 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224
Radek Krejci6d6556c2018-11-08 09:37:45 +01003225 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003226 switch (kw) {
3227 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003228 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 +02003229 break;
3230 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003231 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 +02003232 break;
3233 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003234 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 +02003235 break;
3236 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003237 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003238 break;
3239 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003240 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003241 break;
3242
3243 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003244 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01003245 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003246 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003247 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003248 break;
3249 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003250 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003251 break;
3252 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003253 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003254 break;
3255 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003256 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003257 break;
3258 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003259 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003260 break;
3261 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003262 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003263 break;
3264 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003265 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003266 break;
3267 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003268 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003269 break;
3270
3271 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003272 YANG_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003273 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003274 break;
3275 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003276 YANG_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003277 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003278 break;
3279 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003280 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003281 break;
3282 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003283 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003284 return LY_EVALID;
3285 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003286 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003287 return ret;
3288}
3289
Michal Vaskoea5abea2018-09-18 13:10:54 +02003290/**
3291 * @brief Parse the uses statement.
3292 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003293 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003294 * @param[in,out] data Data to read from, always moved to currently handled character.
3295 * @param[in,out] siblings Siblings to add to.
3296 *
3297 * @return LY_ERR values.
3298 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003299static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003300parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003301{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003302 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003303 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003304 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003305 enum yang_keyword kw;
3306 struct lysp_node *iter;
3307 struct lysp_node_uses *uses;
3308
3309 /* create structure */
3310 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003311 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003312 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003313 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003314
3315 /* insert into siblings */
3316 if (!*siblings) {
3317 *siblings = (struct lysp_node *)uses;
3318 } else {
3319 for (iter = *siblings; iter->next; iter = iter->next);
3320 iter->next = (struct lysp_node *)uses;
3321 }
3322
3323 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003324 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003325 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003326
3327 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003328 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003329 switch (kw) {
3330 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003331 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 +02003332 break;
3333 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003334 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 +02003335 break;
3336 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003337 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 +02003338 break;
3339 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003340 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003341 break;
3342 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003343 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003344 break;
3345
3346 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003347 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003348 break;
3349 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003350 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003351 break;
3352 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003353 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003354 break;
3355 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003356 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003357 return LY_EVALID;
3358 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003359 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003360 return ret;
3361}
3362
Michal Vaskoea5abea2018-09-18 13:10:54 +02003363/**
3364 * @brief Parse the case statement.
3365 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003366 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003367 * @param[in,out] data Data to read from, always moved to currently handled character.
3368 * @param[in,out] siblings Siblings to add to.
3369 *
3370 * @return LY_ERR values.
3371 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003372static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003373parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003374{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003375 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003376 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003377 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003378 enum yang_keyword kw;
3379 struct lysp_node *iter;
3380 struct lysp_node_case *cas;
3381
3382 /* create structure */
3383 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003384 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003385 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003386 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003387
3388 /* insert into siblings */
3389 if (!*siblings) {
3390 *siblings = (struct lysp_node *)cas;
3391 } else {
3392 for (iter = *siblings; iter->next; iter = iter->next);
3393 iter->next = (struct lysp_node *)cas;
3394 }
3395
3396 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003397 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003398 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003399
3400 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003401 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003402 switch (kw) {
3403 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003404 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 +02003405 break;
3406 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003407 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 +02003408 break;
3409 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003410 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 +02003411 break;
3412 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003413 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003414 break;
3415 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003416 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003417 break;
3418
3419 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003420 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003421 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003423 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003424 break;
3425 case YANG_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003426 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003427 break;
3428 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003429 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003430 break;
3431 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003432 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003433 break;
3434 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003435 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003436 break;
3437 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003438 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003439 break;
3440 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003441 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003442 break;
3443 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003444 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003445 break;
3446 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003447 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003448 return LY_EVALID;
3449 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003450 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003451 return ret;
3452}
3453
Michal Vaskoea5abea2018-09-18 13:10:54 +02003454/**
3455 * @brief Parse the choice statement.
3456 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003457 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003458 * @param[in,out] data Data to read from, always moved to currently handled character.
3459 * @param[in,out] siblings Siblings to add to.
3460 *
3461 * @return LY_ERR values.
3462 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003463static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003464parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003465{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003466 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003467 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003468 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003469 enum yang_keyword kw;
3470 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003471 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003472
3473 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003474 choice = calloc(1, sizeof *choice);
3475 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3476 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003477 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003478
3479 /* insert into siblings */
3480 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003481 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003482 } else {
3483 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003484 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003485 }
3486
3487 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003488 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003489 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003490
3491 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003492 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003493 switch (kw) {
3494 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003495 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003496 break;
3497 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003498 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 +02003499 break;
3500 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003501 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 +02003502 break;
3503 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003504 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003505 break;
3506 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003507 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 +02003508 break;
3509 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003510 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003511 break;
3512 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003513 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003514 break;
3515 case YANG_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003516 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 +02003517 break;
3518
3519 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003520 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003521 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003522 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003523 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003524 break;
3525 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003526 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003527 break;
3528 case YANG_CHOICE:
Radek Krejciceaf2122019-01-02 15:03:26 +01003529 YANG_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003530 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003531 break;
3532 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003533 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003534 break;
3535 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003536 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003537 break;
3538 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003539 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003540 break;
3541 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003542 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 break;
3544 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003545 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003546 break;
3547 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003548 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003549 return LY_EVALID;
3550 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003551 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003552 LY_CHECK_RET(ret);
3553checks:
3554 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
3555 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
3556 return LY_EVALID;
3557 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 return ret;
3559}
3560
Michal Vaskoea5abea2018-09-18 13:10:54 +02003561/**
3562 * @brief Parse the container statement.
3563 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003564 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003565 * @param[in,out] data Data to read from, always moved to currently handled character.
3566 * @param[in,out] siblings Siblings to add to.
3567 *
3568 * @return LY_ERR values.
3569 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003570static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003571parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003572{
3573 LY_ERR ret = 0;
3574 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003575 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003576 enum yang_keyword kw;
3577 struct lysp_node *iter;
3578 struct lysp_node_container *cont;
Radek Krejcie86bf772018-12-14 11:39:53 +01003579 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003580
3581 /* create structure */
3582 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003583 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003585 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003586
3587 /* insert into siblings */
3588 if (!*siblings) {
3589 *siblings = (struct lysp_node *)cont;
3590 } else {
3591 for (iter = *siblings; iter->next; iter = iter->next);
3592 iter->next = (struct lysp_node *)cont;
3593 }
3594
3595 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003596 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003597 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003598
3599 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003600 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003601 switch (kw) {
3602 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003603 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604 break;
3605 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003606 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 +02003607 break;
3608 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003609 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 +02003610 break;
3611 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003612 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 +02003613 break;
3614 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003615 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003616 break;
3617 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003618 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003619 break;
3620 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003621 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 +02003622 break;
3623
3624 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003625 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003626 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003627 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003628 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003629 break;
3630 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003631 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003632 break;
3633 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003634 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003635 break;
3636 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003637 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003638 break;
3639 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003640 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003641 break;
3642 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003643 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003644 break;
3645 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003646 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003647 break;
3648
3649 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003650 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003651 break;
3652 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003653 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003654 break;
3655 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003656 YANG_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003657 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003658 break;
3659 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003660 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003661 break;
3662 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003663 YANG_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003664 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003665 break;
3666 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003667 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003668 break;
3669 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003670 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003671 return LY_EVALID;
3672 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003673 }
Radek Krejcie86bf772018-12-14 11:39:53 +01003674 /* finalize parent pointers to the reallocated items */
3675 LY_ARRAY_FOR(cont->groupings, u) {
3676 LY_LIST_FOR(cont->groupings[u].data, iter) {
3677 iter->parent = (struct lysp_node*)&cont->groupings[u];
3678 }
3679 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003680 return ret;
3681}
3682
Michal Vaskoea5abea2018-09-18 13:10:54 +02003683/**
3684 * @brief Parse the list statement.
3685 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003686 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003687 * @param[in,out] data Data to read from, always moved to currently handled character.
3688 * @param[in,out] siblings Siblings to add to.
3689 *
3690 * @return LY_ERR values.
3691 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003692static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003693parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003694{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003695 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003696 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003697 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003698 enum yang_keyword kw;
3699 struct lysp_node *iter;
3700 struct lysp_node_list *list;
Radek Krejcie86bf772018-12-14 11:39:53 +01003701 unsigned int u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003702
3703 /* create structure */
3704 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003705 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003706 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003707 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003708
3709 /* insert into siblings */
3710 if (!*siblings) {
3711 *siblings = (struct lysp_node *)list;
3712 } else {
3713 for (iter = *siblings; iter->next; iter = iter->next);
3714 iter->next = (struct lysp_node *)list;
3715 }
3716
3717 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003718 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003719 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003720
3721 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003722 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003723 switch (kw) {
3724 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003725 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003726 break;
3727 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003728 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 +02003729 break;
3730 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003731 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 +02003732 break;
3733 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003734 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 +02003735 break;
3736 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003737 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003738 break;
3739 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003740 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003741 break;
3742 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003743 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 +02003744 break;
3745 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003746 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003747 break;
3748 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003749 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003750 break;
3751 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003752 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003753 break;
3754 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003755 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 +02003756 break;
3757
3758 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003759 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003760 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003761 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003762 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003763 break;
3764 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003765 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003766 break;
3767 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003768 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003769 break;
3770 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003771 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003772 break;
3773 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003774 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003775 break;
3776 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003777 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003778 break;
3779 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003780 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003781 break;
3782
3783 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003784 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003785 break;
3786 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003787 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003788 break;
3789 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003790 YANG_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003791 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003792 break;
3793 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003794 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003795 break;
3796 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003797 YANG_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003798 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003799 break;
3800 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003801 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003802 break;
3803 default:
Radek Krejci10113652018-11-14 16:56:50 +01003804 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003805 return LY_EVALID;
3806 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003807 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003808 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01003809 /* finalize parent pointers to the reallocated items */
3810 LY_ARRAY_FOR(list->groupings, u) {
3811 LY_LIST_FOR(list->groupings[u].data, iter) {
3812 iter->parent = (struct lysp_node*)&list->groupings[u];
3813 }
3814 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003815checks:
3816 if (list->max && list->min > list->max) {
3817 LOGVAL_YANG(ctx, LYVE_SEMANTICS,
3818 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3819 list->min, list->max);
3820 return LY_EVALID;
3821 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003822
3823 return ret;
3824}
3825
Michal Vaskoea5abea2018-09-18 13:10:54 +02003826/**
3827 * @brief Parse the yin-element statement.
3828 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003829 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003830 * @param[in,out] data Data to read from, always moved to currently handled character.
3831 * @param[in,out] flags Flags to write to.
3832 * @param[in,out] exts Extension instances to add to.
3833 *
3834 * @return LY_ERR values.
3835 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003836static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003837parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003838{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003839 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003840 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003841 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003842 enum yang_keyword kw;
3843
3844 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003845 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003846 return LY_EVALID;
3847 }
3848
3849 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003850 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003851
3852 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3853 *flags |= LYS_YINELEM_TRUE;
3854 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3855 *flags |= LYS_YINELEM_FALSE;
3856 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003857 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003858 free(buf);
3859 return LY_EVALID;
3860 }
3861 free(buf);
3862
Radek Krejci6d6556c2018-11-08 09:37:45 +01003863 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003864 switch (kw) {
3865 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003866 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3867 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003868 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003869 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003870 return LY_EVALID;
3871 }
3872 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003873 return ret;
3874}
3875
Michal Vaskoea5abea2018-09-18 13:10:54 +02003876/**
3877 * @brief Parse the yin-element statement.
3878 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003879 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003880 * @param[in,out] data Data to read from, always moved to currently handled character.
3881 * @param[in,out] argument Value to write to.
3882 * @param[in,out] flags Flags to write to.
3883 * @param[in,out] exts Extension instances to add to.
3884 *
3885 * @return LY_ERR values.
3886 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003887static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003888parse_argument(struct ly_parser_ctx *ctx, const char **data, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003889{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003890 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003891 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003892 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003893 enum yang_keyword kw;
3894
3895 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003896 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003897 return LY_EVALID;
3898 }
3899
3900 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003901 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003902 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003903
Radek Krejci6d6556c2018-11-08 09:37:45 +01003904 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003905 switch (kw) {
3906 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003907 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908 break;
3909 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003910 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003911 break;
3912 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003913 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003914 return LY_EVALID;
3915 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003916 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003917 return ret;
3918}
3919
Michal Vaskoea5abea2018-09-18 13:10:54 +02003920/**
3921 * @brief Parse the extension statement.
3922 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003923 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003924 * @param[in,out] data Data to read from, always moved to currently handled character.
3925 * @param[in,out] extensions Extensions to add to.
3926 *
3927 * @return LY_ERR values.
3928 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003929static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003930parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003931{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003932 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003933 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003934 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003935 enum yang_keyword kw;
3936 struct lysp_ext *ex;
3937
Radek Krejci2c4e7172018-10-19 15:56:26 +02003938 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003939
3940 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003941 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003942 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003943
Radek Krejci6d6556c2018-11-08 09:37:45 +01003944 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003945 switch (kw) {
3946 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003947 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 +02003948 break;
3949 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003950 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 +02003951 break;
3952 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003953 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003954 break;
3955 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003956 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003957 break;
3958 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003959 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003960 break;
3961 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003962 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003963 return LY_EVALID;
3964 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003965 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003966 return ret;
3967}
3968
Michal Vaskoea5abea2018-09-18 13:10:54 +02003969/**
3970 * @brief Parse the deviate statement.
3971 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003972 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003973 * @param[in,out] data Data to read from, always moved to currently handled character.
3974 * @param[in,out] deviates Deviates to add to.
3975 *
3976 * @return LY_ERR values.
3977 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003978static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003979parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003980{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003981 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003982 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003983 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003984 enum yang_keyword kw;
3985 struct lysp_deviate *iter, *d;
3986 struct lysp_deviate_add *d_add = NULL;
3987 struct lysp_deviate_rpl *d_rpl = NULL;
3988 struct lysp_deviate_del *d_del = NULL;
3989 const char **d_units, ***d_uniques, ***d_dflts;
3990 struct lysp_restr **d_musts;
3991 uint16_t *d_flags;
3992 uint32_t *d_min, *d_max;
3993
3994 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003995 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003996
3997 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3998 dev_mod = LYS_DEV_NOT_SUPPORTED;
3999 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4000 dev_mod = LYS_DEV_ADD;
4001 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4002 dev_mod = LYS_DEV_REPLACE;
4003 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4004 dev_mod = LYS_DEV_DELETE;
4005 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004006 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004007 free(buf);
4008 return LY_EVALID;
4009 }
4010 free(buf);
4011
4012 /* create structure */
4013 switch (dev_mod) {
4014 case LYS_DEV_NOT_SUPPORTED:
4015 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004016 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017 break;
4018 case LYS_DEV_ADD:
4019 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004020 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004021 d = (struct lysp_deviate *)d_add;
4022 d_units = &d_add->units;
4023 d_uniques = &d_add->uniques;
4024 d_dflts = &d_add->dflts;
4025 d_musts = &d_add->musts;
4026 d_flags = &d_add->flags;
4027 d_min = &d_add->min;
4028 d_max = &d_add->max;
4029 break;
4030 case LYS_DEV_REPLACE:
4031 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004032 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004033 d = (struct lysp_deviate *)d_rpl;
4034 d_units = &d_rpl->units;
4035 d_flags = &d_rpl->flags;
4036 d_min = &d_rpl->min;
4037 d_max = &d_rpl->max;
4038 break;
4039 case LYS_DEV_DELETE:
4040 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004041 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004042 d = (struct lysp_deviate *)d_del;
4043 d_units = &d_del->units;
4044 d_uniques = &d_del->uniques;
4045 d_dflts = &d_del->dflts;
4046 d_musts = &d_del->musts;
4047 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004048 break;
4049 default:
4050 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004051 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004052 }
4053 d->mod = dev_mod;
4054
4055 /* insert into siblings */
4056 if (!*deviates) {
4057 *deviates = d;
4058 } else {
4059 for (iter = *deviates; iter->next; iter = iter->next);
4060 iter->next = d;
4061 }
4062
Radek Krejci6d6556c2018-11-08 09:37:45 +01004063 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004064 switch (kw) {
4065 case YANG_CONFIG:
4066 switch (dev_mod) {
4067 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004068 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004069 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004070 return LY_EVALID;
4071 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004072 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004073 break;
4074 }
4075 break;
4076 case YANG_DEFAULT:
4077 switch (dev_mod) {
4078 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004079 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004080 return LY_EVALID;
4081 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004082 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 +02004083 break;
4084 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004085 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 +02004086 break;
4087 }
4088 break;
4089 case YANG_MANDATORY:
4090 switch (dev_mod) {
4091 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004092 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004093 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004094 return LY_EVALID;
4095 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004096 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004097 break;
4098 }
4099 break;
4100 case YANG_MAX_ELEMENTS:
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_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004108 break;
4109 }
4110 break;
4111 case YANG_MIN_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_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004119 break;
4120 }
4121 break;
4122 case YANG_MUST:
4123 switch (dev_mod) {
4124 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004125 case LYS_DEV_REPLACE:
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_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004130 break;
4131 }
4132 break;
4133 case YANG_TYPE:
4134 switch (dev_mod) {
4135 case LYS_DEV_NOT_SUPPORTED:
4136 case LYS_DEV_ADD:
4137 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004138 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004139 return LY_EVALID;
4140 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004141 if (d_rpl->type) {
4142 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4143 return LY_EVALID;
4144 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004145 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004146 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004147 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004148 break;
4149 }
4150 break;
4151 case YANG_UNIQUE:
4152 switch (dev_mod) {
4153 case LYS_DEV_NOT_SUPPORTED:
4154 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004155 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004156 return LY_EVALID;
4157 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004158 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 +02004159 break;
4160 }
4161 break;
4162 case YANG_UNITS:
4163 switch (dev_mod) {
4164 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004165 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004166 return LY_EVALID;
4167 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004168 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 +02004169 break;
4170 }
4171 break;
4172 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004173 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004174 break;
4175 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004176 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004177 return LY_EVALID;
4178 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004180 return ret;
4181}
4182
Michal Vaskoea5abea2018-09-18 13:10:54 +02004183/**
4184 * @brief Parse the deviation statement.
4185 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004186 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004187 * @param[in,out] data Data to read from, always moved to currently handled character.
4188 * @param[in,out] deviations Deviations to add to.
4189 *
4190 * @return LY_ERR values.
4191 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004192static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004193parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004194{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004195 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004196 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004197 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004198 enum yang_keyword kw;
4199 struct lysp_deviation *dev;
4200
Radek Krejci2c4e7172018-10-19 15:56:26 +02004201 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004202
4203 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004204 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004205 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004206
Radek Krejci6d6556c2018-11-08 09:37:45 +01004207 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004208 switch (kw) {
4209 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004210 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 +02004211 break;
4212 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004213 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004214 break;
4215 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004216 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 +02004217 break;
4218 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004219 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004220 break;
4221 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004222 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004223 return LY_EVALID;
4224 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004225 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004226 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004227checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004228 /* mandatory substatements */
4229 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004230 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004231 return LY_EVALID;
4232 }
4233
4234 return ret;
4235}
4236
Michal Vaskoea5abea2018-09-18 13:10:54 +02004237/**
4238 * @brief Parse the feature statement.
4239 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004240 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004241 * @param[in,out] data Data to read from, always moved to currently handled character.
4242 * @param[in,out] features Features to add to.
4243 *
4244 * @return LY_ERR values.
4245 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004246static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004247parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004248{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004249 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004250 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004251 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004252 enum yang_keyword kw;
4253 struct lysp_feature *feat;
4254
Radek Krejci2c4e7172018-10-19 15:56:26 +02004255 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004256
4257 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004258 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004259 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004260
Radek Krejci6d6556c2018-11-08 09:37:45 +01004261 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004262 switch (kw) {
4263 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004264 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 +02004265 break;
4266 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004267 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 +02004268 break;
4269 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004270 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 +02004271 break;
4272 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004273 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004274 break;
4275 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004276 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004277 break;
4278 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004279 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004280 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004281 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004282 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004283 return ret;
4284}
4285
Michal Vaskoea5abea2018-09-18 13:10:54 +02004286/**
4287 * @brief Parse the identity statement.
4288 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004289 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004290 * @param[in,out] data Data to read from, always moved to currently handled character.
4291 * @param[in,out] identities Identities to add to.
4292 *
4293 * @return LY_ERR values.
4294 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004295static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004296parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004297{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004298 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004299 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004300 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004301 enum yang_keyword kw;
4302 struct lysp_ident *ident;
4303
Radek Krejci2c4e7172018-10-19 15:56:26 +02004304 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004305
4306 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004307 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004308 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004309
Radek Krejci6d6556c2018-11-08 09:37:45 +01004310 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004311 switch (kw) {
4312 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004313 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 +02004314 break;
4315 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01004316 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004317 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 +02004318 break;
4319 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004320 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 +02004321 break;
4322 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004323 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004324 break;
4325 case YANG_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004326 if (ident->bases && ctx->mod_version < 2) {
Radek Krejci10113652018-11-14 16:56:50 +01004327 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4328 return LY_EVALID;
4329 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004330 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 +02004331 break;
4332 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004333 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004334 break;
4335 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004336 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004337 return LY_EVALID;
4338 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004339 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004340 return ret;
4341}
4342
Michal Vaskoea5abea2018-09-18 13:10:54 +02004343/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004344 * @brief Finalize some of the (sub)module structure after parsing.
4345 *
4346 * Update parent pointers in the nodes inside grouping/RPC/Notification, which could be reallocated.
4347 *
4348 * @param[in] mod Parsed module to be updated.
4349 * @return LY_ERR value (currently only LY_SUCCESS, but it can change in future).
4350 */
4351static LY_ERR
4352parse_sub_module_finalize(struct lysp_module *mod)
4353{
4354 unsigned int u;
4355 struct lysp_node *child;
4356
4357 /* finalize parent pointers to the reallocated items */
4358 LY_ARRAY_FOR(mod->groupings, u) {
4359 LY_LIST_FOR(mod->groupings[u].data, child) {
4360 child->parent = (struct lysp_node*)&mod->groupings[u];
4361 }
4362 }
4363
4364 /* TODO the same finalization for rpcs and notifications, do also in the relevant nodes */
4365
4366 return LY_SUCCESS;
4367}
4368
4369/**
4370 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004371 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004372 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004373 * @param[in,out] data Data to read from, always moved to currently handled character.
4374 * @param[in,out] mod Module to write to.
4375 *
4376 * @return LY_ERR values.
4377 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004378static LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004379parse_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004380{
4381 LY_ERR ret = 0;
4382 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004383 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004384 enum yang_keyword kw, prev_kw = 0;
4385 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004386 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004387
4388 /* (sub)module name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004389 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004390 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004391
Radek Krejci6d6556c2018-11-08 09:37:45 +01004392 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004393
Radek Krejcie3846472018-10-15 15:24:51 +02004394#define CHECK_ORDER(SECTION) \
4395 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4396
Michal Vasko7fbc8162018-09-17 10:35:16 +02004397 switch (kw) {
4398 /* module header */
4399 case YANG_NAMESPACE:
4400 case YANG_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004401 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4402 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004403 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004404 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004405 break;
4406 /* linkage */
4407 case YANG_INCLUDE:
4408 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004409 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004410 break;
4411 /* meta */
4412 case YANG_ORGANIZATION:
4413 case YANG_CONTACT:
4414 case YANG_DESCRIPTION:
4415 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004416 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004417 break;
4418
4419 /* revision */
4420 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004421 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004423 /* body */
4424 case YANG_ANYDATA:
4425 case YANG_ANYXML:
4426 case YANG_AUGMENT:
4427 case YANG_CHOICE:
4428 case YANG_CONTAINER:
4429 case YANG_DEVIATION:
4430 case YANG_EXTENSION:
4431 case YANG_FEATURE:
4432 case YANG_GROUPING:
4433 case YANG_IDENTITY:
4434 case YANG_LEAF:
4435 case YANG_LEAF_LIST:
4436 case YANG_LIST:
4437 case YANG_NOTIFICATION:
4438 case YANG_RPC:
4439 case YANG_TYPEDEF:
4440 case YANG_USES:
4441 case YANG_CUSTOM:
4442 mod_stmt = Y_MOD_BODY;
4443 break;
4444 default:
4445 /* error handled in the next switch */
4446 break;
4447 }
Radek Krejcie3846472018-10-15 15:24:51 +02004448#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004449
Radek Krejcie3846472018-10-15 15:24:51 +02004450 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004451 switch (kw) {
4452 /* module header */
4453 case YANG_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004454 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4455 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004456 break;
4457 case YANG_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004458 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 +02004459 break;
4460 case YANG_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004461 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 +02004462 break;
4463
4464 /* linkage */
4465 case YANG_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004466 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004467 break;
4468 case YANG_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004469 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004470 break;
4471
4472 /* meta */
4473 case YANG_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004474 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 +02004475 break;
4476 case YANG_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004477 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 +02004478 break;
4479 case YANG_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004480 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 +02004481 break;
4482 case YANG_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004483 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 +02004484 break;
4485
4486 /* revision */
4487 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004488 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004489 break;
4490
4491 /* body */
4492 case YANG_ANYDATA:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004493 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004494 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004495 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004496 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004497 break;
4498 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004499 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004500 break;
4501 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004502 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004503 break;
4504 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004505 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004506 break;
4507 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004508 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004509 break;
4510 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004511 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004512 break;
4513 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004514 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004515 break;
4516
4517 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004518 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004519 break;
4520 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004521 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004522 break;
4523 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004524 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004525 break;
4526 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004527 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004528 break;
4529 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004530 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004531 break;
4532 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004533 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004534 break;
4535 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004536 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004537 break;
4538 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004539 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004540 break;
4541 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004542 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004543 break;
4544 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004545 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004546 break;
4547
4548 default:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004549 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004550 return LY_EVALID;
4551 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004552 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004553 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004554
Radek Krejci6d6556c2018-11-08 09:37:45 +01004555checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004556 /* finalize parent pointers to the reallocated items */
4557 LY_CHECK_RET(parse_sub_module_finalize(mod));
4558
Michal Vasko7fbc8162018-09-17 10:35:16 +02004559 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004560 if (!mod->mod->ns) {
4561 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
4562 return LY_EVALID;
4563 } else if (!mod->mod->prefix) {
4564 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
4565 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004566 }
4567
Radek Krejcie9e987e2018-10-31 12:50:27 +01004568 /* submodules share the namespace with the module names, so there must not be
4569 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004570 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4571 if (dup) {
4572 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
4573 return LY_EVALID;
4574 }
4575
4576 return ret;
4577}
4578
4579/**
4580 * @brief Parse submodule substatements.
4581 *
4582 * @param[in] ctx yang parser context for logging.
4583 * @param[in,out] data Data to read from, always moved to currently handled character.
4584 * @param[out] submod Parsed submodule structure.
4585 *
4586 * @return LY_ERR values.
4587 */
4588static LY_ERR
4589parse_submodule(struct ly_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
4590{
4591 LY_ERR ret = 0;
4592 char *buf, *word;
4593 size_t word_len;
4594 enum yang_keyword kw, prev_kw = 0;
4595 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4596 struct lysp_submodule *dup;
4597
4598 /* submodule name */
4599 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
4600 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4601
4602 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4603
4604#define CHECK_ORDER(SECTION) \
4605 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4606
4607 switch (kw) {
4608 /* module header */
4609 case YANG_BELONGS_TO:
4610 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4611 break;
4612 case YANG_YANG_VERSION:
4613 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4614 break;
4615 /* linkage */
4616 case YANG_INCLUDE:
4617 case YANG_IMPORT:
4618 CHECK_ORDER(Y_MOD_LINKAGE);
4619 break;
4620 /* meta */
4621 case YANG_ORGANIZATION:
4622 case YANG_CONTACT:
4623 case YANG_DESCRIPTION:
4624 case YANG_REFERENCE:
4625 CHECK_ORDER(Y_MOD_META);
4626 break;
4627
4628 /* revision */
4629 case YANG_REVISION:
4630 CHECK_ORDER(Y_MOD_REVISION);
4631 break;
4632 /* body */
4633 case YANG_ANYDATA:
4634 case YANG_ANYXML:
4635 case YANG_AUGMENT:
4636 case YANG_CHOICE:
4637 case YANG_CONTAINER:
4638 case YANG_DEVIATION:
4639 case YANG_EXTENSION:
4640 case YANG_FEATURE:
4641 case YANG_GROUPING:
4642 case YANG_IDENTITY:
4643 case YANG_LEAF:
4644 case YANG_LEAF_LIST:
4645 case YANG_LIST:
4646 case YANG_NOTIFICATION:
4647 case YANG_RPC:
4648 case YANG_TYPEDEF:
4649 case YANG_USES:
4650 case YANG_CUSTOM:
4651 mod_stmt = Y_MOD_BODY;
4652 break;
4653 default:
4654 /* error handled in the next switch */
4655 break;
4656 }
4657#undef CHECK_ORDER
4658
4659 prev_kw = kw;
4660 switch (kw) {
4661 /* module header */
4662 case YANG_YANG_VERSION:
4663 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4664 ctx->mod_version = submod->version;
4665 break;
4666 case YANG_BELONGS_TO:
4667 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4668 break;
4669
4670 /* linkage */
4671 case YANG_INCLUDE:
4672 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4673 break;
4674 case YANG_IMPORT:
4675 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4676 break;
4677
4678 /* meta */
4679 case YANG_ORGANIZATION:
4680 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4681 break;
4682 case YANG_CONTACT:
4683 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4684 break;
4685 case YANG_DESCRIPTION:
4686 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4687 break;
4688 case YANG_REFERENCE:
4689 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4690 break;
4691
4692 /* revision */
4693 case YANG_REVISION:
4694 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4695 break;
4696
4697 /* body */
4698 case YANG_ANYDATA:
4699 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
4700 /* fall through */
4701 case YANG_ANYXML:
4702 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4703 break;
4704 case YANG_CHOICE:
4705 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4706 break;
4707 case YANG_CONTAINER:
4708 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4709 break;
4710 case YANG_LEAF:
4711 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4712 break;
4713 case YANG_LEAF_LIST:
4714 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4715 break;
4716 case YANG_LIST:
4717 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4718 break;
4719 case YANG_USES:
4720 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4721 break;
4722
4723 case YANG_AUGMENT:
4724 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4725 break;
4726 case YANG_DEVIATION:
4727 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4728 break;
4729 case YANG_EXTENSION:
4730 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4731 break;
4732 case YANG_FEATURE:
4733 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4734 break;
4735 case YANG_GROUPING:
4736 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4737 break;
4738 case YANG_IDENTITY:
4739 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4740 break;
4741 case YANG_NOTIFICATION:
4742 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4743 break;
4744 case YANG_RPC:
4745 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4746 break;
4747 case YANG_TYPEDEF:
4748 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4749 break;
4750 case YANG_CUSTOM:
4751 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4752 break;
4753
4754 default:
4755 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
4756 return LY_EVALID;
4757 }
4758 }
4759 LY_CHECK_RET(ret);
4760
4761checks:
4762 /* finalize parent pointers to the reallocated items */
4763 LY_CHECK_RET(parse_sub_module_finalize((struct lysp_module*)submod));
4764
4765 /* mandatory substatements */
4766 if (!submod->belongsto) {
4767 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
4768 return LY_EVALID;
4769 }
4770
4771 /* submodules share the namespace with the module names, so there must not be
4772 * a submodule of the same name in the context, no need for revision matching */
4773 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4774 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
4775 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004776 return LY_EVALID;
4777 }
4778
Michal Vasko7fbc8162018-09-17 10:35:16 +02004779 return ret;
4780}
4781
Radek Krejcid4557c62018-09-17 11:42:09 +02004782LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004783yang_parse_submodule(struct ly_parser_ctx *context, const char *data, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004784{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004785 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004786 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004787 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004788 enum yang_keyword kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004789 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004790
4791 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004792 ret = get_keyword(context, &data, &kw, &word, &word_len);
4793 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004794
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004795 if (kw == YANG_MODULE) {
4796 LOGERR(context->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
4797 ret = LY_EINVAL;
4798 goto cleanup;
4799 } else if (kw != YANG_SUBMODULE) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004800 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004801 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004802 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004803 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004804 }
4805
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004806 mod_p = calloc(1, sizeof *mod_p);
4807 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4808 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004809
4810 /* substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004811 ret = parse_submodule(context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004812 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004813
4814 /* read some trailing spaces or new lines */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004815 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4816 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004817
4818 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004819 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004820 word_len, word);
4821 free(buf);
Radek Krejci40544fa2019-01-11 09:38:37 +01004822 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004823 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004824 }
4825 assert(!buf);
4826
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004827 mod_p->parsing = 0;
4828 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004829
Radek Krejcibbe09a92018-11-08 09:36:54 +01004830cleanup:
4831 if (ret) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004832 lysp_submodule_free(context->ctx, mod_p);
4833 }
4834
4835 return ret;
4836}
4837
4838LY_ERR
4839yang_parse_module(struct ly_parser_ctx *context, const char *data, struct lys_module *mod)
4840{
4841 LY_ERR ret = LY_SUCCESS;
4842 char *word, *buf;
4843 size_t word_len;
4844 enum yang_keyword kw;
4845 struct lysp_module *mod_p = NULL;
4846
4847 /* "module"/"submodule" */
4848 ret = get_keyword(context, &data, &kw, &word, &word_len);
4849 LY_CHECK_GOTO(ret, cleanup);
4850
4851 if (kw == YANG_SUBMODULE) {
4852 LOGERR(context->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
4853 ret = LY_EINVAL;
4854 goto cleanup;
4855 } else if (kw != YANG_MODULE) {
4856 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
4857 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004858 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004859 goto cleanup;
4860 }
4861
4862 mod_p = calloc(1, sizeof *mod_p);
4863 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4864 mod_p->mod = mod;
4865 mod_p->parsing = 1;
4866
4867 /* substatements */
4868 ret = parse_module(context, &data, mod_p);
4869 LY_CHECK_GOTO(ret, cleanup);
4870
4871 /* read some trailing spaces or new lines */
4872 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4873 LY_CHECK_GOTO(ret, cleanup);
4874
4875 if (word) {
4876 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
4877 word_len, word);
4878 free(buf);
Radek Krejci40544fa2019-01-11 09:38:37 +01004879 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004880 goto cleanup;
4881 }
4882 assert(!buf);
4883
4884 mod_p->parsing = 0;
4885 mod->parsed = mod_p;
4886
4887cleanup:
4888 if (ret) {
4889 lysp_module_free(mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004890 }
4891
Michal Vasko7fbc8162018-09-17 10:35:16 +02004892 return ret;
4893}