blob: 5435eabfb6680f466ecb7976337342f13ae1d36f [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
44/* These 2 macros checks YANG's identifier grammar rule */
45#define is_yangidentstartchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
46#define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
47 c == '_' || c == '-' || c == '.')
48
Radek Krejci9fcacc12018-10-11 15:59:11 +020049#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
50 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
51 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020052
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020053#define MOVE_INPUT(CTX, DATA, COUNT) (*(data))+=COUNT;(CTX)->indent+=COUNT
54
Michal Vaskoea5abea2018-09-18 13:10:54 +020055/**
56 * @brief Loop through all substatements providing, return if there are none.
57 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020058 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020059 * @param[in] DATA Raw data to read from.
60 * @param[out] KW YANG keyword read.
61 * @param[out] WORD Pointer to the keyword itself.
62 * @param[out] WORD_LEN Length of the keyword.
63 * @param[out] ERR Variable for error storing.
64 *
65 * @return In case there are no substatements or a fatal error encountered.
66 */
Michal Vasko7fbc8162018-09-17 10:35:16 +020067#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR) \
68 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
Radek Krejcic59bc972018-09-17 16:13:06 +020069 LY_CHECK_RET(ERR); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020070 \
71 if (KW == YANG_SEMICOLON) { \
72 return ERR; \
73 } \
74 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020075 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020076 return LY_EVALID; \
77 } \
78 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
79 !ERR && (KW != YANG_RIGHT_BRACE); \
80 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
81
Radek Krejci44ceedc2018-10-02 15:54:31 +020082static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
83static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
84static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
85static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
86static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
87static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +020088
Michal Vaskoea5abea2018-09-18 13:10:54 +020089/**
90 * @brief Add another character to dynamic buffer, a low-level function.
91 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020092 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +020093 *
Radek Krejci404251e2018-10-09 12:06:44 +020094 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +020095 * @param[in, out] input Input string to process.
96 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +020097 * @param[in,out] buf Buffer to use, can be moved by realloc().
98 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +020099 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200100 *
101 * @return LY_ERR values.
102 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200103static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200104buf_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 +0200105{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200106 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200107 *buf_len += 16;
108 *buf = ly_realloc(*buf, *buf_len);
109 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
110 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200111 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200112
Radek Krejci44ceedc2018-10-02 15:54:31 +0200113 (*buf_used) += len;
114 (*input) += len;
115
Michal Vasko7fbc8162018-09-17 10:35:16 +0200116 return LY_SUCCESS;
117}
118
Michal Vaskoea5abea2018-09-18 13:10:54 +0200119/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200120 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200121 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200122 * @param[in] ctx yang parser context for logging.
123 * @param[in] c UTF8 code point of a character to check.
124 * @return LY_ERR values.
125 */
126static LY_ERR
127check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
128{
129 if (!is_yangutf8char(c)) {
130 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
131 return LY_EVALID;
132 }
133 return LY_SUCCESS;
134}
135
136/**
137 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
138 *
139 * @param[in] ctx yang parser context for logging.
140 * @param[in] c UTF8 code point of a character to check.
141 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200142 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
143 * 0 - colon not yet found (no prefix)
144 * 1 - \p c is the colon character
145 * 2 - prefix already processed, now processing the identifier
146 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200147 * If the identifier cannot be prefixed, NULL is expected.
148 * @return LY_ERR values.
149 */
150static LY_ERR
151check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
152{
153 if (first || (prefix && (*prefix) == 1)) {
154 if (!is_yangidentstartchar(c)) {
155 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
156 return LY_EVALID;
157 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200158 if (prefix) {
159 if (first) {
160 (*prefix) = 0;
161 } else {
162 (*prefix) = 2;
163 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200164 }
165 } else if (c == ':' && prefix && (*prefix) == 0) {
166 (*prefix) = 1;
167 } else if (!is_yangidentchar(c)) {
168 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
169 return LY_EVALID;
170 }
171
172 return LY_SUCCESS;
173}
174
175/**
176 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
177 *
178 * @param[in] ctx yang parser context for logging.
179 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
180 * when function returns.
181 * @param[in] arg Type of the input string to select method of checking character validity.
182 * @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 +0200183 * 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 +0200184 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
185 * @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 +0200186 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200187 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200188 *
189 * @return LY_ERR values.
190 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200191static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200192buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
193 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200194{
Radek Krejci404251e2018-10-09 12:06:44 +0200195 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200196 unsigned int c;
197 size_t len;
198
199 /* get UTF8 code point (and number of bytes coding the character) */
200 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
201 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
202 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200203 if (c == '\n') {
204 ctx->indent = 0;
205 } else {
206 /* note - even the multibyte character is count as 1 */
207 ++ctx->indent;
208 }
209
Radek Krejci44ceedc2018-10-02 15:54:31 +0200210 /* check character validity */
211 switch (arg) {
212 case Y_IDENTIF_ARG:
213 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
214 break;
215 case Y_PREF_IDENTIF_ARG:
216 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
217 break;
218 case Y_STR_ARG:
219 case Y_MAYBE_STR_ARG:
220 LY_CHECK_RET(check_stringchar(ctx, c));
221 break;
222 }
223
Michal Vasko7fbc8162018-09-17 10:35:16 +0200224 if (word_b && *word_b) {
225 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200226 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200227 return LY_EMEM;
228 }
229
230 /* in case of realloc */
231 *word_p = *word_b;
232 } else if (need_buf) {
233 /* first time we need a buffer, copy everything read up to now */
234 if (*word_len) {
235 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200236 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200237 *buf_len = *word_len;
238 memcpy(*word_b, *word_p, *word_len);
239 }
240
241 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200242 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200243 return LY_EMEM;
244 }
245
246 /* in case of realloc */
247 *word_p = *word_b;
248 } else {
249 /* just remember the first character pointer */
250 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200251 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200252 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200253 /* ... and update the word's length */
254 (*word_len) += len;
255 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200256 }
257
258 return LY_SUCCESS;
259}
260
Michal Vaskoea5abea2018-09-18 13:10:54 +0200261/**
262 * @brief Skip YANG comment in data.
263 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200264 * @param[in] ctx yang parser context for logging.
265 * @param[in,out] data Data to read from, automatically moved after the comment.
266 * @param[in] comment Type of the comment to process:
267 * 1 for a one-line comment,
268 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200269 *
270 * @return LY_ERR values.
271 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200272static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200273skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200274{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200275 /* internal statuses: 0 - comment ended,
276 * 1 - in line comment,
277 * 2 - in block comment,
278 * 3 - in block comment with last read character '*'
279 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200280 while (**data && comment) {
281 switch (comment) {
282 case 1:
283 if (**data == '\n') {
284 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200285 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200286 }
287 break;
288 case 2:
289 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200290 comment = 3;
291 } else if (**data == '\n') {
292 ++ctx->line;
293 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200294 break;
295 case 3:
296 if (**data == '/') {
297 comment = 0;
298 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200299 if (**data == '\n') {
300 ++ctx->line;
301 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200302 comment = 2;
303 }
304 break;
305 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200306 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200307 }
308
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200309 if (**data == '\n') {
310 ctx->indent = 0;
311 } else {
312 ++ctx->indent;
313 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200314 ++(*data);
315 }
316
317 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200318 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200319 return LY_EVALID;
320 }
321
322 return LY_SUCCESS;
323}
324
Michal Vaskoea5abea2018-09-18 13:10:54 +0200325/**
326 * @brief Read a quoted string from data.
327 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200328 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200329 * @param[in,out] data Data to read from, always moved to currently handled character.
330 * @param[in] arg Type of YANG keyword argument expected.
331 * @param[out] word_p Pointer to the read quoted string.
332 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
333 * set to NULL. Otherwise equal to \p word_p.
334 * @param[out] word_len Length of the read quoted string.
335 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
336 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
337 * indenation in the final quoted string.
338 *
339 * @return LY_ERR values.
340 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200341static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200342read_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 +0200343 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200344{
345 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
346 * 4 - string finished, now skipping whitespaces looking for +,
347 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200348 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200349 const char *c;
350
351 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200352 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200353 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200354 } else {
355 assert(**data == '\'');
356 string = 1;
357 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200358 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200359
360 while (**data && string) {
361 switch (string) {
362 case 1:
363 switch (**data) {
364 case '\'':
365 /* string may be finished, but check for + */
366 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200367 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200368 break;
369 default:
370 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200371 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 +0200372 break;
373 }
374 break;
375 case 2:
376 switch (**data) {
377 case '\"':
378 /* string may be finished, but check for + */
379 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200380 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200381 break;
382 case '\\':
383 /* special character following */
384 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200385 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200386 break;
387 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200388 if (current_indent < block_indent) {
389 ++current_indent;
390 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200391 } else {
392 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200393 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 +0200394 }
395 break;
396 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200397 if (current_indent < block_indent) {
398 assert(need_buf);
399 current_indent += 8;
400 ctx->indent += 8;
401 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
402 /* store leftover spaces from the tab */
403 c = " ";
404 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 +0200405 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200406 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200407 } else {
408 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200409 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 +0200410 /* additional characters for indentation - only 1 was count in buf_store_char */
411 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200412 }
413 break;
414 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200415 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200416 /* we will be removing the indents so we need our own buffer */
417 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200418
419 /* remove trailing tabs and spaces */
420 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
421 --(*word_len);
422 }
423
424 /* start indentation */
425 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200426 }
427
428 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200429 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
430
431 /* maintain line number */
432 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200433
434 /* reset context indentation counter for possible string after this one */
435 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200436 break;
437 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200438 /* first non-whitespace character, stop eating indentation */
439 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200440
441 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200442 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 +0200443 break;
444 }
445 break;
446 case 3:
447 /* string encoded characters */
448 switch (**data) {
449 case 'n':
450 c = "\n";
451 break;
452 case 't':
453 c = "\t";
454 break;
455 case '\"':
456 c = *data;
457 break;
458 case '\\':
459 c = *data;
460 break;
461 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200462 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200463 return LY_EVALID;
464 }
465
466 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200467 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 +0200468
469 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200470 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200471 break;
472 case 4:
473 switch (**data) {
474 case '+':
475 /* string continues */
476 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200477 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200478 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200479 case '\n':
480 ++ctx->line;
481 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200482 case ' ':
483 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200484 /* just skip */
485 break;
486 default:
487 /* string is finished */
488 goto string_end;
489 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200490 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200491 break;
492 case 5:
493 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200494 case '\n':
495 ++ctx->line;
496 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200497 case ' ':
498 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200499 /* skip */
500 break;
501 case '\'':
502 string = 1;
503 break;
504 case '\"':
505 string = 2;
506 break;
507 default:
508 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200509 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200510 return LY_EVALID;
511 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200512 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200513 break;
514 default:
515 return LY_EINT;
516 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200517 }
518
519string_end:
520 return LY_SUCCESS;
521}
522
Michal Vaskoea5abea2018-09-18 13:10:54 +0200523/**
524 * @brief Get another YANG string from the raw data.
525 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200526 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200527 * @param[in,out] data Data to read from, always moved to currently handled character.
528 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200529 * @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 +0200530 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
531 * set to NULL. Otherwise equal to \p word_p.
532 * @param[out] word_len Length of the read string.
533 *
534 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200535 */
536static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200537get_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 +0200538{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200539 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200540 LY_ERR ret;
541
542 /* word buffer - dynamically allocated */
543 *word_b = NULL;
544
545 /* word pointer - just a pointer to data */
546 *word_p = NULL;
547
548 *word_len = 0;
549 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200550 switch (**data) {
551 case '\'':
552 case '\"':
553 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200554 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
555 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
556 "unquoted string character, optsep, semicolon or opening brace");
557 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200558 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200559 ret = read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200560 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200561 goto str_end;
562 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200563 if ((*data)[1] == '/') {
564 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200565 MOVE_INPUT(ctx, data, 2);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200566 ret = skip_comment(ctx, data, 1);
567 } else if ((*data)[1] == '*') {
568 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200569 MOVE_INPUT(ctx, data, 2);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200570 ret = skip_comment(ctx, data, 2);
571 } else {
572 /* not a comment after all */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200573 ret = buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0);
574 }
575 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200576 break;
577 case ' ':
578 if (*word_len) {
579 /* word is finished */
580 goto str_end;
581 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200582 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200583 break;
584 case '\t':
585 if (*word_len) {
586 /* word is finished */
587 goto str_end;
588 }
589 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200590 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200591
592 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200593 break;
594 case '\n':
595 if (*word_len) {
596 /* word is finished */
597 goto str_end;
598 }
599 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200600 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200601
602 /* track line numbers */
603 ++ctx->line;
604
605 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200606 break;
607 case ';':
608 case '{':
609 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
610 /* word is finished */
611 goto str_end;
612 }
613
Radek Krejci44ceedc2018-10-02 15:54:31 +0200614 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200615 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200616 case '}':
617 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
618 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
619 "unquoted string character, optsep, semicolon or opening brace");
620 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200621 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200622 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 +0200623 break;
624 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200625 }
626
627str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200628 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200629 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200630 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
631 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
632 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200633 *word_p = *word_b;
634 }
635
636 return LY_SUCCESS;
637}
638
Michal Vaskoea5abea2018-09-18 13:10:54 +0200639/**
640 * @brief Get another YANG keyword from the raw data.
641 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200642 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200643 * @param[in,out] data Data to read from, always moved to currently handled character.
644 * @param[out] kw YANG keyword read.
645 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
646 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
647 *
648 * @return LY_ERR values.
649 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200650static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200651get_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 +0200652{
653 LY_ERR ret;
654 int prefix;
655 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200656 unsigned int c;
657 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200658
659 if (word_p) {
660 *word_p = NULL;
661 *word_len = 0;
662 }
663
664 /* first skip "optsep", comments */
665 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200666 switch (**data) {
667 case '/':
668 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200669 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200670 MOVE_INPUT(ctx, data, 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200671 ret = skip_comment(ctx, data, 1);
672 if (ret) {
673 return ret;
674 }
Radek Krejcidcc7b322018-10-11 14:24:02 +0200675 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200676 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200677 MOVE_INPUT(ctx, data, 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200678 ret = skip_comment(ctx, data, 2);
679 if (ret) {
680 return ret;
681 }
682 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200683 /* error - not a comment after all, keyword cannot start with slash */
684 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
685 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200686 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200687 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200688 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200689 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200690 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200691 ctx->indent = 0;
692 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200693 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200694 /* skip whitespaces (optsep) */
695 ++ctx->indent;
696 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200697 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200698 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200699 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200700 break;
701 default:
702 /* either a keyword start or an invalid character */
703 goto keyword_start;
704 }
705
706 ++(*data);
707 }
708
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200709#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
710#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
711#define IF_KW_PREFIX_END }
712
Michal Vasko7fbc8162018-09-17 10:35:16 +0200713keyword_start:
714 word_start = *data;
715 *kw = YANG_NONE;
716
717 /* read the keyword itself */
718 switch (**data) {
719 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200720 MOVE_INPUT(ctx, data, 1);
721 IF_KW("rgument", 7, YANG_ARGUMENT)
722 else IF_KW("ugment", 6, YANG_AUGMENT)
723 else IF_KW("ction", 5, YANG_ACTION)
724 else IF_KW_PREFIX("ny", 2)
725 IF_KW("data", 4, YANG_ANYDATA)
726 else IF_KW("xml", 3, YANG_ANYXML)
727 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200728 break;
729 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200730 MOVE_INPUT(ctx, data, 1);
731 IF_KW("ase", 3, YANG_BASE)
732 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
733 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200734 break;
735 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200736 MOVE_INPUT(ctx, data, 1);
737 IF_KW("ase", 3, YANG_CASE)
738 else IF_KW("hoice", 5, YANG_CHOICE)
739 else IF_KW_PREFIX("on", 2)
740 IF_KW("fig", 3, YANG_CONFIG)
741 else IF_KW_PREFIX("ta", 2)
742 IF_KW("ct", 2, YANG_CONTACT)
743 else IF_KW("iner", 4, YANG_CONTAINER)
744 IF_KW_PREFIX_END
745 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200746 break;
747 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200748 MOVE_INPUT(ctx, data, 1);
749 IF_KW_PREFIX("e", 1)
750 IF_KW("fault", 5, YANG_DEFAULT)
751 else IF_KW("scription", 9, YANG_DESCRIPTION)
752 else IF_KW_PREFIX("viat", 4)
753 IF_KW("e", 1, YANG_DEVIATE)
754 else IF_KW("ion", 3, YANG_DEVIATION)
755 IF_KW_PREFIX_END
756 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200757 break;
758 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200759 MOVE_INPUT(ctx, data, 1);
760 IF_KW("num", 3, YANG_ENUM)
761 else IF_KW_PREFIX("rror-", 5)
762 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
763 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
764 IF_KW_PREFIX_END
765 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200766 break;
767 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200768 MOVE_INPUT(ctx, data, 1);
769 IF_KW("eature", 6, YANG_FEATURE)
770 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200771 break;
772 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200773 MOVE_INPUT(ctx, data, 1);
774 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200775 break;
776 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200777 MOVE_INPUT(ctx, data, 1);
778 IF_KW("dentity", 7, YANG_IDENTITY)
779 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
780 else IF_KW("mport", 5, YANG_IMPORT)
781 else IF_KW_PREFIX("n", 1)
782 IF_KW("clude", 5, YANG_INCLUDE)
783 else IF_KW("put", 3, YANG_INPUT)
784 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200785 break;
786 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200787 MOVE_INPUT(ctx, data, 1);
788 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200789 break;
790 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200791 MOVE_INPUT(ctx, data, 1);
792 IF_KW_PREFIX("e", 1)
793 IF_KW("af-list", 7, YANG_LEAF_LIST)
794 else IF_KW("af", 2, YANG_LEAF)
795 else IF_KW("ngth", 4, YANG_LENGTH)
796 IF_KW_PREFIX_END
797 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200798 break;
799 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200800 MOVE_INPUT(ctx, data, 1);
801 IF_KW_PREFIX("a", 1)
802 IF_KW("ndatory", 7, YANG_MANDATORY)
803 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
804 IF_KW_PREFIX_END
805 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
806 else IF_KW("ust", 3, YANG_MUST)
807 else IF_KW_PREFIX("od", 2)
808 IF_KW("ule", 3, YANG_MODULE)
809 else IF_KW("ifier", 5, YANG_MODIFIER)
810 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200811 break;
812 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200813 MOVE_INPUT(ctx, data, 1);
814 IF_KW("amespace", 8, YANG_NAMESPACE)
815 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200816 break;
817 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200818 MOVE_INPUT(ctx, data, 1);
819 IF_KW_PREFIX("r", 1)
820 IF_KW("dered-by", 8, YANG_ORDERED_BY)
821 else IF_KW("ganization", 10, YANG_ORGANIZATION)
822 IF_KW_PREFIX_END
823 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200824 break;
825 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200826 MOVE_INPUT(ctx, data, 1);
827 IF_KW("ath", 3, YANG_PATH)
828 else IF_KW("attern", 6, YANG_PATTERN)
829 else IF_KW("osition", 7, YANG_POSITION)
830 else IF_KW_PREFIX("re", 2)
831 IF_KW("fix", 3, YANG_PREFIX)
832 else IF_KW("sence", 5, YANG_PRESENCE)
833 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200834 break;
835 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200836 MOVE_INPUT(ctx, data, 1);
837 IF_KW("ange", 4, YANG_RANGE)
838 else IF_KW_PREFIX("e", 1)
839 IF_KW_PREFIX("f", 1)
840 IF_KW("erence", 6, YANG_REFERENCE)
841 else IF_KW("ine", 3, YANG_REFINE)
842 IF_KW_PREFIX_END
843 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
844 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
845 else IF_KW("vision", 6, YANG_REVISION)
846 IF_KW_PREFIX_END
847 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200848 break;
849 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200850 MOVE_INPUT(ctx, data, 1);
851 IF_KW("tatus", 5, YANG_STATUS)
852 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200853 break;
854 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200855 MOVE_INPUT(ctx, data, 1);
856 IF_KW("ypedef", 6, YANG_TYPEDEF)
857 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200858 break;
859 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200860 MOVE_INPUT(ctx, data, 1);
861 IF_KW_PREFIX("ni", 2)
862 IF_KW("que", 3, YANG_UNIQUE)
863 else IF_KW("ts", 2, YANG_UNITS)
864 IF_KW_PREFIX_END
865 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200866 break;
867 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200868 MOVE_INPUT(ctx, data, 1);
869 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200870 break;
871 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200872 MOVE_INPUT(ctx, data, 1);
873 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200874 break;
875 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200876 MOVE_INPUT(ctx, data, 1);
877 IF_KW("ang-version", 11, YANG_YANG_VERSION)
878 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200879 break;
880 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200881 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200882 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200883 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200884 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200885 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200886 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200887 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200888 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200889 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200890 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200891 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200892 default:
893 break;
894 }
895
896 if (*kw != YANG_NONE) {
897 /* make sure we have the whole keyword */
898 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200899 case '\n':
900 ++ctx->line;
901 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200902 case ' ':
903 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200904 /* mandatory "sep" */
905 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200906 case ':':
907 /* keyword is not actually a keyword, but prefix of an extension.
908 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
909 * and we will be checking the keyword (extension instance) itself */
910 prefix = 1;
911 MOVE_INPUT(ctx, data, 1);
912 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200913 case '{':
914 /* allowed only for input and output statements which can be without arguments */
915 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
916 break;
917 }
918 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200919 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200920 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200921 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
922 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200923 return LY_EVALID;
924 }
925 } else {
926 /* still can be an extension */
927 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200928extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200929 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200930 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
931 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200932 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200933 /* check character validity */
934 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200935 }
936 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200937 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200938 return LY_EVALID;
939 }
940
941 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200942 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200943 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200944 return LY_EVALID;
945 }
946
947 *kw = YANG_CUSTOM;
948 }
Radek Krejci626df482018-10-11 15:06:31 +0200949success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200950 if (word_p) {
951 *word_p = (char *)word_start;
952 *word_len = *data - word_start;
953 }
954
955 return LY_SUCCESS;
956}
957
Michal Vaskoea5abea2018-09-18 13:10:54 +0200958/**
959 * @brief Parse extension instance substatements.
960 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200961 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200962 * @param[in,out] data Data to read from, always moved to currently handled character.
963 * @param[in] word Extension instance substatement name (keyword).
964 * @param[in] word_len Extension instance substatement name length.
965 * @param[in,out] child Children of this extension instance to add to.
966 *
967 * @return LY_ERR values.
968 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200969static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200970parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200971 struct lysp_stmt **child)
972{
973 char *buf;
974 LY_ERR ret = 0;
975 enum yang_keyword kw;
976 struct lysp_stmt *stmt, *par_child;
977
978 stmt = calloc(1, sizeof *stmt);
979 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
980
Radek Krejci44ceedc2018-10-02 15:54:31 +0200981 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200982
983 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200984 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +0200985 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200986
Radek Krejci0ae092d2018-09-20 16:43:19 +0200987 if (word) {
988 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200989 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200990 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200991 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200992 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200993 }
994
995 /* insert into parent statements */
996 if (!*child) {
997 *child = stmt;
998 } else {
999 for (par_child = *child; par_child->next; par_child = par_child->next);
1000 par_child->next = stmt;
1001 }
1002
1003 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001004 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001005
1006 ret = parse_ext_substmt(ctx, data, word, word_len, &stmt->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001007 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001008 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001009 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001010
1011 return ret;
1012}
1013
Michal Vaskoea5abea2018-09-18 13:10:54 +02001014/**
1015 * @brief Parse extension instance.
1016 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001017 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001018 * @param[in,out] data Data to read from, always moved to currently handled character.
1019 * @param[in] ext_name Extension instance substatement name (keyword).
1020 * @param[in] ext_name_len Extension instance substatement name length.
1021 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1022 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1023 * @param[in,out] exts Extension instances to add to.
1024 *
1025 * @return LY_ERR values.
1026 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001027static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001028parse_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 +02001029 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1030{
1031 LY_ERR ret = 0;
1032 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001033 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001034 struct lysp_ext_instance *e;
1035 enum yang_keyword kw;
1036
Radek Krejci2c4e7172018-10-19 15:56:26 +02001037 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001038
1039 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001040 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001041 e->insubstmt = insubstmt;
1042 e->insubstmt_index = insubstmt_index;
1043
1044 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001045 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001046 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001047
Radek Krejci0ae092d2018-09-20 16:43:19 +02001048 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001049 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001050 }
1051
1052 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001053 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001054
1055 ret = parse_ext_substmt(ctx, data, word, word_len, &e->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001056 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001057 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001058 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001059
1060 return ret;
1061}
1062
Michal Vaskoea5abea2018-09-18 13:10:54 +02001063/**
1064 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1065 * description, etc...
1066 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001067 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001068 * @param[in,out] data Data to read from, always moved to currently handled character.
1069 * @param[in] substmt Type of this substatement.
1070 * @param[in] substmt_index Index of this substatement.
1071 * @param[in,out] value Place to store the parsed value.
1072 * @param[in] arg Type of the YANG keyword argument (of the value).
1073 * @param[in,out] exts Extension instances to add to.
1074 *
1075 * @return LY_ERR values.
1076 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001077static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001078parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001079 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1080{
1081 LY_ERR ret = 0;
1082 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001083 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001084 enum yang_keyword kw;
1085
1086 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001087 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001088 return LY_EVALID;
1089 }
1090
1091 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001092 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001093 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001094
1095 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001096 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001097
1098 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001099 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001100
1101 switch (kw) {
1102 case YANG_CUSTOM:
1103 ret = parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001104 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001105 break;
1106 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001107 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001108 return LY_EVALID;
1109 }
1110 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001111 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001112
1113 return ret;
1114}
1115
Michal Vaskoea5abea2018-09-18 13:10:54 +02001116/**
1117 * @brief Parse the yang-version statement.
1118 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001119 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001120 * @param[in,out] data Data to read from, always moved to currently handled character.
1121 * @param[in] mod Module to store the parsed information in.
1122 *
1123 * @return LY_ERR values.
1124 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001125static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001126parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001127{
1128 LY_ERR ret = 0;
1129 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001130 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131 enum yang_keyword kw;
1132
1133 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001134 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001135 return LY_EVALID;
1136 }
1137
1138 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001139 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001140 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001141
1142 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1143 mod->version = LYS_VERSION_1_0;
1144 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1145 mod->version = LYS_VERSION_1_1;
1146 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001147 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001148 free(buf);
1149 return LY_EVALID;
1150 }
1151 free(buf);
1152
1153 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001154 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001155
1156 switch (kw) {
1157 case YANG_CUSTOM:
1158 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001159 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001160 break;
1161 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001162 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001163 return LY_EVALID;
1164 }
1165 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001166 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001167
1168 return ret;
1169}
1170
Michal Vaskoea5abea2018-09-18 13:10:54 +02001171/**
1172 * @brief Parse the belongs-to statement.
1173 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001174 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001175 * @param[in,out] data Data to read from, always moved to currently handled character.
1176 * @param[in,out] belongsto Place to store the parsed value.
1177 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1178 * @param[in,out] exts Extension instances to add to.
1179 *
1180 * @return LY_ERR values.
1181 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001182static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001183parse_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 +02001184{
1185 LY_ERR ret = 0;
1186 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001187 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001188 enum yang_keyword kw;
1189
1190 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001191 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001192 return LY_EVALID;
1193 }
1194
1195 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001196 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001197 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001198
Radek Krejci44ceedc2018-10-02 15:54:31 +02001199 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001200 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001201 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001202
1203 switch (kw) {
1204 case YANG_PREFIX:
1205 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts);
1206 break;
1207 case YANG_CUSTOM:
1208 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts);
1209 break;
1210 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001211 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001212 return LY_EVALID;
1213 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001214 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001215 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001216 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001217
1218 /* mandatory substatements */
1219 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001220 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001221 return LY_EVALID;
1222 }
1223
1224 return ret;
1225}
1226
Michal Vaskoea5abea2018-09-18 13:10:54 +02001227/**
1228 * @brief Parse the revision-date statement.
1229 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001230 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001231 * @param[in,out] data Data to read from, always moved to currently handled character.
1232 * @param[in,out] rev Array to store the parsed value in.
1233 * @param[in,out] exts Extension instances to add to.
1234 *
1235 * @return LY_ERR values.
1236 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001237static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001238parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001239{
1240 LY_ERR ret = 0;
1241 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001242 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001243 enum yang_keyword kw;
1244
1245 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001246 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001247 return LY_EVALID;
1248 }
1249
1250 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001251 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001252 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001253
1254 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001255 if (lysp_check_date(ctx->ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001256 free(buf);
1257 return LY_EVALID;
1258 }
1259
1260 /* store value and spend buf if allocated */
1261 strncpy(rev, word, word_len);
1262 free(buf);
1263
1264 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001265 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001266
1267 switch (kw) {
1268 case YANG_CUSTOM:
1269 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001270 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001271 break;
1272 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001273 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001274 return LY_EVALID;
1275 }
1276 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001277 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001278
1279 return ret;
1280}
1281
Michal Vaskoea5abea2018-09-18 13:10:54 +02001282/**
1283 * @brief Parse the include statement.
1284 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001285 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001286 * @param[in,out] data Data to read from, always moved to currently handled character.
1287 * @param[in,out] includes Parsed includes to add to.
1288 *
1289 * @return LY_ERR values.
1290 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001291static LY_ERR
Radek Krejcid33273d2018-10-25 14:55:52 +02001292parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001293{
Radek Krejcid33273d2018-10-25 14:55:52 +02001294 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001295 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001296 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001297 enum yang_keyword kw;
1298 struct lysp_include *inc;
1299
Radek Krejcid33273d2018-10-25 14:55:52 +02001300 LY_ARRAY_NEW_RET(ctx->ctx, mod->includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001301
1302 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001303 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001304 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001305
Radek Krejci086c7132018-10-26 15:29:04 +02001306 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1307
1308 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001309 switch (kw) {
1310 case YANG_DESCRIPTION:
1311 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts);
1312 break;
1313 case YANG_REFERENCE:
1314 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts);
1315 break;
1316 case YANG_REVISION_DATE:
1317 ret = parse_revisiondate(ctx, data, inc->rev, &inc->exts);
1318 break;
1319 case YANG_CUSTOM:
1320 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts);
1321 break;
1322 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001323 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001324 return LY_EVALID;
1325 }
Radek Krejci086c7132018-10-26 15:29:04 +02001326 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001327 }
Radek Krejci086c7132018-10-26 15:29:04 +02001328 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001329
1330 return ret;
1331}
1332
Michal Vaskoea5abea2018-09-18 13:10:54 +02001333/**
1334 * @brief Parse the import statement.
1335 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001336 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001337 * @param[in,out] data Data to read from, always moved to currently handled character.
1338 * @param[in,out] imports Parsed imports to add to.
1339 *
1340 * @return LY_ERR values.
1341 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001342static LY_ERR
Radek Krejci70853c52018-10-15 14:46:16 +02001343parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *module)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001344{
1345 LY_ERR ret = 0;
1346 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001347 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001348 enum yang_keyword kw;
1349 struct lysp_import *imp;
1350
Radek Krejci2c4e7172018-10-19 15:56:26 +02001351 LY_ARRAY_NEW_RET(ctx->ctx, module->imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001352
1353 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001354 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001355 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001356
Radek Krejci44ceedc2018-10-02 15:54:31 +02001357 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001358
Radek Krejci086c7132018-10-26 15:29:04 +02001359 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001360 switch (kw) {
1361 case YANG_PREFIX:
1362 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts);
Radek Krejci70853c52018-10-15 14:46:16 +02001363 LY_CHECK_RET(lysp_check_prefix(ctx, module, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001364 break;
1365 case YANG_DESCRIPTION:
1366 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts);
1367 break;
1368 case YANG_REFERENCE:
1369 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts);
1370 break;
1371 case YANG_REVISION_DATE:
1372 ret = parse_revisiondate(ctx, data, imp->rev, &imp->exts);
1373 break;
1374 case YANG_CUSTOM:
1375 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts);
1376 break;
1377 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001378 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001379 return LY_EVALID;
1380 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001381 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001382 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001383 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001384
1385 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001386 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001387
1388 return ret;
1389}
1390
Michal Vaskoea5abea2018-09-18 13:10:54 +02001391/**
1392 * @brief Parse the revision statement.
1393 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001394 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001395 * @param[in,out] data Data to read from, always moved to currently handled character.
1396 * @param[in,out] revs Parsed revisions to add to.
1397 *
1398 * @return LY_ERR values.
1399 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001400static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001401parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001402{
1403 LY_ERR ret = 0;
1404 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001405 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001406 enum yang_keyword kw;
1407 struct lysp_revision *rev;
1408
Radek Krejci2c4e7172018-10-19 15:56:26 +02001409 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001410
1411 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001412 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001413 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001414
1415 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001416 if (lysp_check_date(ctx->ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001417 return LY_EVALID;
1418 }
1419
Radek Krejcib7db73a2018-10-24 14:18:40 +02001420 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001421 free(buf);
1422
1423 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001424 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001425
1426 switch (kw) {
1427 case YANG_DESCRIPTION:
1428 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts);
1429 break;
1430 case YANG_REFERENCE:
1431 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts);
1432 break;
1433 case YANG_CUSTOM:
1434 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts);
1435 break;
1436 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001437 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438 return LY_EVALID;
1439 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001440 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001441 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001442 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001443
1444 return ret;
1445}
1446
Michal Vaskoea5abea2018-09-18 13:10:54 +02001447/**
1448 * @brief Parse a generic text field that can have more instances such as base.
1449 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001450 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001451 * @param[in,out] data Data to read from, always moved to currently handled character.
1452 * @param[in] substmt Type of this substatement.
1453 * @param[in,out] texts Parsed values to add to.
1454 * @param[in] arg Type of the expected argument.
1455 * @param[in,out] exts Extension instances to add to.
1456 *
1457 * @return LY_ERR values.
1458 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001459static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001460parse_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 +02001461 struct lysp_ext_instance **exts)
1462{
1463 LY_ERR ret = 0;
1464 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001465 const char **item;
1466 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001467 enum yang_keyword kw;
1468
1469 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001470 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001471
1472 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001473 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001474 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001475
Radek Krejci151a5b72018-10-19 14:21:44 +02001476 INSERT_WORD(ctx, buf, *item, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001477 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001478 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001479
1480 switch (kw) {
1481 case YANG_CUSTOM:
Radek Krejci151a5b72018-10-19 14:21:44 +02001482 ret = parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001483 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001484 break;
1485 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001486 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001487 return LY_EVALID;
1488 }
1489 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001490 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001491
1492 return ret;
1493}
1494
Michal Vaskoea5abea2018-09-18 13:10:54 +02001495/**
1496 * @brief Parse the config statement.
1497 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001498 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001499 * @param[in,out] data Data to read from, always moved to currently handled character.
1500 * @param[in,out] flags Flags to add to.
1501 * @param[in,out] exts Extension instances to add to.
1502 *
1503 * @return LY_ERR values.
1504 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001505static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001506parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001507{
1508 LY_ERR ret = 0;
1509 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001510 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001511 enum yang_keyword kw;
1512
1513 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001514 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001515 return LY_EVALID;
1516 }
1517
1518 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001519 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001520 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001521
1522 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1523 *flags |= LYS_CONFIG_W;
1524 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1525 *flags |= LYS_CONFIG_R;
1526 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001527 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001528 free(buf);
1529 return LY_EVALID;
1530 }
1531 free(buf);
1532
1533 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001534 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001535
1536 switch (kw) {
1537 case YANG_CUSTOM:
1538 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001539 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001540 break;
1541 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001542 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001543 return LY_EVALID;
1544 }
1545 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001546 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001547
1548 return ret;
1549}
1550
Michal Vaskoea5abea2018-09-18 13:10:54 +02001551/**
1552 * @brief Parse the mandatory statement.
1553 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001554 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001555 * @param[in,out] data Data to read from, always moved to currently handled character.
1556 * @param[in,out] flags Flags to add to.
1557 * @param[in,out] exts Extension instances to add to.
1558 *
1559 * @return LY_ERR values.
1560 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001561static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001562parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001563{
1564 LY_ERR ret = 0;
1565 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001566 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001567 enum yang_keyword kw;
1568
1569 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001570 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001571 return LY_EVALID;
1572 }
1573
1574 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001575 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001576 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001577
1578 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1579 *flags |= LYS_MAND_TRUE;
1580 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1581 *flags |= LYS_MAND_FALSE;
1582 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001583 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001584 free(buf);
1585 return LY_EVALID;
1586 }
1587 free(buf);
1588
1589 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001590 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001591
1592 switch (kw) {
1593 case YANG_CUSTOM:
1594 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001595 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001596 break;
1597 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001598 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001599 return LY_EVALID;
1600 }
1601 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001602 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001603
1604 return ret;
1605}
1606
Michal Vaskoea5abea2018-09-18 13:10:54 +02001607/**
1608 * @brief Parse a restriction such as range or length.
1609 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001610 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001611 * @param[in,out] data Data to read from, always moved to currently handled character.
1612 * @param[in] restr_kw Type of this particular restriction.
1613 * @param[in,out] exts Extension instances to add to.
1614 *
1615 * @return LY_ERR values.
1616 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001617static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001618parse_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 +02001619{
1620 LY_ERR ret = 0;
1621 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001622 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001623 enum yang_keyword kw;
1624
1625 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001626 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001627 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001628
Radek Krejci44ceedc2018-10-02 15:54:31 +02001629 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001630 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001631 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001632
1633 switch (kw) {
1634 case YANG_DESCRIPTION:
1635 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
1636 break;
1637 case YANG_REFERENCE:
1638 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
1639 break;
1640 case YANG_ERROR_APP_TAG:
1641 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
1642 break;
1643 case YANG_ERROR_MESSAGE:
1644 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
1645 break;
1646 case YANG_CUSTOM:
1647 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
1648 break;
1649 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001650 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001651 return LY_EVALID;
1652 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001653 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001654 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001655 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001656
1657 return ret;
1658}
1659
Michal Vaskoea5abea2018-09-18 13:10:54 +02001660/**
1661 * @brief Parse a restriction that can have more instances such as must.
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] restr_kw Type of this particular restriction.
1666 * @param[in,out] restrs Restrictions 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_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 +02001672{
1673 struct lysp_restr *restr;
1674
Radek Krejci2c4e7172018-10-19 15:56:26 +02001675 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001676
1677 return parse_restr(ctx, data, restr_kw, restr);
1678}
1679
Michal Vaskoea5abea2018-09-18 13:10:54 +02001680/**
1681 * @brief Parse the status statement.
1682 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001683 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001684 * @param[in,out] data Data to read from, always moved to currently handled character.
1685 * @param[in,out] flags Flags to add to.
1686 * @param[in,out] exts Extension instances to add to.
1687 *
1688 * @return LY_ERR values.
1689 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001690static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001691parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001692{
1693 LY_ERR ret = 0;
1694 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001695 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001696 enum yang_keyword kw;
1697
1698 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001699 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001700 return LY_EVALID;
1701 }
1702
1703 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001704 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001705 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001706
1707 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1708 *flags |= LYS_STATUS_CURR;
1709 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1710 *flags |= LYS_STATUS_DEPRC;
1711 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1712 *flags |= LYS_STATUS_OBSLT;
1713 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001714 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001715 free(buf);
1716 return LY_EVALID;
1717 }
1718 free(buf);
1719
1720 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001721 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001722
1723 switch (kw) {
1724 case YANG_CUSTOM:
1725 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001726 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001727 break;
1728 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001729 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001730 return LY_EVALID;
1731 }
1732 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001733 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001734
1735 return ret;
1736}
1737
Michal Vaskoea5abea2018-09-18 13:10:54 +02001738/**
1739 * @brief Parse the when statement.
1740 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001741 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001742 * @param[in,out] data Data to read from, always moved to currently handled character.
1743 * @param[in,out] when_p When pointer to parse to.
1744 *
1745 * @return LY_ERR values.
1746 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001747static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001748parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001749{
1750 LY_ERR ret = 0;
1751 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001752 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001753 enum yang_keyword kw;
1754 struct lysp_when *when;
1755
1756 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001757 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001758 return LY_EVALID;
1759 }
1760
1761 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001762 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001763 *when_p = when;
1764
1765 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001766 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001767 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001768
Radek Krejci44ceedc2018-10-02 15:54:31 +02001769 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001770 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001771 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001772
1773 switch (kw) {
1774 case YANG_DESCRIPTION:
1775 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts);
1776 break;
1777 case YANG_REFERENCE:
1778 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts);
1779 break;
1780 case YANG_CUSTOM:
1781 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts);
1782 break;
1783 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001784 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001785 return LY_EVALID;
1786 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001787 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001788 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001789 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001790
1791 return ret;
1792}
1793
Michal Vaskoea5abea2018-09-18 13:10:54 +02001794/**
1795 * @brief Parse the anydata or anyxml statement.
1796 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001797 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001798 * @param[in,out] data Data to read from, always moved to currently handled character.
1799 * @param[in] kw Type of this particular keyword.
1800 * @param[in,out] siblings Siblings to add to.
1801 *
1802 * @return LY_ERR values.
1803 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001804static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001805parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001806{
1807 LY_ERR ret = 0;
1808 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001809 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001810 struct lysp_node *iter;
1811 struct lysp_node_anydata *any;
1812
1813 /* create structure */
1814 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001815 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001816 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
1817
1818 /* insert into siblings */
1819 if (!*siblings) {
1820 *siblings = (struct lysp_node *)any;
1821 } else {
1822 for (iter = *siblings; iter->next; iter = iter->next);
1823 iter->next = (struct lysp_node *)any;
1824 }
1825
1826 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001827 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001828 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001829
Radek Krejci44ceedc2018-10-02 15:54:31 +02001830 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001831
1832 /* parse substatements */
1833 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001834 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001835
1836 switch (kw) {
1837 case YANG_CONFIG:
1838 ret = parse_config(ctx, data, &any->flags, &any->exts);
1839 break;
1840 case YANG_DESCRIPTION:
1841 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts);
1842 break;
1843 case YANG_IF_FEATURE:
1844 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts);
1845 break;
1846 case YANG_MANDATORY:
1847 ret = parse_mandatory(ctx, data, &any->flags, &any->exts);
1848 break;
1849 case YANG_MUST:
1850 ret = parse_restrs(ctx, data, kw, &any->musts);
1851 break;
1852 case YANG_REFERENCE:
1853 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts);
1854 break;
1855 case YANG_STATUS:
1856 ret = parse_status(ctx, data, &any->flags, &any->exts);
1857 break;
1858 case YANG_WHEN:
1859 ret = parse_when(ctx, data, &any->when);
1860 break;
1861 case YANG_CUSTOM:
1862 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts);
1863 break;
1864 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001865 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001866 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001867 return LY_EVALID;
1868 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001869 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001870 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001871 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001872
1873 return ret;
1874}
1875
Michal Vaskoea5abea2018-09-18 13:10:54 +02001876/**
1877 * @brief Parse the value or position statement. Substatement of type enum statement.
1878 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001879 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001880 * @param[in,out] data Data to read from, always moved to currently handled character.
1881 * @param[in] val_kw Type of this particular keyword.
1882 * @param[in,out] value Value to write to.
1883 * @param[in,out] flags Flags to write to.
1884 * @param[in,out] exts Extension instances to add to.
1885 *
1886 * @return LY_ERR values.
1887 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001888static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001889parse_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 +02001890 struct lysp_ext_instance **exts)
1891{
1892 LY_ERR ret = 0;
1893 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001894 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001895 long int num;
1896 unsigned long int unum;
1897 enum yang_keyword kw;
1898
1899 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001900 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001901 return LY_EVALID;
1902 }
1903 *flags |= LYS_SET_VALUE;
1904
1905 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001906 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001907 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001908
1909 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 +02001910 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001911 free(buf);
1912 return LY_EVALID;
1913 }
1914
1915 errno = 0;
1916 if (val_kw == YANG_VALUE) {
1917 num = strtol(word, &ptr, 10);
1918 } else {
1919 unum = strtoul(word, &ptr, 10);
1920 }
1921 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001922 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001923 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001924 free(buf);
1925 return LY_EVALID;
1926 }
1927 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001928 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001929 free(buf);
1930 return LY_EVALID;
1931 }
1932 if (val_kw == YANG_VALUE) {
1933 *value = num;
1934 } else {
1935 *value = unum;
1936 }
1937 free(buf);
1938
1939 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001940 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001941
1942 switch (kw) {
1943 case YANG_CUSTOM:
1944 ret = parse_ext(ctx, data, word, word_len, val_kw == YANG_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001945 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001946 break;
1947 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001948 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949 return LY_EVALID;
1950 }
1951 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001952 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001953
1954 return ret;
1955}
1956
Michal Vaskoea5abea2018-09-18 13:10:54 +02001957/**
1958 * @brief Parse the enum or bit statement. Substatement of type statement.
1959 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001960 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001961 * @param[in,out] data Data to read from, always moved to currently handled character.
1962 * @param[in] enum_kw Type of this particular keyword.
1963 * @param[in,out] enums Enums or bits to add to.
1964 *
1965 * @return LY_ERR values.
1966 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001967static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001968parse_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 +02001969{
1970 LY_ERR ret = 0;
1971 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001972 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001973 enum yang_keyword kw;
1974 struct lysp_type_enum *enm;
1975
Radek Krejci2c4e7172018-10-19 15:56:26 +02001976 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001977
1978 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001979 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001980 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001981
Radek Krejci44ceedc2018-10-02 15:54:31 +02001982 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001983 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001984 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001985
1986 switch (kw) {
1987 case YANG_DESCRIPTION:
1988 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts);
1989 break;
1990 case YANG_IF_FEATURE:
1991 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts);
1992 break;
1993 case YANG_REFERENCE:
1994 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts);
1995 break;
1996 case YANG_STATUS:
1997 ret = parse_status(ctx, data, &enm->flags, &enm->exts);
1998 break;
1999 case YANG_VALUE:
2000 case YANG_POSITION:
2001 ret = parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts);
2002 break;
2003 case YANG_CUSTOM:
2004 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts);
2005 break;
2006 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002007 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002008 return LY_EVALID;
2009 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002010 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002011 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002012 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002013
2014 return ret;
2015}
2016
Michal Vaskoea5abea2018-09-18 13:10:54 +02002017/**
2018 * @brief Parse the fraction-digits statement. Substatement of type statement.
2019 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002020 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002021 * @param[in,out] data Data to read from, always moved to currently handled character.
2022 * @param[in,out] fracdig Value to write to.
2023 * @param[in,out] exts Extension instances to add to.
2024 *
2025 * @return LY_ERR values.
2026 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002027static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002028parse_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 +02002029{
2030 LY_ERR ret = 0;
2031 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002032 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002033 unsigned long int num;
2034 enum yang_keyword kw;
2035
2036 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002037 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002038 return LY_EVALID;
2039 }
2040
2041 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002042 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002043 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002044
2045 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002046 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002047 free(buf);
2048 return LY_EVALID;
2049 }
2050
2051 errno = 0;
2052 num = strtoul(word, &ptr, 10);
2053 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002054 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002055 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002056 free(buf);
2057 return LY_EVALID;
2058 }
2059 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002060 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002061 free(buf);
2062 return LY_EVALID;
2063 }
2064 *fracdig = num;
2065 free(buf);
2066
2067 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002068 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002069
2070 switch (kw) {
2071 case YANG_CUSTOM:
2072 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002073 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002074 break;
2075 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002076 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002077 return LY_EVALID;
2078 }
2079 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002080 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002081
2082 return ret;
2083}
2084
Michal Vaskoea5abea2018-09-18 13:10:54 +02002085/**
2086 * @brief Parse the require-instance statement. Substatement of type statement.
2087 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002088 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002089 * @param[in,out] data Data to read from, always moved to currently handled character.
2090 * @param[in,out] reqinst Value to write to.
2091 * @param[in,out] flags Flags to write to.
2092 * @param[in,out] exts Extension instances to add to.
2093 *
2094 * @return LY_ERR values.
2095 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002096static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002097parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002098 struct lysp_ext_instance **exts)
2099{
2100 LY_ERR ret = 0;
2101 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002102 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002103 enum yang_keyword kw;
2104
2105 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002106 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002107 return LY_EVALID;
2108 }
2109 *flags |= LYS_SET_REQINST;
2110
2111 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002112 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002113 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002114
2115 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2116 *reqinst = 1;
2117 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002118 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002119 free(buf);
2120 return LY_EVALID;
2121 }
2122 free(buf);
2123
2124 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002125 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002126
2127 switch (kw) {
2128 case YANG_CUSTOM:
2129 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002130 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002131 break;
2132 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002133 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002134 return LY_EVALID;
2135 }
2136 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002137 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002138
2139 return ret;
2140}
2141
Michal Vaskoea5abea2018-09-18 13:10:54 +02002142/**
2143 * @brief Parse the modifier statement. Substatement of type pattern statement.
2144 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002145 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002146 * @param[in,out] data Data to read from, always moved to currently handled character.
2147 * @param[in,out] pat Value to write to.
2148 * @param[in,out] exts Extension instances to add to.
2149 *
2150 * @return LY_ERR values.
2151 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002152static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002153parse_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 +02002154{
2155 LY_ERR ret = 0;
2156 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002157 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002158 enum yang_keyword kw;
2159
2160 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002161 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002162 return LY_EVALID;
2163 }
2164
2165 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002166 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002167 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002168
2169 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002170 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002171 free(buf);
2172 return LY_EVALID;
2173 }
2174 free(buf);
2175
2176 /* replace the value in the dictionary */
2177 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002178 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002179 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002180 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002181
2182 assert(buf[0] == 0x06);
2183 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002184 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002185
2186 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002187 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002188
2189 switch (kw) {
2190 case YANG_CUSTOM:
2191 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002192 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002193 break;
2194 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002195 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002196 return LY_EVALID;
2197 }
2198 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002199 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002200
2201 return ret;
2202}
2203
Michal Vaskoea5abea2018-09-18 13:10:54 +02002204/**
2205 * @brief Parse the pattern statement. Substatement of type statement.
2206 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002207 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002208 * @param[in,out] data Data to read from, always moved to currently handled character.
2209 * @param[in,out] patterns Restrictions to add to.
2210 *
2211 * @return LY_ERR values.
2212 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002213static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002214parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002215{
2216 LY_ERR ret = 0;
2217 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002218 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002219 enum yang_keyword kw;
2220 struct lysp_restr *restr;
2221
Radek Krejci2c4e7172018-10-19 15:56:26 +02002222 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002223
2224 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002225 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002226 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002227
2228 /* add special meaning first byte */
2229 if (buf) {
2230 buf = realloc(buf, word_len + 2);
2231 word = buf;
2232 } else {
2233 buf = malloc(word_len + 2);
2234 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002235 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002236 memmove(buf + 1, word, word_len);
2237 buf[0] = 0x06; /* pattern's default regular-match flag */
2238 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2239 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002240
2241 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002242 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002243
2244 switch (kw) {
2245 case YANG_DESCRIPTION:
2246 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
2247 break;
2248 case YANG_REFERENCE:
2249 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
2250 break;
2251 case YANG_ERROR_APP_TAG:
2252 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
2253 break;
2254 case YANG_ERROR_MESSAGE:
2255 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
2256 break;
2257 case YANG_MODIFIER:
2258 ret = parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts);
2259 break;
2260 case YANG_CUSTOM:
2261 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
2262 break;
2263 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002264 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265 return LY_EVALID;
2266 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002267 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002268 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002269 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002270
2271 return ret;
2272}
2273
Michal Vaskoea5abea2018-09-18 13:10:54 +02002274/**
2275 * @brief Parse the type statement.
2276 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002277 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002278 * @param[in,out] data Data to read from, always moved to currently handled character.
2279 * @param[in,out] type Type to wrote to.
2280 *
2281 * @return LY_ERR values.
2282 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002283static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002284parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002285{
2286 LY_ERR ret = 0;
2287 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002288 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002289 enum yang_keyword kw;
2290 struct lysp_type *nest_type;
2291
2292 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002293 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002294 return LY_EVALID;
2295 }
2296
2297 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002298 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002299 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002300
Radek Krejci44ceedc2018-10-02 15:54:31 +02002301 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002302 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002303 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002304
2305 switch (kw) {
2306 case YANG_BASE:
2307 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts);
2308 break;
2309 case YANG_BIT:
2310 ret = parse_type_enum(ctx, data, kw, &type->bits);
2311 break;
2312 case YANG_ENUM:
2313 ret = parse_type_enum(ctx, data, kw, &type->enums);
2314 break;
2315 case YANG_FRACTION_DIGITS:
2316 ret = parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts);
2317 break;
2318 case YANG_LENGTH:
2319 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002320 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002321 return LY_EVALID;
2322 }
2323 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002324 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002325
2326 ret = parse_restr(ctx, data, kw, type->length);
2327 break;
2328 case YANG_PATH:
2329 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts);
2330 break;
2331 case YANG_PATTERN:
2332 ret = parse_type_pattern(ctx, data, &type->patterns);
2333 break;
2334 case YANG_RANGE:
2335 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002336 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002337 return LY_EVALID;
2338 }
2339 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002340 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002341
2342 ret = parse_restr(ctx, data, kw, type->range);
2343 break;
2344 case YANG_REQUIRE_INSTANCE:
2345 ret = parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts);
2346 break;
2347 case YANG_TYPE:
2348 {
Radek Krejci2c4e7172018-10-19 15:56:26 +02002349 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002350 }
2351 ret = parse_type(ctx, data, nest_type);
2352 break;
2353 case YANG_CUSTOM:
2354 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts);
2355 break;
2356 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002357 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002358 return LY_EVALID;
2359 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002360 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002361 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002362 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002363
2364 return ret;
2365}
2366
Michal Vaskoea5abea2018-09-18 13:10:54 +02002367/**
2368 * @brief Parse the leaf statement.
2369 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002370 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002371 * @param[in,out] data Data to read from, always moved to currently handled character.
2372 * @param[in,out] siblings Siblings to add to.
2373 *
2374 * @return LY_ERR values.
2375 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002376static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002377parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002378{
2379 LY_ERR ret = 0;
2380 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002381 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002382 enum yang_keyword kw;
2383 struct lysp_node *iter;
2384 struct lysp_node_leaf *leaf;
2385
2386 /* create structure */
2387 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002388 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002389 leaf->nodetype = LYS_LEAF;
2390
2391 /* insert into siblings */
2392 if (!*siblings) {
2393 *siblings = (struct lysp_node *)leaf;
2394 } else {
2395 for (iter = *siblings; iter->next; iter = iter->next);
2396 iter->next = (struct lysp_node *)leaf;
2397 }
2398
2399 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002400 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002401 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002402
Radek Krejci44ceedc2018-10-02 15:54:31 +02002403 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002404
2405 /* parse substatements */
2406 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002407 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002408
2409 switch (kw) {
2410 case YANG_CONFIG:
2411 ret = parse_config(ctx, data, &leaf->flags, &leaf->exts);
2412 break;
2413 case YANG_DEFAULT:
2414 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts);
2415 break;
2416 case YANG_DESCRIPTION:
2417 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts);
2418 break;
2419 case YANG_IF_FEATURE:
2420 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts);
2421 break;
2422 case YANG_MANDATORY:
2423 ret = parse_mandatory(ctx, data, &leaf->flags, &leaf->exts);
2424 break;
2425 case YANG_MUST:
2426 ret = parse_restrs(ctx, data, kw, &leaf->musts);
2427 break;
2428 case YANG_REFERENCE:
2429 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts);
2430 break;
2431 case YANG_STATUS:
2432 ret = parse_status(ctx, data, &leaf->flags, &leaf->exts);
2433 break;
2434 case YANG_TYPE:
2435 ret = parse_type(ctx, data, &leaf->type);
2436 break;
2437 case YANG_UNITS:
2438 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts);
2439 break;
2440 case YANG_WHEN:
2441 ret = parse_when(ctx, data, &leaf->when);
2442 break;
2443 case YANG_CUSTOM:
2444 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts);
2445 break;
2446 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002447 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002448 return LY_EVALID;
2449 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002450 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002451 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002452 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002453
2454 /* mandatory substatements */
2455 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002456 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002457 return LY_EVALID;
2458 }
2459
2460 return ret;
2461}
2462
Michal Vaskoea5abea2018-09-18 13:10:54 +02002463/**
2464 * @brief Parse the max-elements statement.
2465 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002466 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002467 * @param[in,out] data Data to read from, always moved to currently handled character.
2468 * @param[in,out] max Value to write to.
2469 * @param[in,out] flags Flags to write to.
2470 * @param[in,out] exts Extension instances to add to.
2471 *
2472 * @return LY_ERR values.
2473 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002474static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002475parse_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 +02002476{
2477 LY_ERR ret = 0;
2478 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002479 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002480 unsigned long int num;
2481 enum yang_keyword kw;
2482
2483 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002484 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485 return LY_EVALID;
2486 }
2487 *flags |= LYS_SET_MAX;
2488
2489 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002490 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002491 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002492
2493 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002494 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002495 free(buf);
2496 return LY_EVALID;
2497 }
2498
2499 if (strncmp(word, "unbounded", word_len)) {
2500 errno = 0;
2501 num = strtoul(word, &ptr, 10);
2502 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002503 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002504 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002505 free(buf);
2506 return LY_EVALID;
2507 }
2508 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002509 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002510 free(buf);
2511 return LY_EVALID;
2512 }
2513
2514 *max = num;
2515 }
2516 free(buf);
2517
2518 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002519 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002520
2521 switch (kw) {
2522 case YANG_CUSTOM:
2523 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002524 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002525 break;
2526 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002527 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002528 return LY_EVALID;
2529 }
2530 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002531 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002532
2533 return ret;
2534}
2535
Michal Vaskoea5abea2018-09-18 13:10:54 +02002536/**
2537 * @brief Parse the min-elements statement.
2538 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002539 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002540 * @param[in,out] data Data to read from, always moved to currently handled character.
2541 * @param[in,out] min Value to write to.
2542 * @param[in,out] flags Flags to write to.
2543 * @param[in,out] exts Extension instances to add to.
2544 *
2545 * @return LY_ERR values.
2546 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002547static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002548parse_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 +02002549{
2550 LY_ERR ret = 0;
2551 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002552 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002553 unsigned long int num;
2554 enum yang_keyword kw;
2555
2556 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002557 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002558 return LY_EVALID;
2559 }
2560 *flags |= LYS_SET_MIN;
2561
2562 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002563 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002564 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002565
2566 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002567 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002568 free(buf);
2569 return LY_EVALID;
2570 }
2571
2572 errno = 0;
2573 num = strtoul(word, &ptr, 10);
2574 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002575 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002576 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002577 free(buf);
2578 return LY_EVALID;
2579 }
2580 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002581 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002582 free(buf);
2583 return LY_EVALID;
2584 }
2585 *min = num;
2586 free(buf);
2587
2588 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002589 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002590
2591 switch (kw) {
2592 case YANG_CUSTOM:
2593 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002594 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002595 break;
2596 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002597 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002598 return LY_EVALID;
2599 }
2600 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002601 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002602
2603 return ret;
2604}
2605
Michal Vaskoea5abea2018-09-18 13:10:54 +02002606/**
2607 * @brief Parse the ordered-by 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] flags Flags to write to.
2612 * @param[in,out] exts Extension instances to add to.
2613 *
2614 * @return LY_ERR values.
2615 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002616static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002617parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002618{
2619 LY_ERR ret = 0;
2620 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002621 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002622 enum yang_keyword kw;
2623
2624 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002625 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002626 return LY_EVALID;
2627 }
2628
2629 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002630 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002631 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002632
2633 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2634 *flags |= LYS_ORDBY_SYSTEM;
2635 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2636 *flags |= LYS_ORDBY_USER;
2637 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002638 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002639 free(buf);
2640 return LY_EVALID;
2641 }
2642 free(buf);
2643
2644 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002645 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002646
2647 switch (kw) {
2648 case YANG_CUSTOM:
2649 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002650 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002651 break;
2652 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002653 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002654 return LY_EVALID;
2655 }
2656 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002657 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002658
2659 return ret;
2660}
2661
Michal Vaskoea5abea2018-09-18 13:10:54 +02002662/**
2663 * @brief Parse the leaf-list statement.
2664 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002665 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002666 * @param[in,out] data Data to read from, always moved to currently handled character.
2667 * @param[in,out] siblings Siblings to add to.
2668 *
2669 * @return LY_ERR values.
2670 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002672parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002673{
2674 LY_ERR ret = 0;
2675 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002676 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002677 enum yang_keyword kw;
2678 struct lysp_node *iter;
2679 struct lysp_node_leaflist *llist;
2680
2681 /* create structure */
2682 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002683 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002684 llist->nodetype = LYS_LEAFLIST;
2685
2686 /* insert into siblings */
2687 if (!*siblings) {
2688 *siblings = (struct lysp_node *)llist;
2689 } else {
2690 for (iter = *siblings; iter->next; iter = iter->next);
2691 iter->next = (struct lysp_node *)llist;
2692 }
2693
2694 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002695 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002696 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002697
Radek Krejci44ceedc2018-10-02 15:54:31 +02002698 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002699
2700 /* parse substatements */
2701 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002702 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002703
2704 switch (kw) {
2705 case YANG_CONFIG:
2706 ret = parse_config(ctx, data, &llist->flags, &llist->exts);
2707 break;
2708 case YANG_DEFAULT:
2709 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts);
2710 break;
2711 case YANG_DESCRIPTION:
2712 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts);
2713 break;
2714 case YANG_IF_FEATURE:
2715 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts);
2716 break;
2717 case YANG_MAX_ELEMENTS:
2718 ret = parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts);
2719 break;
2720 case YANG_MIN_ELEMENTS:
2721 ret = parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts);
2722 break;
2723 case YANG_MUST:
2724 ret = parse_restrs(ctx, data, kw, &llist->musts);
2725 break;
2726 case YANG_ORDERED_BY:
2727 ret = parse_orderedby(ctx, data, &llist->flags, &llist->exts);
2728 break;
2729 case YANG_REFERENCE:
2730 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts);
2731 break;
2732 case YANG_STATUS:
2733 ret = parse_status(ctx, data, &llist->flags, &llist->exts);
2734 break;
2735 case YANG_TYPE:
2736 ret = parse_type(ctx, data, &llist->type);
2737 break;
2738 case YANG_UNITS:
2739 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts);
2740 break;
2741 case YANG_WHEN:
2742 ret = parse_when(ctx, data, &llist->when);
2743 break;
2744 case YANG_CUSTOM:
2745 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts);
2746 break;
2747 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002748 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002749 return LY_EVALID;
2750 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002751 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002752 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002753 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002754
2755 /* mandatory substatements */
2756 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002757 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002758 return LY_EVALID;
2759 }
2760
2761 return ret;
2762}
2763
Michal Vaskoea5abea2018-09-18 13:10:54 +02002764/**
2765 * @brief Parse the refine statement.
2766 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002767 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002768 * @param[in,out] data Data to read from, always moved to currently handled character.
2769 * @param[in,out] refines Refines to add to.
2770 *
2771 * @return LY_ERR values.
2772 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002773static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002774parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002775{
2776 LY_ERR ret = 0;
2777 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002778 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002779 enum yang_keyword kw;
2780 struct lysp_refine *rf;
2781
Radek Krejci2c4e7172018-10-19 15:56:26 +02002782 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002783
2784 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002785 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002786 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002787
Radek Krejci44ceedc2018-10-02 15:54:31 +02002788 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002789 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002790 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002791
2792 switch (kw) {
2793 case YANG_CONFIG:
2794 ret = parse_config(ctx, data, &rf->flags, &rf->exts);
2795 break;
2796 case YANG_DEFAULT:
2797 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts);
2798 break;
2799 case YANG_DESCRIPTION:
2800 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts);
2801 break;
2802 case YANG_IF_FEATURE:
2803 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts);
2804 break;
2805 case YANG_MAX_ELEMENTS:
2806 ret = parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts);
2807 break;
2808 case YANG_MIN_ELEMENTS:
2809 ret = parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts);
2810 break;
2811 case YANG_MUST:
2812 ret = parse_restrs(ctx, data, kw, &rf->musts);
2813 break;
2814 case YANG_MANDATORY:
2815 ret = parse_mandatory(ctx, data, &rf->flags, &rf->exts);
2816 break;
2817 case YANG_REFERENCE:
2818 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts);
2819 break;
2820 case YANG_PRESENCE:
2821 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts);
2822 break;
2823 case YANG_CUSTOM:
2824 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts);
2825 break;
2826 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002827 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002828 return LY_EVALID;
2829 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002830 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002831 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002832 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002833
2834 return ret;
2835}
2836
Michal Vaskoea5abea2018-09-18 13:10:54 +02002837/**
2838 * @brief Parse the typedef statement.
2839 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002840 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002841 * @param[in,out] data Data to read from, always moved to currently handled character.
2842 * @param[in,out] typedefs Typedefs to add to.
2843 *
2844 * @return LY_ERR values.
2845 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002847parse_typedef(struct ly_parser_ctx *ctx, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002848{
2849 LY_ERR ret = 0;
2850 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002851 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002852 enum yang_keyword kw;
2853 struct lysp_tpdf *tpdf;
2854
Radek Krejci2c4e7172018-10-19 15:56:26 +02002855 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002856
2857 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002858 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002859 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860
Radek Krejci44ceedc2018-10-02 15:54:31 +02002861 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002862
2863 /* parse substatements */
2864 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002865 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002866
2867 switch (kw) {
2868 case YANG_DEFAULT:
2869 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts);
2870 break;
2871 case YANG_DESCRIPTION:
2872 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts);
2873 break;
2874 case YANG_REFERENCE:
2875 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts);
2876 break;
2877 case YANG_STATUS:
2878 ret = parse_status(ctx, data, &tpdf->flags, &tpdf->exts);
2879 break;
2880 case YANG_TYPE:
2881 ret = parse_type(ctx, data, &tpdf->type);
2882 break;
2883 case YANG_UNITS:
2884 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts);
2885 break;
2886 case YANG_CUSTOM:
2887 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts);
2888 break;
2889 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002890 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891 return LY_EVALID;
2892 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002893 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002894 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002895 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002896
2897 /* mandatory substatements */
2898 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002899 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002900 return LY_EVALID;
2901 }
2902
2903 return ret;
2904}
2905
Michal Vaskoea5abea2018-09-18 13:10:54 +02002906/**
2907 * @brief Parse the input or output statement.
2908 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002909 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002910 * @param[in,out] data Data to read from, always moved to currently handled character.
2911 * @param[in] kw Type of this particular keyword
2912 * @param[in,out] inout_p Input/output pointer to write to.
2913 *
2914 * @return LY_ERR values.
2915 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002916static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002917parse_inout(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_action_inout **inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918{
2919 LY_ERR ret = 0;
2920 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002921 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002922 struct lysp_action_inout *inout;
2923
2924 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002925 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002926 return LY_EVALID;
2927 }
2928
2929 /* create structure */
2930 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002931 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932 *inout_p = inout;
2933
2934 /* parse substatements */
2935 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002936 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002937
2938 switch (kw) {
2939 case YANG_ANYDATA:
2940 case YANG_ANYXML:
2941 ret = parse_any(ctx, data, kw, &inout->data);
2942 break;
2943 case YANG_CHOICE:
2944 ret = parse_choice(ctx, data, &inout->data);
2945 break;
2946 case YANG_CONTAINER:
2947 ret = parse_container(ctx, data, &inout->data);
2948 break;
2949 case YANG_LEAF:
2950 ret = parse_leaf(ctx, data, &inout->data);
2951 break;
2952 case YANG_LEAF_LIST:
2953 ret = parse_leaflist(ctx, data, &inout->data);
2954 break;
2955 case YANG_LIST:
2956 ret = parse_list(ctx, data, &inout->data);
2957 break;
2958 case YANG_USES:
2959 ret = parse_uses(ctx, data, &inout->data);
2960 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002961 case YANG_TYPEDEF:
2962 ret = parse_typedef(ctx, data, &inout->typedefs);
2963 break;
2964 case YANG_MUST:
2965 ret = parse_restrs(ctx, data, kw, &inout->musts);
2966 break;
2967 case YANG_GROUPING:
2968 ret = parse_grouping(ctx, data, &inout->groupings);
2969 break;
2970 case YANG_CUSTOM:
2971 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts);
2972 break;
2973 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002974 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975 return LY_EVALID;
2976 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002977 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002979 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002980
2981 return ret;
2982}
2983
Michal Vaskoea5abea2018-09-18 13:10:54 +02002984/**
2985 * @brief Parse the action statement.
2986 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002987 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002988 * @param[in,out] data Data to read from, always moved to currently handled character.
2989 * @param[in,out] actions Actions to add to.
2990 *
2991 * @return LY_ERR values.
2992 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002993static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002994parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002995{
2996 LY_ERR ret = 0;
2997 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002998 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002999 enum yang_keyword kw;
3000 struct lysp_action *act;
3001
Radek Krejci2c4e7172018-10-19 15:56:26 +02003002 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003003
3004 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003005 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003006 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003007
Radek Krejci44ceedc2018-10-02 15:54:31 +02003008 INSERT_WORD(ctx, buf, act->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003009 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003010 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003011
3012 switch (kw) {
3013 case YANG_DESCRIPTION:
3014 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts);
3015 break;
3016 case YANG_IF_FEATURE:
3017 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts);
3018 break;
3019 case YANG_REFERENCE:
3020 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts);
3021 break;
3022 case YANG_STATUS:
3023 ret = parse_status(ctx, data, &act->flags, &act->exts);
3024 break;
3025
3026 case YANG_INPUT:
3027 ret = parse_inout(ctx, data, kw, &act->input);
3028 break;
3029 case YANG_OUTPUT:
3030 ret = parse_inout(ctx, data, kw, &act->output);
3031 break;
3032
3033 case YANG_TYPEDEF:
3034 ret = parse_typedef(ctx, data, &act->typedefs);
3035 break;
3036 case YANG_GROUPING:
3037 ret = parse_grouping(ctx, data, &act->groupings);
3038 break;
3039 case YANG_CUSTOM:
3040 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts);
3041 break;
3042 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003043 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003044 return LY_EVALID;
3045 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003046 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003047 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003048 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003049
3050 return ret;
3051}
3052
Michal Vaskoea5abea2018-09-18 13:10:54 +02003053/**
3054 * @brief Parse the notification statement.
3055 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003056 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003057 * @param[in,out] data Data to read from, always moved to currently handled character.
3058 * @param[in,out] notifs Notifications to add to.
3059 *
3060 * @return LY_ERR values.
3061 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003062static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003063parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003064{
3065 LY_ERR ret = 0;
3066 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003067 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003068 enum yang_keyword kw;
3069 struct lysp_notif *notif;
3070
Radek Krejci2c4e7172018-10-19 15:56:26 +02003071 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003072
3073 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003074 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003075 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076
Radek Krejci44ceedc2018-10-02 15:54:31 +02003077 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003078 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003079 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003080
3081 switch (kw) {
3082 case YANG_DESCRIPTION:
3083 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts);
3084 break;
3085 case YANG_IF_FEATURE:
3086 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts);
3087 break;
3088 case YANG_REFERENCE:
3089 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts);
3090 break;
3091 case YANG_STATUS:
3092 ret = parse_status(ctx, data, &notif->flags, &notif->exts);
3093 break;
3094
3095 case YANG_ANYDATA:
3096 case YANG_ANYXML:
3097 ret = parse_any(ctx, data, kw, &notif->data);
3098 break;
3099 case YANG_CHOICE:
3100 ret = parse_case(ctx, data, &notif->data);
3101 break;
3102 case YANG_CONTAINER:
3103 ret = parse_container(ctx, data, &notif->data);
3104 break;
3105 case YANG_LEAF:
3106 ret = parse_leaf(ctx, data, &notif->data);
3107 break;
3108 case YANG_LEAF_LIST:
3109 ret = parse_leaflist(ctx, data, &notif->data);
3110 break;
3111 case YANG_LIST:
3112 ret = parse_list(ctx, data, &notif->data);
3113 break;
3114 case YANG_USES:
3115 ret = parse_uses(ctx, data, &notif->data);
3116 break;
3117
3118 case YANG_MUST:
3119 ret = parse_restrs(ctx, data, kw, &notif->musts);
3120 break;
3121 case YANG_TYPEDEF:
3122 ret = parse_typedef(ctx, data, &notif->typedefs);
3123 break;
3124 case YANG_GROUPING:
3125 ret = parse_grouping(ctx, data, &notif->groupings);
3126 break;
3127 case YANG_CUSTOM:
3128 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts);
3129 break;
3130 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003131 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003132 return LY_EVALID;
3133 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003134 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003136 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003137
3138 return ret;
3139}
3140
Michal Vaskoea5abea2018-09-18 13:10:54 +02003141/**
3142 * @brief Parse the grouping statement.
3143 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003144 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003145 * @param[in,out] data Data to read from, always moved to currently handled character.
3146 * @param[in,out] groupings Groupings to add to.
3147 *
3148 * @return LY_ERR values.
3149 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003150static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003151parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003152{
3153 LY_ERR ret = 0;
3154 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003155 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003156 enum yang_keyword kw;
3157 struct lysp_grp *grp;
3158
Radek Krejci2c4e7172018-10-19 15:56:26 +02003159 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003160
3161 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003162 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003163 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003164
Radek Krejci44ceedc2018-10-02 15:54:31 +02003165 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003166
3167 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003168 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003169
3170 switch (kw) {
3171 case YANG_DESCRIPTION:
3172 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts);
3173 break;
3174 case YANG_REFERENCE:
3175 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts);
3176 break;
3177 case YANG_STATUS:
3178 ret = parse_status(ctx, data, &grp->flags, &grp->exts);
3179 break;
3180
3181 case YANG_ANYDATA:
3182 case YANG_ANYXML:
3183 ret = parse_any(ctx, data, kw, &grp->data);
3184 break;
3185 case YANG_CHOICE:
3186 ret = parse_choice(ctx, data, &grp->data);
3187 break;
3188 case YANG_CONTAINER:
3189 ret = parse_container(ctx, data, &grp->data);
3190 break;
3191 case YANG_LEAF:
3192 ret = parse_leaf(ctx, data, &grp->data);
3193 break;
3194 case YANG_LEAF_LIST:
3195 ret = parse_leaflist(ctx, data, &grp->data);
3196 break;
3197 case YANG_LIST:
3198 ret = parse_list(ctx, data, &grp->data);
3199 break;
3200 case YANG_USES:
3201 ret = parse_uses(ctx, data, &grp->data);
3202 break;
3203
3204 case YANG_TYPEDEF:
3205 ret = parse_typedef(ctx, data, &grp->typedefs);
3206 break;
3207 case YANG_ACTION:
3208 ret = parse_action(ctx, data, &grp->actions);
3209 break;
3210 case YANG_GROUPING:
3211 ret = parse_grouping(ctx, data, &grp->groupings);
3212 break;
3213 case YANG_NOTIFICATION:
3214 ret = parse_notif(ctx, data, &grp->notifs);
3215 break;
3216 case YANG_CUSTOM:
3217 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts);
3218 break;
3219 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003220 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003221 return LY_EVALID;
3222 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003223 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003225 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003226
3227 return ret;
3228}
3229
Michal Vaskoea5abea2018-09-18 13:10:54 +02003230/**
3231 * @brief Parse the refine statement.
3232 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003233 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003234 * @param[in,out] data Data to read from, always moved to currently handled character.
3235 * @param[in,out] augments Augments to add to.
3236 *
3237 * @return LY_ERR values.
3238 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003239static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003240parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003241{
3242 LY_ERR ret = 0;
3243 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003244 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003245 enum yang_keyword kw;
3246 struct lysp_augment *aug;
3247
Radek Krejci2c4e7172018-10-19 15:56:26 +02003248 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003249
3250 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003251 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003252 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003253
Radek Krejci44ceedc2018-10-02 15:54:31 +02003254 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003255 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003256 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003257
3258 switch (kw) {
3259 case YANG_DESCRIPTION:
3260 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts);
3261 break;
3262 case YANG_IF_FEATURE:
3263 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts);
3264 break;
3265 case YANG_REFERENCE:
3266 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts);
3267 break;
3268 case YANG_STATUS:
3269 ret = parse_status(ctx, data, &aug->flags, &aug->exts);
3270 break;
3271 case YANG_WHEN:
3272 ret = parse_when(ctx, data, &aug->when);
3273 break;
3274
3275 case YANG_ANYDATA:
3276 case YANG_ANYXML:
3277 ret = parse_any(ctx, data, kw, &aug->child);
3278 break;
3279 case YANG_CASE:
3280 ret = parse_case(ctx, data, &aug->child);
3281 break;
3282 case YANG_CHOICE:
3283 ret = parse_choice(ctx, data, &aug->child);
3284 break;
3285 case YANG_CONTAINER:
3286 ret = parse_container(ctx, data, &aug->child);
3287 break;
3288 case YANG_LEAF:
3289 ret = parse_leaf(ctx, data, &aug->child);
3290 break;
3291 case YANG_LEAF_LIST:
3292 ret = parse_leaflist(ctx, data, &aug->child);
3293 break;
3294 case YANG_LIST:
3295 ret = parse_list(ctx, data, &aug->child);
3296 break;
3297 case YANG_USES:
3298 ret = parse_uses(ctx, data, &aug->child);
3299 break;
3300
3301 case YANG_ACTION:
3302 ret = parse_action(ctx, data, &aug->actions);
3303 break;
3304 case YANG_NOTIFICATION:
3305 ret = parse_notif(ctx, data, &aug->notifs);
3306 break;
3307 case YANG_CUSTOM:
3308 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts);
3309 break;
3310 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003311 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003312 return LY_EVALID;
3313 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003314 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003315 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003316 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003317
3318 return ret;
3319}
3320
Michal Vaskoea5abea2018-09-18 13:10:54 +02003321/**
3322 * @brief Parse the uses statement.
3323 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003324 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003325 * @param[in,out] data Data to read from, always moved to currently handled character.
3326 * @param[in,out] siblings Siblings to add to.
3327 *
3328 * @return LY_ERR values.
3329 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003330static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003331parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003332{
3333 LY_ERR ret = 0;
3334 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003335 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003336 enum yang_keyword kw;
3337 struct lysp_node *iter;
3338 struct lysp_node_uses *uses;
3339
3340 /* create structure */
3341 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003342 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003343 uses->nodetype = LYS_USES;
3344
3345 /* insert into siblings */
3346 if (!*siblings) {
3347 *siblings = (struct lysp_node *)uses;
3348 } else {
3349 for (iter = *siblings; iter->next; iter = iter->next);
3350 iter->next = (struct lysp_node *)uses;
3351 }
3352
3353 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003354 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003355 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003356
Radek Krejci44ceedc2018-10-02 15:54:31 +02003357 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003358
3359 /* parse substatements */
3360 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003361 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003362
3363 switch (kw) {
3364 case YANG_DESCRIPTION:
3365 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts);
3366 break;
3367 case YANG_IF_FEATURE:
3368 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts);
3369 break;
3370 case YANG_REFERENCE:
3371 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts);
3372 break;
3373 case YANG_STATUS:
3374 ret = parse_status(ctx, data, &uses->flags, &uses->exts);
3375 break;
3376 case YANG_WHEN:
3377 ret = parse_when(ctx, data, &uses->when);
3378 break;
3379
3380 case YANG_REFINE:
3381 ret = parse_refine(ctx, data, &uses->refines);
3382 break;
3383 case YANG_AUGMENT:
3384 ret = parse_augment(ctx, data, &uses->augments);
3385 break;
3386 case YANG_CUSTOM:
3387 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts);
3388 break;
3389 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003390 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003391 return LY_EVALID;
3392 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003393 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003394 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003395 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003396
3397 return ret;
3398}
3399
Michal Vaskoea5abea2018-09-18 13:10:54 +02003400/**
3401 * @brief Parse the case statement.
3402 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003403 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003404 * @param[in,out] data Data to read from, always moved to currently handled character.
3405 * @param[in,out] siblings Siblings to add to.
3406 *
3407 * @return LY_ERR values.
3408 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003409static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003410parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003411{
3412 LY_ERR ret = 0;
3413 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003414 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003415 enum yang_keyword kw;
3416 struct lysp_node *iter;
3417 struct lysp_node_case *cas;
3418
3419 /* create structure */
3420 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003421 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422 cas->nodetype = LYS_CASE;
3423
3424 /* insert into siblings */
3425 if (!*siblings) {
3426 *siblings = (struct lysp_node *)cas;
3427 } else {
3428 for (iter = *siblings; iter->next; iter = iter->next);
3429 iter->next = (struct lysp_node *)cas;
3430 }
3431
3432 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003433 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003434 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003435
Radek Krejci44ceedc2018-10-02 15:54:31 +02003436 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003437
3438 /* parse substatements */
3439 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003440 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003441
3442 switch (kw) {
3443 case YANG_DESCRIPTION:
3444 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts);
3445 break;
3446 case YANG_IF_FEATURE:
3447 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts);
3448 break;
3449 case YANG_REFERENCE:
3450 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts);
3451 break;
3452 case YANG_STATUS:
3453 ret = parse_status(ctx, data, &cas->flags, &cas->exts);
3454 break;
3455 case YANG_WHEN:
3456 ret = parse_when(ctx, data, &cas->when);
3457 break;
3458
3459 case YANG_ANYDATA:
3460 case YANG_ANYXML:
3461 ret = parse_any(ctx, data, kw, &cas->child);
3462 break;
3463 case YANG_CHOICE:
3464 ret = parse_case(ctx, data, &cas->child);
3465 break;
3466 case YANG_CONTAINER:
3467 ret = parse_container(ctx, data, &cas->child);
3468 break;
3469 case YANG_LEAF:
3470 ret = parse_leaf(ctx, data, &cas->child);
3471 break;
3472 case YANG_LEAF_LIST:
3473 ret = parse_leaflist(ctx, data, &cas->child);
3474 break;
3475 case YANG_LIST:
3476 ret = parse_list(ctx, data, &cas->child);
3477 break;
3478 case YANG_USES:
3479 ret = parse_uses(ctx, data, &cas->child);
3480 break;
3481 case YANG_CUSTOM:
3482 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts);
3483 break;
3484 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003485 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003486 return LY_EVALID;
3487 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003488 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003489 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003490 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003491
3492 return ret;
3493}
3494
Michal Vaskoea5abea2018-09-18 13:10:54 +02003495/**
3496 * @brief Parse the choice statement.
3497 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003498 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003499 * @param[in,out] data Data to read from, always moved to currently handled character.
3500 * @param[in,out] siblings Siblings to add to.
3501 *
3502 * @return LY_ERR values.
3503 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003504static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003505parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003506{
3507 LY_ERR ret = 0;
3508 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003509 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003510 enum yang_keyword kw;
3511 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003512 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003513
3514 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003515 choice = calloc(1, sizeof *choice);
3516 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3517 choice->nodetype = LYS_CHOICE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003518
3519 /* insert into siblings */
3520 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003521 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003522 } else {
3523 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003524 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003525 }
3526
3527 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003528 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003529 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530
Radek Krejci44ceedc2018-10-02 15:54:31 +02003531 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003532
3533 /* parse substatements */
3534 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003535 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536
3537 switch (kw) {
3538 case YANG_CONFIG:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003539 ret = parse_config(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003540 break;
3541 case YANG_DESCRIPTION:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003542 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 break;
3544 case YANG_IF_FEATURE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003545 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003546 break;
3547 case YANG_MANDATORY:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003548 ret = parse_mandatory(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003549 break;
3550 case YANG_REFERENCE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003551 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003552 break;
3553 case YANG_STATUS:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003554 ret = parse_status(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003555 break;
3556 case YANG_WHEN:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003557 ret = parse_when(ctx, data, &choice->when);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 break;
3559 case YANG_DEFAULT:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003560 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_IDENTIF_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561 break;
3562
3563 case YANG_ANYDATA:
3564 case YANG_ANYXML:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003565 ret = parse_any(ctx, data, kw, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003566 break;
3567 case YANG_CASE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003568 ret = parse_case(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569 break;
3570 case YANG_CHOICE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003571 ret = parse_choice(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003572 break;
3573 case YANG_CONTAINER:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003574 ret = parse_container(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003575 break;
3576 case YANG_LEAF:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003577 ret = parse_leaf(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578 break;
3579 case YANG_LEAF_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003580 ret = parse_leaflist(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003581 break;
3582 case YANG_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003583 ret = parse_list(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584 break;
3585 case YANG_CUSTOM:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003586 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003587 break;
3588 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003589 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590 return LY_EVALID;
3591 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003592 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003593 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003594 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003595
3596 return ret;
3597}
3598
Michal Vaskoea5abea2018-09-18 13:10:54 +02003599/**
3600 * @brief Parse the container statement.
3601 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003602 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003603 * @param[in,out] data Data to read from, always moved to currently handled character.
3604 * @param[in,out] siblings Siblings to add to.
3605 *
3606 * @return LY_ERR values.
3607 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003608static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003609parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610{
3611 LY_ERR ret = 0;
3612 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003613 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003614 enum yang_keyword kw;
3615 struct lysp_node *iter;
3616 struct lysp_node_container *cont;
3617
3618 /* create structure */
3619 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003620 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003621 cont->nodetype = LYS_CONTAINER;
3622
3623 /* insert into siblings */
3624 if (!*siblings) {
3625 *siblings = (struct lysp_node *)cont;
3626 } else {
3627 for (iter = *siblings; iter->next; iter = iter->next);
3628 iter->next = (struct lysp_node *)cont;
3629 }
3630
3631 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003632 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003633 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003634
Radek Krejci44ceedc2018-10-02 15:54:31 +02003635 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003636
3637 /* parse substatements */
3638 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003639 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003640
3641 switch (kw) {
3642 case YANG_CONFIG:
3643 ret = parse_config(ctx, data, &cont->flags, &cont->exts);
3644 break;
3645 case YANG_DESCRIPTION:
3646 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts);
3647 break;
3648 case YANG_IF_FEATURE:
3649 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts);
3650 break;
3651 case YANG_REFERENCE:
3652 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts);
3653 break;
3654 case YANG_STATUS:
3655 ret = parse_status(ctx, data, &cont->flags, &cont->exts);
3656 break;
3657 case YANG_WHEN:
3658 ret = parse_when(ctx, data, &cont->when);
3659 break;
3660 case YANG_PRESENCE:
3661 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts);
3662 break;
3663
3664 case YANG_ANYDATA:
3665 case YANG_ANYXML:
3666 ret = parse_any(ctx, data, kw, &cont->child);
3667 break;
3668 case YANG_CHOICE:
3669 ret = parse_choice(ctx, data, &cont->child);
3670 break;
3671 case YANG_CONTAINER:
3672 ret = parse_container(ctx, data, &cont->child);
3673 break;
3674 case YANG_LEAF:
3675 ret = parse_leaf(ctx, data, &cont->child);
3676 break;
3677 case YANG_LEAF_LIST:
3678 ret = parse_leaflist(ctx, data, &cont->child);
3679 break;
3680 case YANG_LIST:
3681 ret = parse_list(ctx, data, &cont->child);
3682 break;
3683 case YANG_USES:
3684 ret = parse_uses(ctx, data, &cont->child);
3685 break;
3686
3687 case YANG_TYPEDEF:
3688 ret = parse_typedef(ctx, data, &cont->typedefs);
3689 break;
3690 case YANG_MUST:
3691 ret = parse_restrs(ctx, data, kw, &cont->musts);
3692 break;
3693 case YANG_ACTION:
3694 ret = parse_action(ctx, data, &cont->actions);
3695 break;
3696 case YANG_GROUPING:
3697 ret = parse_grouping(ctx, data, &cont->groupings);
3698 break;
3699 case YANG_NOTIFICATION:
3700 ret = parse_notif(ctx, data, &cont->notifs);
3701 break;
3702 case YANG_CUSTOM:
3703 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts);
3704 break;
3705 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003706 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003707 return LY_EVALID;
3708 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003709 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003710 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003711 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003712
3713 return ret;
3714}
3715
Michal Vaskoea5abea2018-09-18 13:10:54 +02003716/**
3717 * @brief Parse the list statement.
3718 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003719 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003720 * @param[in,out] data Data to read from, always moved to currently handled character.
3721 * @param[in,out] siblings Siblings to add to.
3722 *
3723 * @return LY_ERR values.
3724 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003726parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003727{
3728 LY_ERR ret = 0;
3729 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003730 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003731 enum yang_keyword kw;
3732 struct lysp_node *iter;
3733 struct lysp_node_list *list;
3734
3735 /* create structure */
3736 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003737 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003738 list->nodetype = LYS_LIST;
3739
3740 /* insert into siblings */
3741 if (!*siblings) {
3742 *siblings = (struct lysp_node *)list;
3743 } else {
3744 for (iter = *siblings; iter->next; iter = iter->next);
3745 iter->next = (struct lysp_node *)list;
3746 }
3747
3748 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003749 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003750 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003751
Radek Krejci44ceedc2018-10-02 15:54:31 +02003752 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003753
3754 /* parse substatements */
3755 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003756 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003757
3758 switch (kw) {
3759 case YANG_CONFIG:
3760 ret = parse_config(ctx, data, &list->flags, &list->exts);
3761 break;
3762 case YANG_DESCRIPTION:
3763 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts);
3764 break;
3765 case YANG_IF_FEATURE:
3766 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts);
3767 break;
3768 case YANG_REFERENCE:
3769 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts);
3770 break;
3771 case YANG_STATUS:
3772 ret = parse_status(ctx, data, &list->flags, &list->exts);
3773 break;
3774 case YANG_WHEN:
3775 ret = parse_when(ctx, data, &list->when);
3776 break;
3777 case YANG_KEY:
3778 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts);
3779 break;
3780 case YANG_MAX_ELEMENTS:
3781 ret = parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts);
3782 break;
3783 case YANG_MIN_ELEMENTS:
3784 ret = parse_minelements(ctx, data, &list->min, &list->flags, &list->exts);
3785 break;
3786 case YANG_ORDERED_BY:
3787 ret = parse_orderedby(ctx, data, &list->flags, &list->exts);
3788 break;
3789 case YANG_UNIQUE:
3790 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts);
3791 break;
3792
3793 case YANG_ANYDATA:
3794 case YANG_ANYXML:
3795 ret = parse_any(ctx, data, kw, &list->child);
3796 break;
3797 case YANG_CHOICE:
3798 ret = parse_choice(ctx, data, &list->child);
3799 break;
3800 case YANG_CONTAINER:
3801 ret = parse_container(ctx, data, &list->child);
3802 break;
3803 case YANG_LEAF:
3804 ret = parse_leaf(ctx, data, &list->child);
3805 break;
3806 case YANG_LEAF_LIST:
3807 ret = parse_leaflist(ctx, data, &list->child);
3808 break;
3809 case YANG_LIST:
3810 ret = parse_list(ctx, data, &list->child);
3811 break;
3812 case YANG_USES:
3813 ret = parse_uses(ctx, data, &list->child);
3814 break;
3815
3816 case YANG_TYPEDEF:
3817 ret = parse_typedef(ctx, data, &list->typedefs);
3818 break;
3819 case YANG_MUST:
3820 ret = parse_restrs(ctx, data, kw, &list->musts);
3821 break;
3822 case YANG_ACTION:
3823 ret = parse_action(ctx, data, &list->actions);
3824 break;
3825 case YANG_GROUPING:
3826 ret = parse_grouping(ctx, data, &list->groupings);
3827 break;
3828 case YANG_NOTIFICATION:
3829 ret = parse_notif(ctx, data, &list->notifs);
3830 break;
3831 case YANG_CUSTOM:
3832 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts);
3833 break;
3834 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003835 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003836 return LY_EVALID;
3837 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003838 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003839 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003840 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003841
3842 return ret;
3843}
3844
Michal Vaskoea5abea2018-09-18 13:10:54 +02003845/**
3846 * @brief Parse the yin-element statement.
3847 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003848 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003849 * @param[in,out] data Data to read from, always moved to currently handled character.
3850 * @param[in,out] flags Flags to write to.
3851 * @param[in,out] exts Extension instances to add to.
3852 *
3853 * @return LY_ERR values.
3854 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003855static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003856parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857{
3858 LY_ERR ret = 0;
3859 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003860 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003861 enum yang_keyword kw;
3862
3863 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003864 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003865 return LY_EVALID;
3866 }
3867
3868 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003869 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003870 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003871
3872 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3873 *flags |= LYS_YINELEM_TRUE;
3874 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3875 *flags |= LYS_YINELEM_FALSE;
3876 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003877 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003878 free(buf);
3879 return LY_EVALID;
3880 }
3881 free(buf);
3882
3883 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003884 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003885
3886 switch (kw) {
3887 case YANG_CUSTOM:
3888 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02003889 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003890 break;
3891 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003892 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003893 return LY_EVALID;
3894 }
3895 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003896 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003897
3898 return ret;
3899}
3900
Michal Vaskoea5abea2018-09-18 13:10:54 +02003901/**
3902 * @brief Parse the yin-element statement.
3903 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003904 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003905 * @param[in,out] data Data to read from, always moved to currently handled character.
3906 * @param[in,out] argument Value to write to.
3907 * @param[in,out] flags Flags to write to.
3908 * @param[in,out] exts Extension instances to add to.
3909 *
3910 * @return LY_ERR values.
3911 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003912static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003913parse_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 +02003914{
3915 LY_ERR ret = 0;
3916 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003917 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003918 enum yang_keyword kw;
3919
3920 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003921 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 return LY_EVALID;
3923 }
3924
3925 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003926 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003927 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003928
Radek Krejci44ceedc2018-10-02 15:54:31 +02003929 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003930 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003931 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003932
3933 switch (kw) {
3934 case YANG_YIN_ELEMENT:
3935 ret = parse_yinelement(ctx, data, flags, exts);
3936 break;
3937 case YANG_CUSTOM:
3938 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts);
3939 break;
3940 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003941 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003942 return LY_EVALID;
3943 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003944 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003945 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003946 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003947
3948 return ret;
3949}
3950
Michal Vaskoea5abea2018-09-18 13:10:54 +02003951/**
3952 * @brief Parse the extension statement.
3953 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003954 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003955 * @param[in,out] data Data to read from, always moved to currently handled character.
3956 * @param[in,out] extensions Extensions to add to.
3957 *
3958 * @return LY_ERR values.
3959 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003960static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003961parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003962{
3963 LY_ERR ret = 0;
3964 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003965 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003966 enum yang_keyword kw;
3967 struct lysp_ext *ex;
3968
Radek Krejci2c4e7172018-10-19 15:56:26 +02003969 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003970
3971 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003972 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003973 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003974
Radek Krejci44ceedc2018-10-02 15:54:31 +02003975 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003976 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003977 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003978
3979 switch (kw) {
3980 case YANG_DESCRIPTION:
3981 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts);
3982 break;
3983 case YANG_REFERENCE:
3984 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts);
3985 break;
3986 case YANG_STATUS:
3987 ret = parse_status(ctx, data, &ex->flags, &ex->exts);
3988 break;
3989 case YANG_ARGUMENT:
3990 ret = parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts);
3991 break;
3992 case YANG_CUSTOM:
3993 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts);
3994 break;
3995 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003996 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003997 return LY_EVALID;
3998 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003999 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004000 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004001 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004002
4003 return ret;
4004}
4005
Michal Vaskoea5abea2018-09-18 13:10:54 +02004006/**
4007 * @brief Parse the deviate statement.
4008 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004009 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004010 * @param[in,out] data Data to read from, always moved to currently handled character.
4011 * @param[in,out] deviates Deviates to add to.
4012 *
4013 * @return LY_ERR values.
4014 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004015static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004016parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017{
4018 LY_ERR ret = 0;
4019 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004020 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004021 enum yang_keyword kw;
4022 struct lysp_deviate *iter, *d;
4023 struct lysp_deviate_add *d_add = NULL;
4024 struct lysp_deviate_rpl *d_rpl = NULL;
4025 struct lysp_deviate_del *d_del = NULL;
4026 const char **d_units, ***d_uniques, ***d_dflts;
4027 struct lysp_restr **d_musts;
4028 uint16_t *d_flags;
4029 uint32_t *d_min, *d_max;
4030
4031 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004032 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004033 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004034
4035 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4036 dev_mod = LYS_DEV_NOT_SUPPORTED;
4037 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4038 dev_mod = LYS_DEV_ADD;
4039 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4040 dev_mod = LYS_DEV_REPLACE;
4041 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4042 dev_mod = LYS_DEV_DELETE;
4043 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004044 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004045 free(buf);
4046 return LY_EVALID;
4047 }
4048 free(buf);
4049
4050 /* create structure */
4051 switch (dev_mod) {
4052 case LYS_DEV_NOT_SUPPORTED:
4053 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004054 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004055 break;
4056 case LYS_DEV_ADD:
4057 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004058 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004059 d = (struct lysp_deviate *)d_add;
4060 d_units = &d_add->units;
4061 d_uniques = &d_add->uniques;
4062 d_dflts = &d_add->dflts;
4063 d_musts = &d_add->musts;
4064 d_flags = &d_add->flags;
4065 d_min = &d_add->min;
4066 d_max = &d_add->max;
4067 break;
4068 case LYS_DEV_REPLACE:
4069 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004070 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004071 d = (struct lysp_deviate *)d_rpl;
4072 d_units = &d_rpl->units;
4073 d_flags = &d_rpl->flags;
4074 d_min = &d_rpl->min;
4075 d_max = &d_rpl->max;
4076 break;
4077 case LYS_DEV_DELETE:
4078 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004079 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004080 d = (struct lysp_deviate *)d_del;
4081 d_units = &d_del->units;
4082 d_uniques = &d_del->uniques;
4083 d_dflts = &d_del->dflts;
4084 d_musts = &d_del->musts;
4085 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004086 break;
4087 default:
4088 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004089 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004090 }
4091 d->mod = dev_mod;
4092
4093 /* insert into siblings */
4094 if (!*deviates) {
4095 *deviates = d;
4096 } else {
4097 for (iter = *deviates; iter->next; iter = iter->next);
4098 iter->next = d;
4099 }
4100
4101 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004102 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004103
4104 switch (kw) {
4105 case YANG_CONFIG:
4106 switch (dev_mod) {
4107 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004108 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004109 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004110 return LY_EVALID;
4111 default:
4112 ret = parse_config(ctx, data, d_flags, &d->exts);
4113 break;
4114 }
4115 break;
4116 case YANG_DEFAULT:
4117 switch (dev_mod) {
4118 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004119 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004120 return LY_EVALID;
4121 case LYS_DEV_REPLACE:
4122 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts);
4123 break;
4124 default:
4125 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts);
4126 break;
4127 }
4128 break;
4129 case YANG_MANDATORY:
4130 switch (dev_mod) {
4131 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004132 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004133 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004134 return LY_EVALID;
4135 default:
4136 ret = parse_mandatory(ctx, data, d_flags, &d->exts);
4137 break;
4138 }
4139 break;
4140 case YANG_MAX_ELEMENTS:
4141 switch (dev_mod) {
4142 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004143 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004144 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004145 return LY_EVALID;
4146 default:
4147 ret = parse_maxelements(ctx, data, d_max, d_flags, &d->exts);
4148 break;
4149 }
4150 break;
4151 case YANG_MIN_ELEMENTS:
4152 switch (dev_mod) {
4153 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004154 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004155 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004156 return LY_EVALID;
4157 default:
4158 ret = parse_minelements(ctx, data, d_min, d_flags, &d->exts);
4159 break;
4160 }
4161 break;
4162 case YANG_MUST:
4163 switch (dev_mod) {
4164 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004165 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004166 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004167 return LY_EVALID;
4168 default:
4169 ret = parse_restrs(ctx, data, kw, d_musts);
4170 break;
4171 }
4172 break;
4173 case YANG_TYPE:
4174 switch (dev_mod) {
4175 case LYS_DEV_NOT_SUPPORTED:
4176 case LYS_DEV_ADD:
4177 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004178 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179 return LY_EVALID;
4180 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004181 if (d_rpl->type) {
4182 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4183 return LY_EVALID;
4184 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004185 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004186 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004187 ret = parse_type(ctx, data, d_rpl->type);
4188 break;
4189 }
4190 break;
4191 case YANG_UNIQUE:
4192 switch (dev_mod) {
4193 case LYS_DEV_NOT_SUPPORTED:
4194 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004195 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004196 return LY_EVALID;
4197 default:
4198 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts);
4199 break;
4200 }
4201 break;
4202 case YANG_UNITS:
4203 switch (dev_mod) {
4204 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004205 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004206 return LY_EVALID;
4207 default:
4208 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts);
4209 break;
4210 }
4211 break;
4212 case YANG_CUSTOM:
4213 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts);
4214 break;
4215 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004216 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004217 return LY_EVALID;
4218 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004219 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004220 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004221 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004222
4223 return ret;
4224}
4225
Michal Vaskoea5abea2018-09-18 13:10:54 +02004226/**
4227 * @brief Parse the deviation statement.
4228 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004229 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004230 * @param[in,out] data Data to read from, always moved to currently handled character.
4231 * @param[in,out] deviations Deviations to add to.
4232 *
4233 * @return LY_ERR values.
4234 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004235static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004236parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004237{
4238 LY_ERR ret = 0;
4239 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004240 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004241 enum yang_keyword kw;
4242 struct lysp_deviation *dev;
4243
Radek Krejci2c4e7172018-10-19 15:56:26 +02004244 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004245
4246 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004247 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004248 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004249
Radek Krejci44ceedc2018-10-02 15:54:31 +02004250 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004251 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004252 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004253
4254 switch (kw) {
4255 case YANG_DESCRIPTION:
4256 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts);
4257 break;
4258 case YANG_DEVIATE:
4259 ret = parse_deviate(ctx, data, &dev->deviates);
4260 break;
4261 case YANG_REFERENCE:
4262 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts);
4263 break;
4264 case YANG_CUSTOM:
4265 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts);
4266 break;
4267 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004268 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004269 return LY_EVALID;
4270 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004271 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004272 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004273 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004274
4275 /* mandatory substatements */
4276 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004277 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004278 return LY_EVALID;
4279 }
4280
4281 return ret;
4282}
4283
Michal Vaskoea5abea2018-09-18 13:10:54 +02004284/**
4285 * @brief Parse the feature statement.
4286 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004287 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004288 * @param[in,out] data Data to read from, always moved to currently handled character.
4289 * @param[in,out] features Features to add to.
4290 *
4291 * @return LY_ERR values.
4292 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004293static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004294parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004295{
4296 LY_ERR ret = 0;
4297 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004298 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004299 enum yang_keyword kw;
4300 struct lysp_feature *feat;
4301
Radek Krejci2c4e7172018-10-19 15:56:26 +02004302 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004303
4304 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004305 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004306 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004307
Radek Krejci44ceedc2018-10-02 15:54:31 +02004308 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004309 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004310 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004311
4312 switch (kw) {
4313 case YANG_DESCRIPTION:
4314 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts);
4315 break;
4316 case YANG_IF_FEATURE:
4317 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts);
4318 break;
4319 case YANG_REFERENCE:
4320 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts);
4321 break;
4322 case YANG_STATUS:
4323 ret = parse_status(ctx, data, &feat->flags, &feat->exts);
4324 break;
4325 case YANG_CUSTOM:
4326 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts);
4327 break;
4328 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004329 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004330 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004331 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004332 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004333 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004334 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004335
4336 return ret;
4337}
4338
Michal Vaskoea5abea2018-09-18 13:10:54 +02004339/**
4340 * @brief Parse the identity statement.
4341 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004342 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004343 * @param[in,out] data Data to read from, always moved to currently handled character.
4344 * @param[in,out] identities Identities to add to.
4345 *
4346 * @return LY_ERR values.
4347 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004348static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004349parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004350{
4351 LY_ERR ret = 0;
4352 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004353 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004354 enum yang_keyword kw;
4355 struct lysp_ident *ident;
4356
Radek Krejci2c4e7172018-10-19 15:56:26 +02004357 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004358
4359 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004360 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004361 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004362
Radek Krejci44ceedc2018-10-02 15:54:31 +02004363 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004364 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004365 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004366
4367 switch (kw) {
4368 case YANG_DESCRIPTION:
4369 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts);
4370 break;
4371 case YANG_IF_FEATURE:
4372 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts);
4373 break;
4374 case YANG_REFERENCE:
4375 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts);
4376 break;
4377 case YANG_STATUS:
4378 ret = parse_status(ctx, data, &ident->flags, &ident->exts);
4379 break;
4380 case YANG_BASE:
4381 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts);
4382 break;
4383 case YANG_CUSTOM:
4384 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts);
4385 break;
4386 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004387 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004388 return LY_EVALID;
4389 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004390 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004391 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004392
4393 return ret;
4394}
4395
Michal Vaskoea5abea2018-09-18 13:10:54 +02004396/**
4397 * @brief Parse the module or submodule statement.
4398 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004399 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004400 * @param[in,out] data Data to read from, always moved to currently handled character.
4401 * @param[in,out] mod Module to write to.
4402 *
4403 * @return LY_ERR values.
4404 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004405static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004406parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004407{
4408 LY_ERR ret = 0;
4409 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004410 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004411 enum yang_keyword kw, prev_kw = 0;
4412 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4413
4414 /* (sub)module name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004415 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004416 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004417
Radek Krejci44ceedc2018-10-02 15:54:31 +02004418 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004419 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004420 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004421
Radek Krejcie3846472018-10-15 15:24:51 +02004422#define CHECK_ORDER(SECTION) \
4423 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4424
Michal Vasko7fbc8162018-09-17 10:35:16 +02004425 switch (kw) {
4426 /* module header */
4427 case YANG_NAMESPACE:
4428 case YANG_PREFIX:
4429 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004430 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004431 return LY_EVALID;
4432 }
Radek Krejcie3846472018-10-15 15:24:51 +02004433 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4434 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004435 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004436 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004437 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004438 return LY_EVALID;
4439 }
Radek Krejcie3846472018-10-15 15:24:51 +02004440 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4441 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004442 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004443 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004444 break;
4445 /* linkage */
4446 case YANG_INCLUDE:
4447 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004448 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004449 break;
4450 /* meta */
4451 case YANG_ORGANIZATION:
4452 case YANG_CONTACT:
4453 case YANG_DESCRIPTION:
4454 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004455 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004456 break;
4457
4458 /* revision */
4459 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004460 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004461 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004462 /* body */
4463 case YANG_ANYDATA:
4464 case YANG_ANYXML:
4465 case YANG_AUGMENT:
4466 case YANG_CHOICE:
4467 case YANG_CONTAINER:
4468 case YANG_DEVIATION:
4469 case YANG_EXTENSION:
4470 case YANG_FEATURE:
4471 case YANG_GROUPING:
4472 case YANG_IDENTITY:
4473 case YANG_LEAF:
4474 case YANG_LEAF_LIST:
4475 case YANG_LIST:
4476 case YANG_NOTIFICATION:
4477 case YANG_RPC:
4478 case YANG_TYPEDEF:
4479 case YANG_USES:
4480 case YANG_CUSTOM:
4481 mod_stmt = Y_MOD_BODY;
4482 break;
4483 default:
4484 /* error handled in the next switch */
4485 break;
4486 }
Radek Krejcie3846472018-10-15 15:24:51 +02004487#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004488
Radek Krejcie3846472018-10-15 15:24:51 +02004489 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004490 switch (kw) {
4491 /* module header */
4492 case YANG_YANG_VERSION:
4493 ret = parse_yangversion(ctx, data, mod);
4494 break;
4495 case YANG_NAMESPACE:
4496 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts);
4497 break;
4498 case YANG_PREFIX:
4499 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts);
Radek Krejci70853c52018-10-15 14:46:16 +02004500 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004501 break;
4502 case YANG_BELONGS_TO:
4503 ret = parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts);
4504 break;
4505
4506 /* linkage */
4507 case YANG_INCLUDE:
Radek Krejcid33273d2018-10-25 14:55:52 +02004508 ret = parse_include(ctx, data, mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004509 break;
4510 case YANG_IMPORT:
Radek Krejci70853c52018-10-15 14:46:16 +02004511 ret = parse_import(ctx, data, mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004512 break;
4513
4514 /* meta */
4515 case YANG_ORGANIZATION:
4516 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts);
4517 break;
4518 case YANG_CONTACT:
4519 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts);
4520 break;
4521 case YANG_DESCRIPTION:
4522 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts);
4523 break;
4524 case YANG_REFERENCE:
4525 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts);
4526 break;
4527
4528 /* revision */
4529 case YANG_REVISION:
4530 ret = parse_revision(ctx, data, &mod->revs);
4531 break;
4532
4533 /* body */
4534 case YANG_ANYDATA:
4535 case YANG_ANYXML:
4536 ret = parse_any(ctx, data, kw, &mod->data);
4537 break;
4538 case YANG_CHOICE:
4539 ret = parse_choice(ctx, data, &mod->data);
4540 break;
4541 case YANG_CONTAINER:
4542 ret = parse_container(ctx, data, &mod->data);
4543 break;
4544 case YANG_LEAF:
4545 ret = parse_leaf(ctx, data, &mod->data);
4546 break;
4547 case YANG_LEAF_LIST:
4548 ret = parse_leaflist(ctx, data, &mod->data);
4549 break;
4550 case YANG_LIST:
4551 ret = parse_list(ctx, data, &mod->data);
4552 break;
4553 case YANG_USES:
4554 ret = parse_uses(ctx, data, &mod->data);
4555 break;
4556
4557 case YANG_AUGMENT:
4558 ret = parse_augment(ctx, data, &mod->augments);
4559 break;
4560 case YANG_DEVIATION:
4561 ret = parse_deviation(ctx, data, &mod->deviations);
4562 break;
4563 case YANG_EXTENSION:
4564 ret = parse_extension(ctx, data, &mod->extensions);
4565 break;
4566 case YANG_FEATURE:
4567 ret = parse_feature(ctx, data, &mod->features);
4568 break;
4569 case YANG_GROUPING:
4570 ret = parse_grouping(ctx, data, &mod->groupings);
4571 break;
4572 case YANG_IDENTITY:
4573 ret = parse_identity(ctx, data, &mod->identities);
4574 break;
4575 case YANG_NOTIFICATION:
4576 ret = parse_notif(ctx, data, &mod->notifs);
4577 break;
4578 case YANG_RPC:
4579 ret = parse_action(ctx, data, &mod->rpcs);
4580 break;
4581 case YANG_TYPEDEF:
4582 ret = parse_typedef(ctx, data, &mod->typedefs);
4583 break;
4584 case YANG_CUSTOM:
4585 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts);
4586 break;
4587
4588 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004589 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004590 return LY_EVALID;
4591 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004592 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004593 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004594 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004595
4596 /* mandatory substatements */
4597 if (mod->submodule) {
4598 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004599 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004600 return LY_EVALID;
4601 }
4602 } else {
4603 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004604 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004605 return LY_EVALID;
4606 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004607 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004608 return LY_EVALID;
4609 }
4610 }
4611
4612 return ret;
4613}
4614
Radek Krejcid4557c62018-09-17 11:42:09 +02004615LY_ERR
Michal Vasko7fbc8162018-09-17 10:35:16 +02004616yang_parse(struct ly_ctx *ctx, const char *data, struct lysp_module **mod_p)
4617{
4618 LY_ERR ret = 0;
4619 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004620 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004621 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004622 struct lysp_module *mod = NULL;
Radek Krejci86d106e2018-10-18 09:53:19 +02004623 struct ly_parser_ctx context = {0};
Michal Vasko7fbc8162018-09-17 10:35:16 +02004624
Radek Krejci44ceedc2018-10-02 15:54:31 +02004625 context.ctx = ctx;
4626 context.line = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004627
4628 /* "module"/"submodule" */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004629 ret = get_keyword(&context, &data, &kw, &word, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004630 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004631
4632 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004633 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004634 ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004635 goto error;
4636 }
4637
4638 mod = calloc(1, sizeof *mod);
4639 LY_CHECK_ERR_GOTO(!mod, LOGMEM(ctx), error);
4640 if (kw == YANG_SUBMODULE) {
4641 mod->submodule = 1;
4642 }
Radek Krejci9fcacc12018-10-11 15:59:11 +02004643 mod->ctx = ctx;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004644
4645 /* substatements */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004646 ret = parse_sub_module(&context, &data, mod);
Radek Krejcic59bc972018-09-17 16:13:06 +02004647 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004648
4649 /* read some trailing spaces or new lines */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004650 ret = get_argument(&context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004651 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004652
4653 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004654 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004655 word_len, word);
4656 free(buf);
4657 goto error;
4658 }
4659 assert(!buf);
4660
4661 *mod_p = mod;
4662 return ret;
4663
4664error:
Radek Krejci9fcacc12018-10-11 15:59:11 +02004665 lysp_module_free(mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004666 return ret;
4667}