blob: ec5200a14aff9b8a0aa147365d2f842bf3a1d90b [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"
30
Radek Krejci44ceedc2018-10-02 15:54:31 +020031struct ly_parser_ctx {
32 struct ly_ctx *ctx;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020033 uint64_t line; /* line number */
34 uint64_t indent; /* current position on the line for indentation */
Radek Krejci44ceedc2018-10-02 15:54:31 +020035};
36
37/* Macro to check YANG's yang-char grammar rule */
38#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
39 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
40 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
41 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
42 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
43 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
44 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
45 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
46 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
47 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
48
49/* These 2 macros checks YANG's identifier grammar rule */
50#define is_yangidentstartchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
51#define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
52 c == '_' || c == '-' || c == '.')
53
54#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);} \
55 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
56
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020057#define MOVE_INPUT(CTX, DATA, COUNT) (*(data))+=COUNT;(CTX)->indent+=COUNT
58
Radek Krejci44ceedc2018-10-02 15:54:31 +020059#define LOGVAL_YANG(CTX, ...) LOGVAL((CTX)->ctx, LY_VLOG_LINE, &(CTX)->line, __VA_ARGS__)
60
Michal Vaskoea5abea2018-09-18 13:10:54 +020061/**
62 * @brief Loop through all substatements providing, return if there are none.
63 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020064 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020065 * @param[in] DATA Raw data to read from.
66 * @param[out] KW YANG keyword read.
67 * @param[out] WORD Pointer to the keyword itself.
68 * @param[out] WORD_LEN Length of the keyword.
69 * @param[out] ERR Variable for error storing.
70 *
71 * @return In case there are no substatements or a fatal error encountered.
72 */
Michal Vasko7fbc8162018-09-17 10:35:16 +020073#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR) \
74 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
Radek Krejcic59bc972018-09-17 16:13:06 +020075 LY_CHECK_RET(ERR); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020076 \
77 if (KW == YANG_SEMICOLON) { \
78 return ERR; \
79 } \
80 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020081 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020082 return LY_EVALID; \
83 } \
84 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
85 !ERR && (KW != YANG_RIGHT_BRACE); \
86 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
87
Radek Krejci44ceedc2018-10-02 15:54:31 +020088static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
89static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
90static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
91static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
92static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
93static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +020094
Michal Vaskoea5abea2018-09-18 13:10:54 +020095/**
96 * @brief Add another character to dynamic buffer, a low-level function.
97 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020098 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +020099 *
Radek Krejci404251e2018-10-09 12:06:44 +0200100 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200101 * @param[in, out] input Input string to process.
102 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200103 * @param[in,out] buf Buffer to use, can be moved by realloc().
104 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200105 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200106 *
107 * @return LY_ERR values.
108 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200109static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200110buf_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 +0200111{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200112 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200113 *buf_len += 16;
114 *buf = ly_realloc(*buf, *buf_len);
115 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
116 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200117 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200118
Radek Krejci44ceedc2018-10-02 15:54:31 +0200119 (*buf_used) += len;
120 (*input) += len;
121
Michal Vasko7fbc8162018-09-17 10:35:16 +0200122 return LY_SUCCESS;
123}
124
Michal Vaskoea5abea2018-09-18 13:10:54 +0200125/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200126 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200127 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200128 * @param[in] ctx yang parser context for logging.
129 * @param[in] c UTF8 code point of a character to check.
130 * @return LY_ERR values.
131 */
132static LY_ERR
133check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
134{
135 if (!is_yangutf8char(c)) {
136 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
137 return LY_EVALID;
138 }
139 return LY_SUCCESS;
140}
141
142/**
143 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
144 *
145 * @param[in] ctx yang parser context for logging.
146 * @param[in] c UTF8 code point of a character to check.
147 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
148 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers.
149 * If the identifier cannot be prefixed, NULL is expected.
150 * @return LY_ERR values.
151 */
152static LY_ERR
153check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
154{
155 if (first || (prefix && (*prefix) == 1)) {
156 if (!is_yangidentstartchar(c)) {
157 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
158 return LY_EVALID;
159 }
160 if (first) {
161 (*prefix) = 0;
162 } else {
163 (*prefix) = 2;
164 }
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;
656 /* slash: 0 - nothing, 1 - last character was '/' */
657 int slash = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200658 unsigned int c;
659 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200660
661 if (word_p) {
662 *word_p = NULL;
663 *word_len = 0;
664 }
665
666 /* first skip "optsep", comments */
667 while (**data) {
668 if (slash) {
669 if (**data == '/') {
670 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200671 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200672 ret = skip_comment(ctx, data, 1);
673 if (ret) {
674 return ret;
675 }
676 } else if (**data == '*') {
677 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200678 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200679 ret = skip_comment(ctx, data, 2);
680 if (ret) {
681 return ret;
682 }
683 } else {
684 /* not a comment after all */
685 goto keyword_start;
686 }
687 slash = 0;
688 }
689
690 switch (**data) {
691 case '/':
692 slash = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200693 ++ctx->indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200694 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200695 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200696 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200697 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200698 ctx->indent = 0;
699 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200700 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200701 /* skip whitespaces (optsep) */
702 ++ctx->indent;
703 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200704 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200705 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200706 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200707 break;
708 default:
709 /* either a keyword start or an invalid character */
710 goto keyword_start;
711 }
712
713 ++(*data);
714 }
715
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200716#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
717#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
718#define IF_KW_PREFIX_END }
719
Michal Vasko7fbc8162018-09-17 10:35:16 +0200720keyword_start:
721 word_start = *data;
722 *kw = YANG_NONE;
723
724 /* read the keyword itself */
725 switch (**data) {
726 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200727 MOVE_INPUT(ctx, data, 1);
728 IF_KW("rgument", 7, YANG_ARGUMENT)
729 else IF_KW("ugment", 6, YANG_AUGMENT)
730 else IF_KW("ction", 5, YANG_ACTION)
731 else IF_KW_PREFIX("ny", 2)
732 IF_KW("data", 4, YANG_ANYDATA)
733 else IF_KW("xml", 3, YANG_ANYXML)
734 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200735 break;
736 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200737 MOVE_INPUT(ctx, data, 1);
738 IF_KW("ase", 3, YANG_BASE)
739 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
740 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200741 break;
742 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200743 MOVE_INPUT(ctx, data, 1);
744 IF_KW("ase", 3, YANG_CASE)
745 else IF_KW("hoice", 5, YANG_CHOICE)
746 else IF_KW_PREFIX("on", 2)
747 IF_KW("fig", 3, YANG_CONFIG)
748 else IF_KW_PREFIX("ta", 2)
749 IF_KW("ct", 2, YANG_CONTACT)
750 else IF_KW("iner", 4, YANG_CONTAINER)
751 IF_KW_PREFIX_END
752 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200753 break;
754 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200755 MOVE_INPUT(ctx, data, 1);
756 IF_KW_PREFIX("e", 1)
757 IF_KW("fault", 5, YANG_DEFAULT)
758 else IF_KW("scription", 9, YANG_DESCRIPTION)
759 else IF_KW_PREFIX("viat", 4)
760 IF_KW("e", 1, YANG_DEVIATE)
761 else IF_KW("ion", 3, YANG_DEVIATION)
762 IF_KW_PREFIX_END
763 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200764 break;
765 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200766 MOVE_INPUT(ctx, data, 1);
767 IF_KW("num", 3, YANG_ENUM)
768 else IF_KW_PREFIX("rror-", 5)
769 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
770 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
771 IF_KW_PREFIX_END
772 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200773 break;
774 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200775 MOVE_INPUT(ctx, data, 1);
776 IF_KW("eature", 6, YANG_FEATURE)
777 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200778 break;
779 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200780 MOVE_INPUT(ctx, data, 1);
781 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200782 break;
783 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200784 MOVE_INPUT(ctx, data, 1);
785 IF_KW("dentity", 7, YANG_IDENTITY)
786 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
787 else IF_KW("mport", 5, YANG_IMPORT)
788 else IF_KW_PREFIX("n", 1)
789 IF_KW("clude", 5, YANG_INCLUDE)
790 else IF_KW("put", 3, YANG_INPUT)
791 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200792 break;
793 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200794 MOVE_INPUT(ctx, data, 1);
795 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200796 break;
797 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200798 MOVE_INPUT(ctx, data, 1);
799 IF_KW_PREFIX("e", 1)
800 IF_KW("af-list", 7, YANG_LEAF_LIST)
801 else IF_KW("af", 2, YANG_LEAF)
802 else IF_KW("ngth", 4, YANG_LENGTH)
803 IF_KW_PREFIX_END
804 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200805 break;
806 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200807 MOVE_INPUT(ctx, data, 1);
808 IF_KW_PREFIX("a", 1)
809 IF_KW("ndatory", 7, YANG_MANDATORY)
810 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
811 IF_KW_PREFIX_END
812 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
813 else IF_KW("ust", 3, YANG_MUST)
814 else IF_KW_PREFIX("od", 2)
815 IF_KW("ule", 3, YANG_MODULE)
816 else IF_KW("ifier", 5, YANG_MODIFIER)
817 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200818 break;
819 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200820 MOVE_INPUT(ctx, data, 1);
821 IF_KW("amespace", 8, YANG_NAMESPACE)
822 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200823 break;
824 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200825 MOVE_INPUT(ctx, data, 1);
826 IF_KW_PREFIX("r", 1)
827 IF_KW("dered-by", 8, YANG_ORDERED_BY)
828 else IF_KW("ganization", 10, YANG_ORGANIZATION)
829 IF_KW_PREFIX_END
830 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200831 break;
832 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200833 MOVE_INPUT(ctx, data, 1);
834 IF_KW("ath", 3, YANG_PATH)
835 else IF_KW("attern", 6, YANG_PATTERN)
836 else IF_KW("osition", 7, YANG_POSITION)
837 else IF_KW_PREFIX("re", 2)
838 IF_KW("fix", 3, YANG_PREFIX)
839 else IF_KW("sence", 5, YANG_PRESENCE)
840 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200841 break;
842 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200843 MOVE_INPUT(ctx, data, 1);
844 IF_KW("ange", 4, YANG_RANGE)
845 else IF_KW_PREFIX("e", 1)
846 IF_KW_PREFIX("f", 1)
847 IF_KW("erence", 6, YANG_REFERENCE)
848 else IF_KW("ine", 3, YANG_REFINE)
849 IF_KW_PREFIX_END
850 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
851 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
852 else IF_KW("vision", 6, YANG_REVISION)
853 IF_KW_PREFIX_END
854 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200855 break;
856 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200857 MOVE_INPUT(ctx, data, 1);
858 IF_KW("tatus", 5, YANG_STATUS)
859 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200860 break;
861 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200862 MOVE_INPUT(ctx, data, 1);
863 IF_KW("ypedef", 6, YANG_TYPEDEF)
864 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200865 break;
866 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200867 MOVE_INPUT(ctx, data, 1);
868 IF_KW_PREFIX("ni", 2)
869 IF_KW("que", 3, YANG_UNIQUE)
870 else IF_KW("ts", 2, YANG_UNITS)
871 IF_KW_PREFIX_END
872 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200873 break;
874 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200875 MOVE_INPUT(ctx, data, 1);
876 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200877 break;
878 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200879 MOVE_INPUT(ctx, data, 1);
880 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200881 break;
882 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200883 MOVE_INPUT(ctx, data, 1);
884 IF_KW("ang-version", 11, YANG_YANG_VERSION)
885 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200886 break;
887 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200888 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200889 *kw = YANG_SEMICOLON;
890 break;
891 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200892 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200893 *kw = YANG_LEFT_BRACE;
894 break;
895 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200896 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200897 *kw = YANG_RIGHT_BRACE;
898 break;
899 default:
900 break;
901 }
902
903 if (*kw != YANG_NONE) {
904 /* make sure we have the whole keyword */
905 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200906 case '\n':
907 ++ctx->line;
908 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200909 case ' ':
910 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200911 /* mandatory "sep" */
912 break;
913 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200914 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200915 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
916 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200917 return LY_EVALID;
918 }
919 } else {
920 /* still can be an extension */
921 prefix = 0;
922 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200923 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
924 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200925 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200926 /* check character validity */
927 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200928 }
929 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200930 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200931 return LY_EVALID;
932 }
933
934 /* prefix is mandatory for extension instances */
935 if (prefix != 1) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200936 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200937 return LY_EVALID;
938 }
939
940 *kw = YANG_CUSTOM;
941 }
942
943 if (word_p) {
944 *word_p = (char *)word_start;
945 *word_len = *data - word_start;
946 }
947
948 return LY_SUCCESS;
949}
950
Michal Vaskoea5abea2018-09-18 13:10:54 +0200951/**
952 * @brief Parse extension instance substatements.
953 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200954 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200955 * @param[in,out] data Data to read from, always moved to currently handled character.
956 * @param[in] word Extension instance substatement name (keyword).
957 * @param[in] word_len Extension instance substatement name length.
958 * @param[in,out] child Children of this extension instance to add to.
959 *
960 * @return LY_ERR values.
961 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200962static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200963parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200964 struct lysp_stmt **child)
965{
966 char *buf;
967 LY_ERR ret = 0;
968 enum yang_keyword kw;
969 struct lysp_stmt *stmt, *par_child;
970
971 stmt = calloc(1, sizeof *stmt);
972 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
973
Radek Krejci44ceedc2018-10-02 15:54:31 +0200974 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200975
976 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200977 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +0200978 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200979
Radek Krejci0ae092d2018-09-20 16:43:19 +0200980 if (word) {
981 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200982 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200983 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200984 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200985 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200986 }
987
988 /* insert into parent statements */
989 if (!*child) {
990 *child = stmt;
991 } else {
992 for (par_child = *child; par_child->next; par_child = par_child->next);
993 par_child->next = stmt;
994 }
995
996 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +0200997 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200998
999 ret = parse_ext_substmt(ctx, data, word, word_len, &stmt->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001000 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001001 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001002 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001003
1004 return ret;
1005}
1006
Michal Vaskoea5abea2018-09-18 13:10:54 +02001007/**
1008 * @brief Parse extension instance.
1009 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001010 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001011 * @param[in,out] data Data to read from, always moved to currently handled character.
1012 * @param[in] ext_name Extension instance substatement name (keyword).
1013 * @param[in] ext_name_len Extension instance substatement name length.
1014 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1015 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1016 * @param[in,out] exts Extension instances to add to.
1017 *
1018 * @return LY_ERR values.
1019 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001020static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001021parse_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 +02001022 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1023{
1024 LY_ERR ret = 0;
1025 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001026 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001027 struct lysp_ext_instance *e;
1028 enum yang_keyword kw;
1029
1030 LYSP_ARRAY_NEW_RET(ctx, exts, e, LY_EMEM);
1031
1032 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001033 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001034 e->insubstmt = insubstmt;
1035 e->insubstmt_index = insubstmt_index;
1036
1037 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001038 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001039 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001040
Radek Krejci0ae092d2018-09-20 16:43:19 +02001041 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001042 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001043 }
1044
1045 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001046 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001047
1048 ret = parse_ext_substmt(ctx, data, word, word_len, &e->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001049 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001050 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001051 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001052
1053 return ret;
1054}
1055
Michal Vaskoea5abea2018-09-18 13:10:54 +02001056/**
1057 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1058 * description, etc...
1059 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001060 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001061 * @param[in,out] data Data to read from, always moved to currently handled character.
1062 * @param[in] substmt Type of this substatement.
1063 * @param[in] substmt_index Index of this substatement.
1064 * @param[in,out] value Place to store the parsed value.
1065 * @param[in] arg Type of the YANG keyword argument (of the value).
1066 * @param[in,out] exts Extension instances to add to.
1067 *
1068 * @return LY_ERR values.
1069 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001070static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001071parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001072 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1073{
1074 LY_ERR ret = 0;
1075 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001076 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001077 enum yang_keyword kw;
1078
1079 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001080 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001081 return LY_EVALID;
1082 }
1083
1084 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001085 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001086 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001087
1088 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001089 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001090
1091 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001092 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001093
1094 switch (kw) {
1095 case YANG_CUSTOM:
1096 ret = parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001097 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001098 break;
1099 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001100 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001101 return LY_EVALID;
1102 }
1103 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001104 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001105
1106 return ret;
1107}
1108
Michal Vaskoea5abea2018-09-18 13:10:54 +02001109/**
1110 * @brief Parse the yang-version statement.
1111 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001112 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001113 * @param[in,out] data Data to read from, always moved to currently handled character.
1114 * @param[in] mod Module to store the parsed information in.
1115 *
1116 * @return LY_ERR values.
1117 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001118static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001119parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001120{
1121 LY_ERR ret = 0;
1122 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001123 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001124 enum yang_keyword kw;
1125
1126 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001127 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001128 return LY_EVALID;
1129 }
1130
1131 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001132 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001133 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001134
1135 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1136 mod->version = LYS_VERSION_1_0;
1137 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1138 mod->version = LYS_VERSION_1_1;
1139 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001140 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001141 free(buf);
1142 return LY_EVALID;
1143 }
1144 free(buf);
1145
1146 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001147 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001148
1149 switch (kw) {
1150 case YANG_CUSTOM:
1151 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001152 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001153 break;
1154 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001155 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001156 return LY_EVALID;
1157 }
1158 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001159 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001160
1161 return ret;
1162}
1163
Michal Vaskoea5abea2018-09-18 13:10:54 +02001164/**
1165 * @brief Parse the belongs-to statement.
1166 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001167 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001168 * @param[in,out] data Data to read from, always moved to currently handled character.
1169 * @param[in,out] belongsto Place to store the parsed value.
1170 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1171 * @param[in,out] exts Extension instances to add to.
1172 *
1173 * @return LY_ERR values.
1174 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001176parse_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 +02001177{
1178 LY_ERR ret = 0;
1179 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001180 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001181 enum yang_keyword kw;
1182
1183 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001184 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001185 return LY_EVALID;
1186 }
1187
1188 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001189 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001190 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001191
Radek Krejci44ceedc2018-10-02 15:54:31 +02001192 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001193 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001194 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001195
1196 switch (kw) {
1197 case YANG_PREFIX:
1198 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts);
1199 break;
1200 case YANG_CUSTOM:
1201 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts);
1202 break;
1203 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001204 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001205 return LY_EVALID;
1206 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001207 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001208 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001209 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001210
1211 /* mandatory substatements */
1212 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001213 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001214 return LY_EVALID;
1215 }
1216
1217 return ret;
1218}
1219
Michal Vaskoea5abea2018-09-18 13:10:54 +02001220/**
1221 * @brief Parse the revision-date statement.
1222 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001223 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001224 * @param[in,out] data Data to read from, always moved to currently handled character.
1225 * @param[in,out] rev Array to store the parsed value in.
1226 * @param[in,out] exts Extension instances to add to.
1227 *
1228 * @return LY_ERR values.
1229 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001230static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001231parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001232{
1233 LY_ERR ret = 0;
1234 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001235 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001236 enum yang_keyword kw;
1237
1238 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001239 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001240 return LY_EVALID;
1241 }
1242
1243 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001244 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001245 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001246
1247 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001248 if (lysp_check_date(ctx->ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001249 free(buf);
1250 return LY_EVALID;
1251 }
1252
1253 /* store value and spend buf if allocated */
1254 strncpy(rev, word, word_len);
1255 free(buf);
1256
1257 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001258 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001259
1260 switch (kw) {
1261 case YANG_CUSTOM:
1262 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001263 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001264 break;
1265 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001266 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001267 return LY_EVALID;
1268 }
1269 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001270 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001271
1272 return ret;
1273}
1274
Michal Vaskoea5abea2018-09-18 13:10:54 +02001275/**
1276 * @brief Parse the include statement.
1277 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001278 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001279 * @param[in,out] data Data to read from, always moved to currently handled character.
1280 * @param[in,out] includes Parsed includes to add to.
1281 *
1282 * @return LY_ERR values.
1283 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001284static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001285parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001286{
1287 LY_ERR ret = 0;
1288 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001289 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001290 enum yang_keyword kw;
1291 struct lysp_include *inc;
1292
1293 LYSP_ARRAY_NEW_RET(ctx, includes, inc, LY_EMEM);
1294
1295 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001296 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001297 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001298
Radek Krejci44ceedc2018-10-02 15:54:31 +02001299 INSERT_WORD(ctx, buf, inc->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001300 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001301 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001302
1303 switch (kw) {
1304 case YANG_DESCRIPTION:
1305 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts);
1306 break;
1307 case YANG_REFERENCE:
1308 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts);
1309 break;
1310 case YANG_REVISION_DATE:
1311 ret = parse_revisiondate(ctx, data, inc->rev, &inc->exts);
1312 break;
1313 case YANG_CUSTOM:
1314 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts);
1315 break;
1316 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001317 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001318 return LY_EVALID;
1319 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001320 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001321 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001322 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001323
1324 return ret;
1325}
1326
Michal Vaskoea5abea2018-09-18 13:10:54 +02001327/**
1328 * @brief Parse the import statement.
1329 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001330 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001331 * @param[in,out] data Data to read from, always moved to currently handled character.
1332 * @param[in,out] imports Parsed imports to add to.
1333 *
1334 * @return LY_ERR values.
1335 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001336static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001337parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001338{
1339 LY_ERR ret = 0;
1340 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001341 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001342 enum yang_keyword kw;
1343 struct lysp_import *imp;
1344
1345 LYSP_ARRAY_NEW_RET(ctx, imports, imp, LY_EVALID);
1346
1347 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001348 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001349 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001350
Radek Krejci44ceedc2018-10-02 15:54:31 +02001351 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001352 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001353 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001354
1355 switch (kw) {
1356 case YANG_PREFIX:
1357 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts);
1358 break;
1359 case YANG_DESCRIPTION:
1360 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts);
1361 break;
1362 case YANG_REFERENCE:
1363 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts);
1364 break;
1365 case YANG_REVISION_DATE:
1366 ret = parse_revisiondate(ctx, data, imp->rev, &imp->exts);
1367 break;
1368 case YANG_CUSTOM:
1369 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts);
1370 break;
1371 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001372 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001373 return LY_EVALID;
1374 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001375 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001376 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001377 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001378
1379 /* mandatory substatements */
1380 if (!imp->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001381 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001382 return LY_EVALID;
1383 }
1384
1385 return ret;
1386}
1387
Michal Vaskoea5abea2018-09-18 13:10:54 +02001388/**
1389 * @brief Parse the revision statement.
1390 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001391 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001392 * @param[in,out] data Data to read from, always moved to currently handled character.
1393 * @param[in,out] revs Parsed revisions to add to.
1394 *
1395 * @return LY_ERR values.
1396 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001397static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001398parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001399{
1400 LY_ERR ret = 0;
1401 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001402 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001403 enum yang_keyword kw;
1404 struct lysp_revision *rev;
1405
1406 LYSP_ARRAY_NEW_RET(ctx, revs, rev, LY_EMEM);
1407
1408 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001409 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001410 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001411
1412 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001413 if (lysp_check_date(ctx->ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001414 return LY_EVALID;
1415 }
1416
1417 strncpy(rev->rev, word, word_len);
1418 free(buf);
1419
1420 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001421 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001422
1423 switch (kw) {
1424 case YANG_DESCRIPTION:
1425 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts);
1426 break;
1427 case YANG_REFERENCE:
1428 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts);
1429 break;
1430 case YANG_CUSTOM:
1431 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts);
1432 break;
1433 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001434 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001435 return LY_EVALID;
1436 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001437 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001439 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001440
1441 return ret;
1442}
1443
Michal Vaskoea5abea2018-09-18 13:10:54 +02001444/**
1445 * @brief Parse a generic text field that can have more instances such as base.
1446 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001447 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001448 * @param[in,out] data Data to read from, always moved to currently handled character.
1449 * @param[in] substmt Type of this substatement.
1450 * @param[in,out] texts Parsed values to add to.
1451 * @param[in] arg Type of the expected argument.
1452 * @param[in,out] exts Extension instances to add to.
1453 *
1454 * @return LY_ERR values.
1455 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001456static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001457parse_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 +02001458 struct lysp_ext_instance **exts)
1459{
1460 LY_ERR ret = 0;
1461 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001462 size_t count, word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001463 enum yang_keyword kw;
1464
1465 /* allocate new pointer */
1466 for (count = 1; (*texts) && (*texts)[count - 1]; ++count);
1467 *texts = realloc(*texts, count * sizeof **texts);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001468 LY_CHECK_ERR_RET(!*texts, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001469
1470 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001471 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001472 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001473
Radek Krejci44ceedc2018-10-02 15:54:31 +02001474 INSERT_WORD(ctx, buf, (*texts)[count - 1], word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001475 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001476 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001477
1478 switch (kw) {
1479 case YANG_CUSTOM:
1480 ret = parse_ext(ctx, data, word, word_len, substmt, count - 1, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001481 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001482 break;
1483 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001484 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001485 return LY_EVALID;
1486 }
1487 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001488 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001489
1490 return ret;
1491}
1492
Michal Vaskoea5abea2018-09-18 13:10:54 +02001493/**
1494 * @brief Parse the config statement.
1495 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001496 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001497 * @param[in,out] data Data to read from, always moved to currently handled character.
1498 * @param[in,out] flags Flags to add to.
1499 * @param[in,out] exts Extension instances to add to.
1500 *
1501 * @return LY_ERR values.
1502 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001503static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001504parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001505{
1506 LY_ERR ret = 0;
1507 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001508 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001509 enum yang_keyword kw;
1510
1511 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001512 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001513 return LY_EVALID;
1514 }
1515
1516 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001517 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001518 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001519
1520 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1521 *flags |= LYS_CONFIG_W;
1522 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1523 *flags |= LYS_CONFIG_R;
1524 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001525 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001526 free(buf);
1527 return LY_EVALID;
1528 }
1529 free(buf);
1530
1531 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001532 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001533
1534 switch (kw) {
1535 case YANG_CUSTOM:
1536 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001537 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001538 break;
1539 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001540 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001541 return LY_EVALID;
1542 }
1543 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001544 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001545
1546 return ret;
1547}
1548
Michal Vaskoea5abea2018-09-18 13:10:54 +02001549/**
1550 * @brief Parse the mandatory statement.
1551 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001552 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001553 * @param[in,out] data Data to read from, always moved to currently handled character.
1554 * @param[in,out] flags Flags to add to.
1555 * @param[in,out] exts Extension instances to add to.
1556 *
1557 * @return LY_ERR values.
1558 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001559static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001560parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001561{
1562 LY_ERR ret = 0;
1563 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001564 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001565 enum yang_keyword kw;
1566
1567 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001568 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001569 return LY_EVALID;
1570 }
1571
1572 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001573 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001574 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001575
1576 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1577 *flags |= LYS_MAND_TRUE;
1578 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1579 *flags |= LYS_MAND_FALSE;
1580 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001581 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001582 free(buf);
1583 return LY_EVALID;
1584 }
1585 free(buf);
1586
1587 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001588 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001589
1590 switch (kw) {
1591 case YANG_CUSTOM:
1592 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001593 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001594 break;
1595 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001596 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001597 return LY_EVALID;
1598 }
1599 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001600 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001601
1602 return ret;
1603}
1604
Michal Vaskoea5abea2018-09-18 13:10:54 +02001605/**
1606 * @brief Parse a restriction such as range or length.
1607 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001608 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001609 * @param[in,out] data Data to read from, always moved to currently handled character.
1610 * @param[in] restr_kw Type of this particular restriction.
1611 * @param[in,out] exts Extension instances to add to.
1612 *
1613 * @return LY_ERR values.
1614 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001615static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001616parse_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 +02001617{
1618 LY_ERR ret = 0;
1619 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001620 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001621 enum yang_keyword kw;
1622
1623 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001624 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001625 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001626
Radek Krejci44ceedc2018-10-02 15:54:31 +02001627 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001628 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001629 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001630
1631 switch (kw) {
1632 case YANG_DESCRIPTION:
1633 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
1634 break;
1635 case YANG_REFERENCE:
1636 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
1637 break;
1638 case YANG_ERROR_APP_TAG:
1639 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
1640 break;
1641 case YANG_ERROR_MESSAGE:
1642 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
1643 break;
1644 case YANG_CUSTOM:
1645 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
1646 break;
1647 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001648 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001649 return LY_EVALID;
1650 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001651 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001652 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001653 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001654
1655 return ret;
1656}
1657
Michal Vaskoea5abea2018-09-18 13:10:54 +02001658/**
1659 * @brief Parse a restriction that can have more instances such as must.
1660 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001661 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001662 * @param[in,out] data Data to read from, always moved to currently handled character.
1663 * @param[in] restr_kw Type of this particular restriction.
1664 * @param[in,out] restrs Restrictions to add to.
1665 *
1666 * @return LY_ERR values.
1667 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001668static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001669parse_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 +02001670{
1671 struct lysp_restr *restr;
1672
1673 LYSP_ARRAY_NEW_RET(ctx, restrs, restr, LY_EMEM);
1674
1675 return parse_restr(ctx, data, restr_kw, restr);
1676}
1677
Michal Vaskoea5abea2018-09-18 13:10:54 +02001678/**
1679 * @brief Parse the status statement.
1680 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001681 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001682 * @param[in,out] data Data to read from, always moved to currently handled character.
1683 * @param[in,out] flags Flags to add to.
1684 * @param[in,out] exts Extension instances to add to.
1685 *
1686 * @return LY_ERR values.
1687 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001688static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001689parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001690{
1691 LY_ERR ret = 0;
1692 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001693 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001694 enum yang_keyword kw;
1695
1696 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001697 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001698 return LY_EVALID;
1699 }
1700
1701 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001702 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001703 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001704
1705 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1706 *flags |= LYS_STATUS_CURR;
1707 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1708 *flags |= LYS_STATUS_DEPRC;
1709 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1710 *flags |= LYS_STATUS_OBSLT;
1711 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001712 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001713 free(buf);
1714 return LY_EVALID;
1715 }
1716 free(buf);
1717
1718 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001719 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001720
1721 switch (kw) {
1722 case YANG_CUSTOM:
1723 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001724 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001725 break;
1726 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001727 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001728 return LY_EVALID;
1729 }
1730 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001731 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001732
1733 return ret;
1734}
1735
Michal Vaskoea5abea2018-09-18 13:10:54 +02001736/**
1737 * @brief Parse the when statement.
1738 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001739 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001740 * @param[in,out] data Data to read from, always moved to currently handled character.
1741 * @param[in,out] when_p When pointer to parse to.
1742 *
1743 * @return LY_ERR values.
1744 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001745static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001746parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001747{
1748 LY_ERR ret = 0;
1749 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001750 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001751 enum yang_keyword kw;
1752 struct lysp_when *when;
1753
1754 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001755 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001756 return LY_EVALID;
1757 }
1758
1759 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001760 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001761 *when_p = when;
1762
1763 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001764 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001765 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001766
Radek Krejci44ceedc2018-10-02 15:54:31 +02001767 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001768 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001769 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001770
1771 switch (kw) {
1772 case YANG_DESCRIPTION:
1773 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts);
1774 break;
1775 case YANG_REFERENCE:
1776 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts);
1777 break;
1778 case YANG_CUSTOM:
1779 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts);
1780 break;
1781 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001782 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001783 return LY_EVALID;
1784 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001785 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001786 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001787 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001788
1789 return ret;
1790}
1791
Michal Vaskoea5abea2018-09-18 13:10:54 +02001792/**
1793 * @brief Parse the anydata or anyxml statement.
1794 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001795 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001796 * @param[in,out] data Data to read from, always moved to currently handled character.
1797 * @param[in] kw Type of this particular keyword.
1798 * @param[in,out] siblings Siblings to add to.
1799 *
1800 * @return LY_ERR values.
1801 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001802static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001803parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001804{
1805 LY_ERR ret = 0;
1806 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001807 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001808 struct lysp_node *iter;
1809 struct lysp_node_anydata *any;
1810
1811 /* create structure */
1812 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001813 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001814 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
1815
1816 /* insert into siblings */
1817 if (!*siblings) {
1818 *siblings = (struct lysp_node *)any;
1819 } else {
1820 for (iter = *siblings; iter->next; iter = iter->next);
1821 iter->next = (struct lysp_node *)any;
1822 }
1823
1824 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001825 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001826 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001827
Radek Krejci44ceedc2018-10-02 15:54:31 +02001828 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001829
1830 /* parse substatements */
1831 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001832 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833
1834 switch (kw) {
1835 case YANG_CONFIG:
1836 ret = parse_config(ctx, data, &any->flags, &any->exts);
1837 break;
1838 case YANG_DESCRIPTION:
1839 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts);
1840 break;
1841 case YANG_IF_FEATURE:
1842 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts);
1843 break;
1844 case YANG_MANDATORY:
1845 ret = parse_mandatory(ctx, data, &any->flags, &any->exts);
1846 break;
1847 case YANG_MUST:
1848 ret = parse_restrs(ctx, data, kw, &any->musts);
1849 break;
1850 case YANG_REFERENCE:
1851 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts);
1852 break;
1853 case YANG_STATUS:
1854 ret = parse_status(ctx, data, &any->flags, &any->exts);
1855 break;
1856 case YANG_WHEN:
1857 ret = parse_when(ctx, data, &any->when);
1858 break;
1859 case YANG_CUSTOM:
1860 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts);
1861 break;
1862 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001863 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001864 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001865 return LY_EVALID;
1866 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001867 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001868 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001869 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001870
1871 return ret;
1872}
1873
Michal Vaskoea5abea2018-09-18 13:10:54 +02001874/**
1875 * @brief Parse the value or position statement. Substatement of type enum statement.
1876 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001877 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001878 * @param[in,out] data Data to read from, always moved to currently handled character.
1879 * @param[in] val_kw Type of this particular keyword.
1880 * @param[in,out] value Value to write to.
1881 * @param[in,out] flags Flags to write to.
1882 * @param[in,out] exts Extension instances to add to.
1883 *
1884 * @return LY_ERR values.
1885 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001886static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001887parse_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 +02001888 struct lysp_ext_instance **exts)
1889{
1890 LY_ERR ret = 0;
1891 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001892 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001893 long int num;
1894 unsigned long int unum;
1895 enum yang_keyword kw;
1896
1897 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001898 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001899 return LY_EVALID;
1900 }
1901 *flags |= LYS_SET_VALUE;
1902
1903 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001904 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001905 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001906
1907 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 +02001908 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001909 free(buf);
1910 return LY_EVALID;
1911 }
1912
1913 errno = 0;
1914 if (val_kw == YANG_VALUE) {
1915 num = strtol(word, &ptr, 10);
1916 } else {
1917 unum = strtoul(word, &ptr, 10);
1918 }
1919 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001920 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001921 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001922 free(buf);
1923 return LY_EVALID;
1924 }
1925 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001926 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001927 free(buf);
1928 return LY_EVALID;
1929 }
1930 if (val_kw == YANG_VALUE) {
1931 *value = num;
1932 } else {
1933 *value = unum;
1934 }
1935 free(buf);
1936
1937 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001938 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001939
1940 switch (kw) {
1941 case YANG_CUSTOM:
1942 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 +02001943 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001944 break;
1945 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001946 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001947 return LY_EVALID;
1948 }
1949 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001950 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001951
1952 return ret;
1953}
1954
Michal Vaskoea5abea2018-09-18 13:10:54 +02001955/**
1956 * @brief Parse the enum or bit statement. Substatement of type statement.
1957 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001958 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001959 * @param[in,out] data Data to read from, always moved to currently handled character.
1960 * @param[in] enum_kw Type of this particular keyword.
1961 * @param[in,out] enums Enums or bits to add to.
1962 *
1963 * @return LY_ERR values.
1964 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001965static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001966parse_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 +02001967{
1968 LY_ERR ret = 0;
1969 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001970 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001971 enum yang_keyword kw;
1972 struct lysp_type_enum *enm;
1973
1974 LYSP_ARRAY_NEW_RET(ctx, enums, enm, LY_EMEM);
1975
1976 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001977 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001978 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001979
Radek Krejci44ceedc2018-10-02 15:54:31 +02001980 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001981 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001982 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001983
1984 switch (kw) {
1985 case YANG_DESCRIPTION:
1986 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts);
1987 break;
1988 case YANG_IF_FEATURE:
1989 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts);
1990 break;
1991 case YANG_REFERENCE:
1992 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts);
1993 break;
1994 case YANG_STATUS:
1995 ret = parse_status(ctx, data, &enm->flags, &enm->exts);
1996 break;
1997 case YANG_VALUE:
1998 case YANG_POSITION:
1999 ret = parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts);
2000 break;
2001 case YANG_CUSTOM:
2002 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts);
2003 break;
2004 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002005 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002006 return LY_EVALID;
2007 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002008 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002009 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002010 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002011
2012 return ret;
2013}
2014
Michal Vaskoea5abea2018-09-18 13:10:54 +02002015/**
2016 * @brief Parse the fraction-digits statement. Substatement of type statement.
2017 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002018 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002019 * @param[in,out] data Data to read from, always moved to currently handled character.
2020 * @param[in,out] fracdig Value to write to.
2021 * @param[in,out] exts Extension instances to add to.
2022 *
2023 * @return LY_ERR values.
2024 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002025static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002026parse_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 +02002027{
2028 LY_ERR ret = 0;
2029 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002030 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002031 unsigned long int num;
2032 enum yang_keyword kw;
2033
2034 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002035 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002036 return LY_EVALID;
2037 }
2038
2039 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002040 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002041 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002042
2043 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002044 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002045 free(buf);
2046 return LY_EVALID;
2047 }
2048
2049 errno = 0;
2050 num = strtoul(word, &ptr, 10);
2051 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002052 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002053 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002054 free(buf);
2055 return LY_EVALID;
2056 }
2057 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002058 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002059 free(buf);
2060 return LY_EVALID;
2061 }
2062 *fracdig = num;
2063 free(buf);
2064
2065 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002066 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002067
2068 switch (kw) {
2069 case YANG_CUSTOM:
2070 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002071 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002072 break;
2073 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002074 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075 return LY_EVALID;
2076 }
2077 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002078 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002079
2080 return ret;
2081}
2082
Michal Vaskoea5abea2018-09-18 13:10:54 +02002083/**
2084 * @brief Parse the require-instance statement. Substatement of type statement.
2085 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002086 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002087 * @param[in,out] data Data to read from, always moved to currently handled character.
2088 * @param[in,out] reqinst Value to write to.
2089 * @param[in,out] flags Flags to write to.
2090 * @param[in,out] exts Extension instances to add to.
2091 *
2092 * @return LY_ERR values.
2093 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002094static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002095parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002096 struct lysp_ext_instance **exts)
2097{
2098 LY_ERR ret = 0;
2099 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002100 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002101 enum yang_keyword kw;
2102
2103 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002104 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002105 return LY_EVALID;
2106 }
2107 *flags |= LYS_SET_REQINST;
2108
2109 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002110 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002111 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002112
2113 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2114 *reqinst = 1;
2115 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002116 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002117 free(buf);
2118 return LY_EVALID;
2119 }
2120 free(buf);
2121
2122 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002123 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002124
2125 switch (kw) {
2126 case YANG_CUSTOM:
2127 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002128 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002129 break;
2130 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002131 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002132 return LY_EVALID;
2133 }
2134 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002135 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002136
2137 return ret;
2138}
2139
Michal Vaskoea5abea2018-09-18 13:10:54 +02002140/**
2141 * @brief Parse the modifier statement. Substatement of type pattern statement.
2142 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002143 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002144 * @param[in,out] data Data to read from, always moved to currently handled character.
2145 * @param[in,out] pat Value to write to.
2146 * @param[in,out] exts Extension instances to add to.
2147 *
2148 * @return LY_ERR values.
2149 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002150static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002151parse_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 +02002152{
2153 LY_ERR ret = 0;
2154 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002155 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002156 enum yang_keyword kw;
2157
2158 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002159 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002160 return LY_EVALID;
2161 }
2162
2163 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002164 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002165 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002166
2167 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002168 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002169 free(buf);
2170 return LY_EVALID;
2171 }
2172 free(buf);
2173
2174 /* replace the value in the dictionary */
2175 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002176 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002177 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002178 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002179
2180 assert(buf[0] == 0x06);
2181 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002182 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002183
2184 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002185 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002186
2187 switch (kw) {
2188 case YANG_CUSTOM:
2189 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002190 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002191 break;
2192 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002193 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002194 return LY_EVALID;
2195 }
2196 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002197 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002198
2199 return ret;
2200}
2201
Michal Vaskoea5abea2018-09-18 13:10:54 +02002202/**
2203 * @brief Parse the pattern statement. Substatement of type statement.
2204 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002205 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002206 * @param[in,out] data Data to read from, always moved to currently handled character.
2207 * @param[in,out] patterns Restrictions to add to.
2208 *
2209 * @return LY_ERR values.
2210 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002211static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002212parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002213{
2214 LY_ERR ret = 0;
2215 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002216 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002217 enum yang_keyword kw;
2218 struct lysp_restr *restr;
2219
2220 LYSP_ARRAY_NEW_RET(ctx, patterns, restr, LY_EMEM);
2221
2222 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002223 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002224 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002225
2226 /* add special meaning first byte */
2227 if (buf) {
2228 buf = realloc(buf, word_len + 2);
2229 word = buf;
2230 } else {
2231 buf = malloc(word_len + 2);
2232 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002233 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002234 memmove(buf + 1, word, word_len + 1);
2235 word[0] = 0x06;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002236 restr->arg = lydict_insert_zc(ctx->ctx, word);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002237
2238 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002239 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002240
2241 switch (kw) {
2242 case YANG_DESCRIPTION:
2243 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
2244 break;
2245 case YANG_REFERENCE:
2246 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
2247 break;
2248 case YANG_ERROR_APP_TAG:
2249 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
2250 break;
2251 case YANG_ERROR_MESSAGE:
2252 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
2253 break;
2254 case YANG_MODIFIER:
2255 ret = parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts);
2256 break;
2257 case YANG_CUSTOM:
2258 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
2259 break;
2260 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002261 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002262 return LY_EVALID;
2263 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002264 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002266 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002267
2268 return ret;
2269}
2270
Michal Vaskoea5abea2018-09-18 13:10:54 +02002271/**
2272 * @brief Parse the type statement.
2273 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002274 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002275 * @param[in,out] data Data to read from, always moved to currently handled character.
2276 * @param[in,out] type Type to wrote to.
2277 *
2278 * @return LY_ERR values.
2279 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002280static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002281parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002282{
2283 LY_ERR ret = 0;
2284 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002285 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002286 enum yang_keyword kw;
2287 struct lysp_type *nest_type;
2288
2289 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002290 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002291 return LY_EVALID;
2292 }
2293
2294 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002295 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002296 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002297
Radek Krejci44ceedc2018-10-02 15:54:31 +02002298 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002299 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002300 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002301
2302 switch (kw) {
2303 case YANG_BASE:
2304 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts);
2305 break;
2306 case YANG_BIT:
2307 ret = parse_type_enum(ctx, data, kw, &type->bits);
2308 break;
2309 case YANG_ENUM:
2310 ret = parse_type_enum(ctx, data, kw, &type->enums);
2311 break;
2312 case YANG_FRACTION_DIGITS:
2313 ret = parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts);
2314 break;
2315 case YANG_LENGTH:
2316 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002317 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002318 return LY_EVALID;
2319 }
2320 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002321 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002322
2323 ret = parse_restr(ctx, data, kw, type->length);
2324 break;
2325 case YANG_PATH:
2326 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts);
2327 break;
2328 case YANG_PATTERN:
2329 ret = parse_type_pattern(ctx, data, &type->patterns);
2330 break;
2331 case YANG_RANGE:
2332 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002333 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002334 return LY_EVALID;
2335 }
2336 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002337 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002338
2339 ret = parse_restr(ctx, data, kw, type->range);
2340 break;
2341 case YANG_REQUIRE_INSTANCE:
2342 ret = parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts);
2343 break;
2344 case YANG_TYPE:
2345 {
2346 LYSP_ARRAY_NEW_RET(ctx, &type->types, nest_type, LY_EMEM);
2347 }
2348 ret = parse_type(ctx, data, nest_type);
2349 break;
2350 case YANG_CUSTOM:
2351 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts);
2352 break;
2353 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002354 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002355 return LY_EVALID;
2356 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002357 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002358 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002359 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002360
2361 return ret;
2362}
2363
Michal Vaskoea5abea2018-09-18 13:10:54 +02002364/**
2365 * @brief Parse the leaf statement.
2366 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002367 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002368 * @param[in,out] data Data to read from, always moved to currently handled character.
2369 * @param[in,out] siblings Siblings to add to.
2370 *
2371 * @return LY_ERR values.
2372 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002373static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002374parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002375{
2376 LY_ERR ret = 0;
2377 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002378 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002379 enum yang_keyword kw;
2380 struct lysp_node *iter;
2381 struct lysp_node_leaf *leaf;
2382
2383 /* create structure */
2384 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002385 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002386 leaf->nodetype = LYS_LEAF;
2387
2388 /* insert into siblings */
2389 if (!*siblings) {
2390 *siblings = (struct lysp_node *)leaf;
2391 } else {
2392 for (iter = *siblings; iter->next; iter = iter->next);
2393 iter->next = (struct lysp_node *)leaf;
2394 }
2395
2396 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002397 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002398 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002399
Radek Krejci44ceedc2018-10-02 15:54:31 +02002400 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002401
2402 /* parse substatements */
2403 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002404 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002405
2406 switch (kw) {
2407 case YANG_CONFIG:
2408 ret = parse_config(ctx, data, &leaf->flags, &leaf->exts);
2409 break;
2410 case YANG_DEFAULT:
2411 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts);
2412 break;
2413 case YANG_DESCRIPTION:
2414 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts);
2415 break;
2416 case YANG_IF_FEATURE:
2417 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts);
2418 break;
2419 case YANG_MANDATORY:
2420 ret = parse_mandatory(ctx, data, &leaf->flags, &leaf->exts);
2421 break;
2422 case YANG_MUST:
2423 ret = parse_restrs(ctx, data, kw, &leaf->musts);
2424 break;
2425 case YANG_REFERENCE:
2426 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts);
2427 break;
2428 case YANG_STATUS:
2429 ret = parse_status(ctx, data, &leaf->flags, &leaf->exts);
2430 break;
2431 case YANG_TYPE:
2432 ret = parse_type(ctx, data, &leaf->type);
2433 break;
2434 case YANG_UNITS:
2435 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts);
2436 break;
2437 case YANG_WHEN:
2438 ret = parse_when(ctx, data, &leaf->when);
2439 break;
2440 case YANG_CUSTOM:
2441 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts);
2442 break;
2443 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002444 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002445 return LY_EVALID;
2446 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002447 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002448 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002449 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002450
2451 /* mandatory substatements */
2452 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002453 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002454 return LY_EVALID;
2455 }
2456
2457 return ret;
2458}
2459
Michal Vaskoea5abea2018-09-18 13:10:54 +02002460/**
2461 * @brief Parse the max-elements statement.
2462 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002463 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002464 * @param[in,out] data Data to read from, always moved to currently handled character.
2465 * @param[in,out] max Value to write to.
2466 * @param[in,out] flags Flags to write to.
2467 * @param[in,out] exts Extension instances to add to.
2468 *
2469 * @return LY_ERR values.
2470 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002471static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002472parse_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 +02002473{
2474 LY_ERR ret = 0;
2475 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002476 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002477 unsigned long int num;
2478 enum yang_keyword kw;
2479
2480 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002481 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002482 return LY_EVALID;
2483 }
2484 *flags |= LYS_SET_MAX;
2485
2486 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002487 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002488 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002489
2490 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002491 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002492 free(buf);
2493 return LY_EVALID;
2494 }
2495
2496 if (strncmp(word, "unbounded", word_len)) {
2497 errno = 0;
2498 num = strtoul(word, &ptr, 10);
2499 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002500 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002501 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002502 free(buf);
2503 return LY_EVALID;
2504 }
2505 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002506 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002507 free(buf);
2508 return LY_EVALID;
2509 }
2510
2511 *max = num;
2512 }
2513 free(buf);
2514
2515 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002516 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002517
2518 switch (kw) {
2519 case YANG_CUSTOM:
2520 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002521 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002522 break;
2523 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002524 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002525 return LY_EVALID;
2526 }
2527 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002528 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002529
2530 return ret;
2531}
2532
Michal Vaskoea5abea2018-09-18 13:10:54 +02002533/**
2534 * @brief Parse the min-elements statement.
2535 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002536 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002537 * @param[in,out] data Data to read from, always moved to currently handled character.
2538 * @param[in,out] min Value to write to.
2539 * @param[in,out] flags Flags to write to.
2540 * @param[in,out] exts Extension instances to add to.
2541 *
2542 * @return LY_ERR values.
2543 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002544static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002545parse_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 +02002546{
2547 LY_ERR ret = 0;
2548 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002549 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002550 unsigned long int num;
2551 enum yang_keyword kw;
2552
2553 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002554 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002555 return LY_EVALID;
2556 }
2557 *flags |= LYS_SET_MIN;
2558
2559 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002560 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002561 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002562
2563 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002564 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002565 free(buf);
2566 return LY_EVALID;
2567 }
2568
2569 errno = 0;
2570 num = strtoul(word, &ptr, 10);
2571 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002572 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002573 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002574 free(buf);
2575 return LY_EVALID;
2576 }
2577 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002578 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002579 free(buf);
2580 return LY_EVALID;
2581 }
2582 *min = num;
2583 free(buf);
2584
2585 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002586 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002587
2588 switch (kw) {
2589 case YANG_CUSTOM:
2590 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002591 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002592 break;
2593 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002594 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002595 return LY_EVALID;
2596 }
2597 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002598 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002599
2600 return ret;
2601}
2602
Michal Vaskoea5abea2018-09-18 13:10:54 +02002603/**
2604 * @brief Parse the ordered-by statement.
2605 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002606 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002607 * @param[in,out] data Data to read from, always moved to currently handled character.
2608 * @param[in,out] flags Flags to write to.
2609 * @param[in,out] exts Extension instances to add to.
2610 *
2611 * @return LY_ERR values.
2612 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002613static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002614parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002615{
2616 LY_ERR ret = 0;
2617 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002618 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619 enum yang_keyword kw;
2620
2621 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002622 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002623 return LY_EVALID;
2624 }
2625
2626 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002627 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002628 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002629
2630 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2631 *flags |= LYS_ORDBY_SYSTEM;
2632 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2633 *flags |= LYS_ORDBY_USER;
2634 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002635 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636 free(buf);
2637 return LY_EVALID;
2638 }
2639 free(buf);
2640
2641 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002642 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002643
2644 switch (kw) {
2645 case YANG_CUSTOM:
2646 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002647 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002648 break;
2649 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002650 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002651 return LY_EVALID;
2652 }
2653 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002654 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002655
2656 return ret;
2657}
2658
Michal Vaskoea5abea2018-09-18 13:10:54 +02002659/**
2660 * @brief Parse the leaf-list statement.
2661 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002662 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002663 * @param[in,out] data Data to read from, always moved to currently handled character.
2664 * @param[in,out] siblings Siblings to add to.
2665 *
2666 * @return LY_ERR values.
2667 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002668static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002669parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002670{
2671 LY_ERR ret = 0;
2672 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002673 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002674 enum yang_keyword kw;
2675 struct lysp_node *iter;
2676 struct lysp_node_leaflist *llist;
2677
2678 /* create structure */
2679 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002680 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002681 llist->nodetype = LYS_LEAFLIST;
2682
2683 /* insert into siblings */
2684 if (!*siblings) {
2685 *siblings = (struct lysp_node *)llist;
2686 } else {
2687 for (iter = *siblings; iter->next; iter = iter->next);
2688 iter->next = (struct lysp_node *)llist;
2689 }
2690
2691 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002692 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002693 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002694
Radek Krejci44ceedc2018-10-02 15:54:31 +02002695 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002696
2697 /* parse substatements */
2698 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002699 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002700
2701 switch (kw) {
2702 case YANG_CONFIG:
2703 ret = parse_config(ctx, data, &llist->flags, &llist->exts);
2704 break;
2705 case YANG_DEFAULT:
2706 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts);
2707 break;
2708 case YANG_DESCRIPTION:
2709 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts);
2710 break;
2711 case YANG_IF_FEATURE:
2712 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts);
2713 break;
2714 case YANG_MAX_ELEMENTS:
2715 ret = parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts);
2716 break;
2717 case YANG_MIN_ELEMENTS:
2718 ret = parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts);
2719 break;
2720 case YANG_MUST:
2721 ret = parse_restrs(ctx, data, kw, &llist->musts);
2722 break;
2723 case YANG_ORDERED_BY:
2724 ret = parse_orderedby(ctx, data, &llist->flags, &llist->exts);
2725 break;
2726 case YANG_REFERENCE:
2727 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts);
2728 break;
2729 case YANG_STATUS:
2730 ret = parse_status(ctx, data, &llist->flags, &llist->exts);
2731 break;
2732 case YANG_TYPE:
2733 ret = parse_type(ctx, data, &llist->type);
2734 break;
2735 case YANG_UNITS:
2736 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts);
2737 break;
2738 case YANG_WHEN:
2739 ret = parse_when(ctx, data, &llist->when);
2740 break;
2741 case YANG_CUSTOM:
2742 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts);
2743 break;
2744 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002745 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002746 return LY_EVALID;
2747 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002748 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002749 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002750 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002751
2752 /* mandatory substatements */
2753 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002754 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002755 return LY_EVALID;
2756 }
2757
2758 return ret;
2759}
2760
Michal Vaskoea5abea2018-09-18 13:10:54 +02002761/**
2762 * @brief Parse the refine statement.
2763 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002764 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002765 * @param[in,out] data Data to read from, always moved to currently handled character.
2766 * @param[in,out] refines Refines to add to.
2767 *
2768 * @return LY_ERR values.
2769 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002770static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002771parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002772{
2773 LY_ERR ret = 0;
2774 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002775 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002776 enum yang_keyword kw;
2777 struct lysp_refine *rf;
2778
2779 LYSP_ARRAY_NEW_RET(ctx, refines, rf, LY_EMEM);
2780
2781 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002782 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002783 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002784
Radek Krejci44ceedc2018-10-02 15:54:31 +02002785 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002786 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002787 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002788
2789 switch (kw) {
2790 case YANG_CONFIG:
2791 ret = parse_config(ctx, data, &rf->flags, &rf->exts);
2792 break;
2793 case YANG_DEFAULT:
2794 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts);
2795 break;
2796 case YANG_DESCRIPTION:
2797 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts);
2798 break;
2799 case YANG_IF_FEATURE:
2800 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts);
2801 break;
2802 case YANG_MAX_ELEMENTS:
2803 ret = parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts);
2804 break;
2805 case YANG_MIN_ELEMENTS:
2806 ret = parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts);
2807 break;
2808 case YANG_MUST:
2809 ret = parse_restrs(ctx, data, kw, &rf->musts);
2810 break;
2811 case YANG_MANDATORY:
2812 ret = parse_mandatory(ctx, data, &rf->flags, &rf->exts);
2813 break;
2814 case YANG_REFERENCE:
2815 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts);
2816 break;
2817 case YANG_PRESENCE:
2818 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts);
2819 break;
2820 case YANG_CUSTOM:
2821 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts);
2822 break;
2823 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002824 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002825 return LY_EVALID;
2826 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002827 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002828 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002829 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002830
2831 return ret;
2832}
2833
Michal Vaskoea5abea2018-09-18 13:10:54 +02002834/**
2835 * @brief Parse the typedef statement.
2836 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002837 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002838 * @param[in,out] data Data to read from, always moved to currently handled character.
2839 * @param[in,out] typedefs Typedefs to add to.
2840 *
2841 * @return LY_ERR values.
2842 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002843static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002844parse_typedef(struct ly_parser_ctx *ctx, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002845{
2846 LY_ERR ret = 0;
2847 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002848 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002849 enum yang_keyword kw;
2850 struct lysp_tpdf *tpdf;
2851
2852 LYSP_ARRAY_NEW_RET(ctx, typedefs, tpdf, LY_EMEM);
2853
2854 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002855 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002856 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857
Radek Krejci44ceedc2018-10-02 15:54:31 +02002858 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002859
2860 /* parse substatements */
2861 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002862 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863
2864 switch (kw) {
2865 case YANG_DEFAULT:
2866 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts);
2867 break;
2868 case YANG_DESCRIPTION:
2869 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts);
2870 break;
2871 case YANG_REFERENCE:
2872 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts);
2873 break;
2874 case YANG_STATUS:
2875 ret = parse_status(ctx, data, &tpdf->flags, &tpdf->exts);
2876 break;
2877 case YANG_TYPE:
2878 ret = parse_type(ctx, data, &tpdf->type);
2879 break;
2880 case YANG_UNITS:
2881 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts);
2882 break;
2883 case YANG_CUSTOM:
2884 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts);
2885 break;
2886 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002887 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002888 return LY_EVALID;
2889 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002890 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002892 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002893
2894 /* mandatory substatements */
2895 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002896 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002897 return LY_EVALID;
2898 }
2899
2900 return ret;
2901}
2902
Michal Vaskoea5abea2018-09-18 13:10:54 +02002903/**
2904 * @brief Parse the input or output statement.
2905 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002906 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002907 * @param[in,out] data Data to read from, always moved to currently handled character.
2908 * @param[in] kw Type of this particular keyword
2909 * @param[in,out] inout_p Input/output pointer to write to.
2910 *
2911 * @return LY_ERR values.
2912 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002913static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002914parse_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 +02002915{
2916 LY_ERR ret = 0;
2917 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002918 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002919 struct lysp_action_inout *inout;
2920
2921 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002922 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002923 return LY_EVALID;
2924 }
2925
2926 /* create structure */
2927 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002928 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002929 *inout_p = inout;
2930
2931 /* parse substatements */
2932 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002933 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002934
2935 switch (kw) {
2936 case YANG_ANYDATA:
2937 case YANG_ANYXML:
2938 ret = parse_any(ctx, data, kw, &inout->data);
2939 break;
2940 case YANG_CHOICE:
2941 ret = parse_choice(ctx, data, &inout->data);
2942 break;
2943 case YANG_CONTAINER:
2944 ret = parse_container(ctx, data, &inout->data);
2945 break;
2946 case YANG_LEAF:
2947 ret = parse_leaf(ctx, data, &inout->data);
2948 break;
2949 case YANG_LEAF_LIST:
2950 ret = parse_leaflist(ctx, data, &inout->data);
2951 break;
2952 case YANG_LIST:
2953 ret = parse_list(ctx, data, &inout->data);
2954 break;
2955 case YANG_USES:
2956 ret = parse_uses(ctx, data, &inout->data);
2957 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002958 case YANG_TYPEDEF:
2959 ret = parse_typedef(ctx, data, &inout->typedefs);
2960 break;
2961 case YANG_MUST:
2962 ret = parse_restrs(ctx, data, kw, &inout->musts);
2963 break;
2964 case YANG_GROUPING:
2965 ret = parse_grouping(ctx, data, &inout->groupings);
2966 break;
2967 case YANG_CUSTOM:
2968 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts);
2969 break;
2970 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002971 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002972 return LY_EVALID;
2973 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002974 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002976 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002977
2978 return ret;
2979}
2980
Michal Vaskoea5abea2018-09-18 13:10:54 +02002981/**
2982 * @brief Parse the action statement.
2983 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002984 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002985 * @param[in,out] data Data to read from, always moved to currently handled character.
2986 * @param[in,out] actions Actions to add to.
2987 *
2988 * @return LY_ERR values.
2989 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002990static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002991parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002992{
2993 LY_ERR ret = 0;
2994 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002995 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002996 enum yang_keyword kw;
2997 struct lysp_action *act;
2998
2999 LYSP_ARRAY_NEW_RET(ctx, actions, act, LY_EMEM);
3000
3001 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003002 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003003 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003004
Radek Krejci44ceedc2018-10-02 15:54:31 +02003005 INSERT_WORD(ctx, buf, act->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003006 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003007 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003008
3009 switch (kw) {
3010 case YANG_DESCRIPTION:
3011 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts);
3012 break;
3013 case YANG_IF_FEATURE:
3014 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts);
3015 break;
3016 case YANG_REFERENCE:
3017 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts);
3018 break;
3019 case YANG_STATUS:
3020 ret = parse_status(ctx, data, &act->flags, &act->exts);
3021 break;
3022
3023 case YANG_INPUT:
3024 ret = parse_inout(ctx, data, kw, &act->input);
3025 break;
3026 case YANG_OUTPUT:
3027 ret = parse_inout(ctx, data, kw, &act->output);
3028 break;
3029
3030 case YANG_TYPEDEF:
3031 ret = parse_typedef(ctx, data, &act->typedefs);
3032 break;
3033 case YANG_GROUPING:
3034 ret = parse_grouping(ctx, data, &act->groupings);
3035 break;
3036 case YANG_CUSTOM:
3037 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts);
3038 break;
3039 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003040 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003041 return LY_EVALID;
3042 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003043 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003044 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003045 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003046
3047 return ret;
3048}
3049
Michal Vaskoea5abea2018-09-18 13:10:54 +02003050/**
3051 * @brief Parse the notification statement.
3052 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003053 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003054 * @param[in,out] data Data to read from, always moved to currently handled character.
3055 * @param[in,out] notifs Notifications to add to.
3056 *
3057 * @return LY_ERR values.
3058 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003059static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003060parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003061{
3062 LY_ERR ret = 0;
3063 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003064 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003065 enum yang_keyword kw;
3066 struct lysp_notif *notif;
3067
3068 LYSP_ARRAY_NEW_RET(ctx, notifs, notif, LY_EMEM);
3069
3070 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003071 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003072 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003073
Radek Krejci44ceedc2018-10-02 15:54:31 +02003074 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003075 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003076 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003077
3078 switch (kw) {
3079 case YANG_DESCRIPTION:
3080 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts);
3081 break;
3082 case YANG_IF_FEATURE:
3083 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts);
3084 break;
3085 case YANG_REFERENCE:
3086 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts);
3087 break;
3088 case YANG_STATUS:
3089 ret = parse_status(ctx, data, &notif->flags, &notif->exts);
3090 break;
3091
3092 case YANG_ANYDATA:
3093 case YANG_ANYXML:
3094 ret = parse_any(ctx, data, kw, &notif->data);
3095 break;
3096 case YANG_CHOICE:
3097 ret = parse_case(ctx, data, &notif->data);
3098 break;
3099 case YANG_CONTAINER:
3100 ret = parse_container(ctx, data, &notif->data);
3101 break;
3102 case YANG_LEAF:
3103 ret = parse_leaf(ctx, data, &notif->data);
3104 break;
3105 case YANG_LEAF_LIST:
3106 ret = parse_leaflist(ctx, data, &notif->data);
3107 break;
3108 case YANG_LIST:
3109 ret = parse_list(ctx, data, &notif->data);
3110 break;
3111 case YANG_USES:
3112 ret = parse_uses(ctx, data, &notif->data);
3113 break;
3114
3115 case YANG_MUST:
3116 ret = parse_restrs(ctx, data, kw, &notif->musts);
3117 break;
3118 case YANG_TYPEDEF:
3119 ret = parse_typedef(ctx, data, &notif->typedefs);
3120 break;
3121 case YANG_GROUPING:
3122 ret = parse_grouping(ctx, data, &notif->groupings);
3123 break;
3124 case YANG_CUSTOM:
3125 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts);
3126 break;
3127 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003128 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003129 return LY_EVALID;
3130 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003131 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003132 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003133 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003134
3135 return ret;
3136}
3137
Michal Vaskoea5abea2018-09-18 13:10:54 +02003138/**
3139 * @brief Parse the grouping statement.
3140 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003141 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003142 * @param[in,out] data Data to read from, always moved to currently handled character.
3143 * @param[in,out] groupings Groupings to add to.
3144 *
3145 * @return LY_ERR values.
3146 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003147static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003148parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003149{
3150 LY_ERR ret = 0;
3151 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003152 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003153 enum yang_keyword kw;
3154 struct lysp_grp *grp;
3155
3156 LYSP_ARRAY_NEW_RET(ctx, groupings, grp, LY_EMEM);
3157
3158 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003159 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003160 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003161
Radek Krejci44ceedc2018-10-02 15:54:31 +02003162 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003163
3164 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003165 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003166
3167 switch (kw) {
3168 case YANG_DESCRIPTION:
3169 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts);
3170 break;
3171 case YANG_REFERENCE:
3172 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts);
3173 break;
3174 case YANG_STATUS:
3175 ret = parse_status(ctx, data, &grp->flags, &grp->exts);
3176 break;
3177
3178 case YANG_ANYDATA:
3179 case YANG_ANYXML:
3180 ret = parse_any(ctx, data, kw, &grp->data);
3181 break;
3182 case YANG_CHOICE:
3183 ret = parse_choice(ctx, data, &grp->data);
3184 break;
3185 case YANG_CONTAINER:
3186 ret = parse_container(ctx, data, &grp->data);
3187 break;
3188 case YANG_LEAF:
3189 ret = parse_leaf(ctx, data, &grp->data);
3190 break;
3191 case YANG_LEAF_LIST:
3192 ret = parse_leaflist(ctx, data, &grp->data);
3193 break;
3194 case YANG_LIST:
3195 ret = parse_list(ctx, data, &grp->data);
3196 break;
3197 case YANG_USES:
3198 ret = parse_uses(ctx, data, &grp->data);
3199 break;
3200
3201 case YANG_TYPEDEF:
3202 ret = parse_typedef(ctx, data, &grp->typedefs);
3203 break;
3204 case YANG_ACTION:
3205 ret = parse_action(ctx, data, &grp->actions);
3206 break;
3207 case YANG_GROUPING:
3208 ret = parse_grouping(ctx, data, &grp->groupings);
3209 break;
3210 case YANG_NOTIFICATION:
3211 ret = parse_notif(ctx, data, &grp->notifs);
3212 break;
3213 case YANG_CUSTOM:
3214 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts);
3215 break;
3216 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003217 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003218 return LY_EVALID;
3219 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003220 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003221 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003222 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003223
3224 return ret;
3225}
3226
Michal Vaskoea5abea2018-09-18 13:10:54 +02003227/**
3228 * @brief Parse the refine statement.
3229 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003230 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003231 * @param[in,out] data Data to read from, always moved to currently handled character.
3232 * @param[in,out] augments Augments to add to.
3233 *
3234 * @return LY_ERR values.
3235 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003236static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003237parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003238{
3239 LY_ERR ret = 0;
3240 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003241 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003242 enum yang_keyword kw;
3243 struct lysp_augment *aug;
3244
3245 LYSP_ARRAY_NEW_RET(ctx, augments, aug, LY_EMEM);
3246
3247 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003248 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003249 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003250
Radek Krejci44ceedc2018-10-02 15:54:31 +02003251 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003252 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003253 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003254
3255 switch (kw) {
3256 case YANG_DESCRIPTION:
3257 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts);
3258 break;
3259 case YANG_IF_FEATURE:
3260 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts);
3261 break;
3262 case YANG_REFERENCE:
3263 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts);
3264 break;
3265 case YANG_STATUS:
3266 ret = parse_status(ctx, data, &aug->flags, &aug->exts);
3267 break;
3268 case YANG_WHEN:
3269 ret = parse_when(ctx, data, &aug->when);
3270 break;
3271
3272 case YANG_ANYDATA:
3273 case YANG_ANYXML:
3274 ret = parse_any(ctx, data, kw, &aug->child);
3275 break;
3276 case YANG_CASE:
3277 ret = parse_case(ctx, data, &aug->child);
3278 break;
3279 case YANG_CHOICE:
3280 ret = parse_choice(ctx, data, &aug->child);
3281 break;
3282 case YANG_CONTAINER:
3283 ret = parse_container(ctx, data, &aug->child);
3284 break;
3285 case YANG_LEAF:
3286 ret = parse_leaf(ctx, data, &aug->child);
3287 break;
3288 case YANG_LEAF_LIST:
3289 ret = parse_leaflist(ctx, data, &aug->child);
3290 break;
3291 case YANG_LIST:
3292 ret = parse_list(ctx, data, &aug->child);
3293 break;
3294 case YANG_USES:
3295 ret = parse_uses(ctx, data, &aug->child);
3296 break;
3297
3298 case YANG_ACTION:
3299 ret = parse_action(ctx, data, &aug->actions);
3300 break;
3301 case YANG_NOTIFICATION:
3302 ret = parse_notif(ctx, data, &aug->notifs);
3303 break;
3304 case YANG_CUSTOM:
3305 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts);
3306 break;
3307 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003308 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003309 return LY_EVALID;
3310 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003311 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003312 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003313 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003314
3315 return ret;
3316}
3317
Michal Vaskoea5abea2018-09-18 13:10:54 +02003318/**
3319 * @brief Parse the uses statement.
3320 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003321 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003322 * @param[in,out] data Data to read from, always moved to currently handled character.
3323 * @param[in,out] siblings Siblings to add to.
3324 *
3325 * @return LY_ERR values.
3326 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003327static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003328parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003329{
3330 LY_ERR ret = 0;
3331 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003332 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003333 enum yang_keyword kw;
3334 struct lysp_node *iter;
3335 struct lysp_node_uses *uses;
3336
3337 /* create structure */
3338 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003339 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003340 uses->nodetype = LYS_USES;
3341
3342 /* insert into siblings */
3343 if (!*siblings) {
3344 *siblings = (struct lysp_node *)uses;
3345 } else {
3346 for (iter = *siblings; iter->next; iter = iter->next);
3347 iter->next = (struct lysp_node *)uses;
3348 }
3349
3350 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003351 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003352 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003353
Radek Krejci44ceedc2018-10-02 15:54:31 +02003354 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003355
3356 /* parse substatements */
3357 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003358 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003359
3360 switch (kw) {
3361 case YANG_DESCRIPTION:
3362 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts);
3363 break;
3364 case YANG_IF_FEATURE:
3365 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts);
3366 break;
3367 case YANG_REFERENCE:
3368 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts);
3369 break;
3370 case YANG_STATUS:
3371 ret = parse_status(ctx, data, &uses->flags, &uses->exts);
3372 break;
3373 case YANG_WHEN:
3374 ret = parse_when(ctx, data, &uses->when);
3375 break;
3376
3377 case YANG_REFINE:
3378 ret = parse_refine(ctx, data, &uses->refines);
3379 break;
3380 case YANG_AUGMENT:
3381 ret = parse_augment(ctx, data, &uses->augments);
3382 break;
3383 case YANG_CUSTOM:
3384 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts);
3385 break;
3386 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003387 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003388 return LY_EVALID;
3389 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003390 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003391 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003392 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003393
3394 return ret;
3395}
3396
Michal Vaskoea5abea2018-09-18 13:10:54 +02003397/**
3398 * @brief Parse the case statement.
3399 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003400 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003401 * @param[in,out] data Data to read from, always moved to currently handled character.
3402 * @param[in,out] siblings Siblings to add to.
3403 *
3404 * @return LY_ERR values.
3405 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003406static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003407parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003408{
3409 LY_ERR ret = 0;
3410 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003411 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003412 enum yang_keyword kw;
3413 struct lysp_node *iter;
3414 struct lysp_node_case *cas;
3415
3416 /* create structure */
3417 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003418 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003419 cas->nodetype = LYS_CASE;
3420
3421 /* insert into siblings */
3422 if (!*siblings) {
3423 *siblings = (struct lysp_node *)cas;
3424 } else {
3425 for (iter = *siblings; iter->next; iter = iter->next);
3426 iter->next = (struct lysp_node *)cas;
3427 }
3428
3429 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003430 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003431 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003432
Radek Krejci44ceedc2018-10-02 15:54:31 +02003433 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003434
3435 /* parse substatements */
3436 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003437 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003438
3439 switch (kw) {
3440 case YANG_DESCRIPTION:
3441 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts);
3442 break;
3443 case YANG_IF_FEATURE:
3444 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts);
3445 break;
3446 case YANG_REFERENCE:
3447 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts);
3448 break;
3449 case YANG_STATUS:
3450 ret = parse_status(ctx, data, &cas->flags, &cas->exts);
3451 break;
3452 case YANG_WHEN:
3453 ret = parse_when(ctx, data, &cas->when);
3454 break;
3455
3456 case YANG_ANYDATA:
3457 case YANG_ANYXML:
3458 ret = parse_any(ctx, data, kw, &cas->child);
3459 break;
3460 case YANG_CHOICE:
3461 ret = parse_case(ctx, data, &cas->child);
3462 break;
3463 case YANG_CONTAINER:
3464 ret = parse_container(ctx, data, &cas->child);
3465 break;
3466 case YANG_LEAF:
3467 ret = parse_leaf(ctx, data, &cas->child);
3468 break;
3469 case YANG_LEAF_LIST:
3470 ret = parse_leaflist(ctx, data, &cas->child);
3471 break;
3472 case YANG_LIST:
3473 ret = parse_list(ctx, data, &cas->child);
3474 break;
3475 case YANG_USES:
3476 ret = parse_uses(ctx, data, &cas->child);
3477 break;
3478 case YANG_CUSTOM:
3479 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts);
3480 break;
3481 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003482 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483 return LY_EVALID;
3484 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003485 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003486 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003487 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003488
3489 return ret;
3490}
3491
Michal Vaskoea5abea2018-09-18 13:10:54 +02003492/**
3493 * @brief Parse the choice statement.
3494 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003495 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003496 * @param[in,out] data Data to read from, always moved to currently handled character.
3497 * @param[in,out] siblings Siblings to add to.
3498 *
3499 * @return LY_ERR values.
3500 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003501static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003502parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003503{
3504 LY_ERR ret = 0;
3505 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003506 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003507 enum yang_keyword kw;
3508 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003509 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003510
3511 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003512 choice = calloc(1, sizeof *choice);
3513 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3514 choice->nodetype = LYS_CHOICE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003515
3516 /* insert into siblings */
3517 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003518 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003519 } else {
3520 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003521 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003522 }
3523
3524 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003525 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003526 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003527
Radek Krejci44ceedc2018-10-02 15:54:31 +02003528 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003529
3530 /* parse substatements */
3531 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003532 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003533
3534 switch (kw) {
3535 case YANG_CONFIG:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003536 ret = parse_config(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003537 break;
3538 case YANG_DESCRIPTION:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003539 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003540 break;
3541 case YANG_IF_FEATURE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003542 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 break;
3544 case YANG_MANDATORY:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003545 ret = parse_mandatory(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003546 break;
3547 case YANG_REFERENCE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003548 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003549 break;
3550 case YANG_STATUS:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003551 ret = parse_status(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003552 break;
3553 case YANG_WHEN:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003554 ret = parse_when(ctx, data, &choice->when);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003555 break;
3556 case YANG_DEFAULT:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003557 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_IDENTIF_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 break;
3559
3560 case YANG_ANYDATA:
3561 case YANG_ANYXML:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003562 ret = parse_any(ctx, data, kw, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563 break;
3564 case YANG_CASE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003565 ret = parse_case(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003566 break;
3567 case YANG_CHOICE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003568 ret = parse_choice(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569 break;
3570 case YANG_CONTAINER:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003571 ret = parse_container(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003572 break;
3573 case YANG_LEAF:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003574 ret = parse_leaf(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003575 break;
3576 case YANG_LEAF_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003577 ret = parse_leaflist(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578 break;
3579 case YANG_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003580 ret = parse_list(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003581 break;
3582 case YANG_CUSTOM:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003583 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584 break;
3585 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003586 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003587 return LY_EVALID;
3588 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003589 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003591 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003592
3593 return ret;
3594}
3595
Michal Vaskoea5abea2018-09-18 13:10:54 +02003596/**
3597 * @brief Parse the container statement.
3598 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003599 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003600 * @param[in,out] data Data to read from, always moved to currently handled character.
3601 * @param[in,out] siblings Siblings to add to.
3602 *
3603 * @return LY_ERR values.
3604 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003605static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003606parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003607{
3608 LY_ERR ret = 0;
3609 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003610 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003611 enum yang_keyword kw;
3612 struct lysp_node *iter;
3613 struct lysp_node_container *cont;
3614
3615 /* create structure */
3616 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003617 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003618 cont->nodetype = LYS_CONTAINER;
3619
3620 /* insert into siblings */
3621 if (!*siblings) {
3622 *siblings = (struct lysp_node *)cont;
3623 } else {
3624 for (iter = *siblings; iter->next; iter = iter->next);
3625 iter->next = (struct lysp_node *)cont;
3626 }
3627
3628 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003629 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003630 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003631
Radek Krejci44ceedc2018-10-02 15:54:31 +02003632 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003633
3634 /* parse substatements */
3635 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003636 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003637
3638 switch (kw) {
3639 case YANG_CONFIG:
3640 ret = parse_config(ctx, data, &cont->flags, &cont->exts);
3641 break;
3642 case YANG_DESCRIPTION:
3643 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts);
3644 break;
3645 case YANG_IF_FEATURE:
3646 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts);
3647 break;
3648 case YANG_REFERENCE:
3649 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts);
3650 break;
3651 case YANG_STATUS:
3652 ret = parse_status(ctx, data, &cont->flags, &cont->exts);
3653 break;
3654 case YANG_WHEN:
3655 ret = parse_when(ctx, data, &cont->when);
3656 break;
3657 case YANG_PRESENCE:
3658 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts);
3659 break;
3660
3661 case YANG_ANYDATA:
3662 case YANG_ANYXML:
3663 ret = parse_any(ctx, data, kw, &cont->child);
3664 break;
3665 case YANG_CHOICE:
3666 ret = parse_choice(ctx, data, &cont->child);
3667 break;
3668 case YANG_CONTAINER:
3669 ret = parse_container(ctx, data, &cont->child);
3670 break;
3671 case YANG_LEAF:
3672 ret = parse_leaf(ctx, data, &cont->child);
3673 break;
3674 case YANG_LEAF_LIST:
3675 ret = parse_leaflist(ctx, data, &cont->child);
3676 break;
3677 case YANG_LIST:
3678 ret = parse_list(ctx, data, &cont->child);
3679 break;
3680 case YANG_USES:
3681 ret = parse_uses(ctx, data, &cont->child);
3682 break;
3683
3684 case YANG_TYPEDEF:
3685 ret = parse_typedef(ctx, data, &cont->typedefs);
3686 break;
3687 case YANG_MUST:
3688 ret = parse_restrs(ctx, data, kw, &cont->musts);
3689 break;
3690 case YANG_ACTION:
3691 ret = parse_action(ctx, data, &cont->actions);
3692 break;
3693 case YANG_GROUPING:
3694 ret = parse_grouping(ctx, data, &cont->groupings);
3695 break;
3696 case YANG_NOTIFICATION:
3697 ret = parse_notif(ctx, data, &cont->notifs);
3698 break;
3699 case YANG_CUSTOM:
3700 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts);
3701 break;
3702 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003703 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003704 return LY_EVALID;
3705 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003706 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003707 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003708 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003709
3710 return ret;
3711}
3712
Michal Vaskoea5abea2018-09-18 13:10:54 +02003713/**
3714 * @brief Parse the list statement.
3715 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003716 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003717 * @param[in,out] data Data to read from, always moved to currently handled character.
3718 * @param[in,out] siblings Siblings to add to.
3719 *
3720 * @return LY_ERR values.
3721 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003722static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003723parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003724{
3725 LY_ERR ret = 0;
3726 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003727 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003728 enum yang_keyword kw;
3729 struct lysp_node *iter;
3730 struct lysp_node_list *list;
3731
3732 /* create structure */
3733 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003734 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003735 list->nodetype = LYS_LIST;
3736
3737 /* insert into siblings */
3738 if (!*siblings) {
3739 *siblings = (struct lysp_node *)list;
3740 } else {
3741 for (iter = *siblings; iter->next; iter = iter->next);
3742 iter->next = (struct lysp_node *)list;
3743 }
3744
3745 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003746 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003747 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003748
Radek Krejci44ceedc2018-10-02 15:54:31 +02003749 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003750
3751 /* parse substatements */
3752 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003753 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003754
3755 switch (kw) {
3756 case YANG_CONFIG:
3757 ret = parse_config(ctx, data, &list->flags, &list->exts);
3758 break;
3759 case YANG_DESCRIPTION:
3760 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts);
3761 break;
3762 case YANG_IF_FEATURE:
3763 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts);
3764 break;
3765 case YANG_REFERENCE:
3766 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts);
3767 break;
3768 case YANG_STATUS:
3769 ret = parse_status(ctx, data, &list->flags, &list->exts);
3770 break;
3771 case YANG_WHEN:
3772 ret = parse_when(ctx, data, &list->when);
3773 break;
3774 case YANG_KEY:
3775 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts);
3776 break;
3777 case YANG_MAX_ELEMENTS:
3778 ret = parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts);
3779 break;
3780 case YANG_MIN_ELEMENTS:
3781 ret = parse_minelements(ctx, data, &list->min, &list->flags, &list->exts);
3782 break;
3783 case YANG_ORDERED_BY:
3784 ret = parse_orderedby(ctx, data, &list->flags, &list->exts);
3785 break;
3786 case YANG_UNIQUE:
3787 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts);
3788 break;
3789
3790 case YANG_ANYDATA:
3791 case YANG_ANYXML:
3792 ret = parse_any(ctx, data, kw, &list->child);
3793 break;
3794 case YANG_CHOICE:
3795 ret = parse_choice(ctx, data, &list->child);
3796 break;
3797 case YANG_CONTAINER:
3798 ret = parse_container(ctx, data, &list->child);
3799 break;
3800 case YANG_LEAF:
3801 ret = parse_leaf(ctx, data, &list->child);
3802 break;
3803 case YANG_LEAF_LIST:
3804 ret = parse_leaflist(ctx, data, &list->child);
3805 break;
3806 case YANG_LIST:
3807 ret = parse_list(ctx, data, &list->child);
3808 break;
3809 case YANG_USES:
3810 ret = parse_uses(ctx, data, &list->child);
3811 break;
3812
3813 case YANG_TYPEDEF:
3814 ret = parse_typedef(ctx, data, &list->typedefs);
3815 break;
3816 case YANG_MUST:
3817 ret = parse_restrs(ctx, data, kw, &list->musts);
3818 break;
3819 case YANG_ACTION:
3820 ret = parse_action(ctx, data, &list->actions);
3821 break;
3822 case YANG_GROUPING:
3823 ret = parse_grouping(ctx, data, &list->groupings);
3824 break;
3825 case YANG_NOTIFICATION:
3826 ret = parse_notif(ctx, data, &list->notifs);
3827 break;
3828 case YANG_CUSTOM:
3829 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts);
3830 break;
3831 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003832 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003833 return LY_EVALID;
3834 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003835 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003836 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003837 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003838
3839 return ret;
3840}
3841
Michal Vaskoea5abea2018-09-18 13:10:54 +02003842/**
3843 * @brief Parse the yin-element statement.
3844 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003845 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003846 * @param[in,out] data Data to read from, always moved to currently handled character.
3847 * @param[in,out] flags Flags to write to.
3848 * @param[in,out] exts Extension instances to add to.
3849 *
3850 * @return LY_ERR values.
3851 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003852static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003853parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003854{
3855 LY_ERR ret = 0;
3856 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003857 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003858 enum yang_keyword kw;
3859
3860 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003861 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003862 return LY_EVALID;
3863 }
3864
3865 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003866 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003867 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003868
3869 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3870 *flags |= LYS_YINELEM_TRUE;
3871 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3872 *flags |= LYS_YINELEM_FALSE;
3873 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003874 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875 free(buf);
3876 return LY_EVALID;
3877 }
3878 free(buf);
3879
3880 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003881 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003882
3883 switch (kw) {
3884 case YANG_CUSTOM:
3885 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02003886 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003887 break;
3888 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003889 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003890 return LY_EVALID;
3891 }
3892 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003893 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003894
3895 return ret;
3896}
3897
Michal Vaskoea5abea2018-09-18 13:10:54 +02003898/**
3899 * @brief Parse the yin-element statement.
3900 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003901 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003902 * @param[in,out] data Data to read from, always moved to currently handled character.
3903 * @param[in,out] argument Value to write to.
3904 * @param[in,out] flags Flags to write to.
3905 * @param[in,out] exts Extension instances to add to.
3906 *
3907 * @return LY_ERR values.
3908 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003909static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003910parse_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 +02003911{
3912 LY_ERR ret = 0;
3913 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003914 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003915 enum yang_keyword kw;
3916
3917 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003918 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003919 return LY_EVALID;
3920 }
3921
3922 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003923 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003924 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003925
Radek Krejci44ceedc2018-10-02 15:54:31 +02003926 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003927 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003928 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003929
3930 switch (kw) {
3931 case YANG_YIN_ELEMENT:
3932 ret = parse_yinelement(ctx, data, flags, exts);
3933 break;
3934 case YANG_CUSTOM:
3935 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts);
3936 break;
3937 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003938 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003939 return LY_EVALID;
3940 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003941 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003942 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003943 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003944
3945 return ret;
3946}
3947
Michal Vaskoea5abea2018-09-18 13:10:54 +02003948/**
3949 * @brief Parse the extension statement.
3950 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003951 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003952 * @param[in,out] data Data to read from, always moved to currently handled character.
3953 * @param[in,out] extensions Extensions to add to.
3954 *
3955 * @return LY_ERR values.
3956 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003957static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003958parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003959{
3960 LY_ERR ret = 0;
3961 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003962 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003963 enum yang_keyword kw;
3964 struct lysp_ext *ex;
3965
3966 LYSP_ARRAY_NEW_RET(ctx, extensions, ex, LY_EMEM);
3967
3968 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003969 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003970 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003971
Radek Krejci44ceedc2018-10-02 15:54:31 +02003972 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003973 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003974 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003975
3976 switch (kw) {
3977 case YANG_DESCRIPTION:
3978 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts);
3979 break;
3980 case YANG_REFERENCE:
3981 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts);
3982 break;
3983 case YANG_STATUS:
3984 ret = parse_status(ctx, data, &ex->flags, &ex->exts);
3985 break;
3986 case YANG_ARGUMENT:
3987 ret = parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts);
3988 break;
3989 case YANG_CUSTOM:
3990 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts);
3991 break;
3992 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003993 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003994 return LY_EVALID;
3995 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003996 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003997 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003998 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003999
4000 return ret;
4001}
4002
Michal Vaskoea5abea2018-09-18 13:10:54 +02004003/**
4004 * @brief Parse the deviate statement.
4005 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004006 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004007 * @param[in,out] data Data to read from, always moved to currently handled character.
4008 * @param[in,out] deviates Deviates to add to.
4009 *
4010 * @return LY_ERR values.
4011 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004012static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004013parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004014{
4015 LY_ERR ret = 0;
4016 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004017 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004018 enum yang_keyword kw;
4019 struct lysp_deviate *iter, *d;
4020 struct lysp_deviate_add *d_add = NULL;
4021 struct lysp_deviate_rpl *d_rpl = NULL;
4022 struct lysp_deviate_del *d_del = NULL;
4023 const char **d_units, ***d_uniques, ***d_dflts;
4024 struct lysp_restr **d_musts;
4025 uint16_t *d_flags;
4026 uint32_t *d_min, *d_max;
4027
4028 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004029 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004030 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004031
4032 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4033 dev_mod = LYS_DEV_NOT_SUPPORTED;
4034 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4035 dev_mod = LYS_DEV_ADD;
4036 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4037 dev_mod = LYS_DEV_REPLACE;
4038 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4039 dev_mod = LYS_DEV_DELETE;
4040 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004041 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004042 free(buf);
4043 return LY_EVALID;
4044 }
4045 free(buf);
4046
4047 /* create structure */
4048 switch (dev_mod) {
4049 case LYS_DEV_NOT_SUPPORTED:
4050 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004051 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004052 break;
4053 case LYS_DEV_ADD:
4054 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004055 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004056 d = (struct lysp_deviate *)d_add;
4057 d_units = &d_add->units;
4058 d_uniques = &d_add->uniques;
4059 d_dflts = &d_add->dflts;
4060 d_musts = &d_add->musts;
4061 d_flags = &d_add->flags;
4062 d_min = &d_add->min;
4063 d_max = &d_add->max;
4064 break;
4065 case LYS_DEV_REPLACE:
4066 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004067 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004068 d = (struct lysp_deviate *)d_rpl;
4069 d_units = &d_rpl->units;
4070 d_flags = &d_rpl->flags;
4071 d_min = &d_rpl->min;
4072 d_max = &d_rpl->max;
4073 break;
4074 case LYS_DEV_DELETE:
4075 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004076 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004077 d = (struct lysp_deviate *)d_del;
4078 d_units = &d_del->units;
4079 d_uniques = &d_del->uniques;
4080 d_dflts = &d_del->dflts;
4081 d_musts = &d_del->musts;
4082 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004083 break;
4084 default:
4085 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004086 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004087 }
4088 d->mod = dev_mod;
4089
4090 /* insert into siblings */
4091 if (!*deviates) {
4092 *deviates = d;
4093 } else {
4094 for (iter = *deviates; iter->next; iter = iter->next);
4095 iter->next = d;
4096 }
4097
4098 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004099 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004100
4101 switch (kw) {
4102 case YANG_CONFIG:
4103 switch (dev_mod) {
4104 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004105 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004106 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004107 return LY_EVALID;
4108 default:
4109 ret = parse_config(ctx, data, d_flags, &d->exts);
4110 break;
4111 }
4112 break;
4113 case YANG_DEFAULT:
4114 switch (dev_mod) {
4115 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004116 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004117 return LY_EVALID;
4118 case LYS_DEV_REPLACE:
4119 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts);
4120 break;
4121 default:
4122 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts);
4123 break;
4124 }
4125 break;
4126 case YANG_MANDATORY:
4127 switch (dev_mod) {
4128 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004129 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004130 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004131 return LY_EVALID;
4132 default:
4133 ret = parse_mandatory(ctx, data, d_flags, &d->exts);
4134 break;
4135 }
4136 break;
4137 case YANG_MAX_ELEMENTS:
4138 switch (dev_mod) {
4139 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004140 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004141 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004142 return LY_EVALID;
4143 default:
4144 ret = parse_maxelements(ctx, data, d_max, d_flags, &d->exts);
4145 break;
4146 }
4147 break;
4148 case YANG_MIN_ELEMENTS:
4149 switch (dev_mod) {
4150 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004151 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004152 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004153 return LY_EVALID;
4154 default:
4155 ret = parse_minelements(ctx, data, d_min, d_flags, &d->exts);
4156 break;
4157 }
4158 break;
4159 case YANG_MUST:
4160 switch (dev_mod) {
4161 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004162 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004163 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004164 return LY_EVALID;
4165 default:
4166 ret = parse_restrs(ctx, data, kw, d_musts);
4167 break;
4168 }
4169 break;
4170 case YANG_TYPE:
4171 switch (dev_mod) {
4172 case LYS_DEV_NOT_SUPPORTED:
4173 case LYS_DEV_ADD:
4174 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004175 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004176 return LY_EVALID;
4177 default:
4178 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004179 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004180 ret = parse_type(ctx, data, d_rpl->type);
4181 break;
4182 }
4183 break;
4184 case YANG_UNIQUE:
4185 switch (dev_mod) {
4186 case LYS_DEV_NOT_SUPPORTED:
4187 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004188 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004189 return LY_EVALID;
4190 default:
4191 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts);
4192 break;
4193 }
4194 break;
4195 case YANG_UNITS:
4196 switch (dev_mod) {
4197 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004198 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004199 return LY_EVALID;
4200 default:
4201 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts);
4202 break;
4203 }
4204 break;
4205 case YANG_CUSTOM:
4206 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts);
4207 break;
4208 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004209 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004210 return LY_EVALID;
4211 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004212 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004213 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004214 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004215
4216 return ret;
4217}
4218
Michal Vaskoea5abea2018-09-18 13:10:54 +02004219/**
4220 * @brief Parse the deviation statement.
4221 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004222 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004223 * @param[in,out] data Data to read from, always moved to currently handled character.
4224 * @param[in,out] deviations Deviations to add to.
4225 *
4226 * @return LY_ERR values.
4227 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004228static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004229parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004230{
4231 LY_ERR ret = 0;
4232 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004233 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004234 enum yang_keyword kw;
4235 struct lysp_deviation *dev;
4236
4237 LYSP_ARRAY_NEW_RET(ctx, deviations, dev, LY_EMEM);
4238
4239 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004240 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004241 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004242
Radek Krejci44ceedc2018-10-02 15:54:31 +02004243 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004244 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004245 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004246
4247 switch (kw) {
4248 case YANG_DESCRIPTION:
4249 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts);
4250 break;
4251 case YANG_DEVIATE:
4252 ret = parse_deviate(ctx, data, &dev->deviates);
4253 break;
4254 case YANG_REFERENCE:
4255 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts);
4256 break;
4257 case YANG_CUSTOM:
4258 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts);
4259 break;
4260 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004261 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004262 return LY_EVALID;
4263 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004264 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004265 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004266 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004267
4268 /* mandatory substatements */
4269 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004270 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004271 return LY_EVALID;
4272 }
4273
4274 return ret;
4275}
4276
Michal Vaskoea5abea2018-09-18 13:10:54 +02004277/**
4278 * @brief Parse the feature statement.
4279 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004280 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004281 * @param[in,out] data Data to read from, always moved to currently handled character.
4282 * @param[in,out] features Features to add to.
4283 *
4284 * @return LY_ERR values.
4285 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004286static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004287parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004288{
4289 LY_ERR ret = 0;
4290 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004291 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004292 enum yang_keyword kw;
4293 struct lysp_feature *feat;
4294
4295 LYSP_ARRAY_NEW_RET(ctx, features, feat, LY_EMEM);
4296
4297 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004298 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004299 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004300
Radek Krejci44ceedc2018-10-02 15:54:31 +02004301 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004302 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004303 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004304
4305 switch (kw) {
4306 case YANG_DESCRIPTION:
4307 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts);
4308 break;
4309 case YANG_IF_FEATURE:
4310 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts);
4311 break;
4312 case YANG_REFERENCE:
4313 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts);
4314 break;
4315 case YANG_STATUS:
4316 ret = parse_status(ctx, data, &feat->flags, &feat->exts);
4317 break;
4318 case YANG_CUSTOM:
4319 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts);
4320 break;
4321 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004322 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004323 return LY_EMEM;
4324 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004325 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004326 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004327 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004328
4329 return ret;
4330}
4331
Michal Vaskoea5abea2018-09-18 13:10:54 +02004332/**
4333 * @brief Parse the identity statement.
4334 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004335 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004336 * @param[in,out] data Data to read from, always moved to currently handled character.
4337 * @param[in,out] identities Identities to add to.
4338 *
4339 * @return LY_ERR values.
4340 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004341static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004342parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004343{
4344 LY_ERR ret = 0;
4345 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004346 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004347 enum yang_keyword kw;
4348 struct lysp_ident *ident;
4349
4350 LYSP_ARRAY_NEW_RET(ctx, identities, ident, LY_EMEM);
4351
4352 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004353 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004354 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004355
Radek Krejci44ceedc2018-10-02 15:54:31 +02004356 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004357 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004358 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004359
4360 switch (kw) {
4361 case YANG_DESCRIPTION:
4362 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts);
4363 break;
4364 case YANG_IF_FEATURE:
4365 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts);
4366 break;
4367 case YANG_REFERENCE:
4368 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts);
4369 break;
4370 case YANG_STATUS:
4371 ret = parse_status(ctx, data, &ident->flags, &ident->exts);
4372 break;
4373 case YANG_BASE:
4374 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts);
4375 break;
4376 case YANG_CUSTOM:
4377 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts);
4378 break;
4379 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004380 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004381 return LY_EVALID;
4382 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004383 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004384 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004385 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004386
4387 return ret;
4388}
4389
Michal Vaskoea5abea2018-09-18 13:10:54 +02004390/**
4391 * @brief Parse the module or submodule statement.
4392 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004393 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004394 * @param[in,out] data Data to read from, always moved to currently handled character.
4395 * @param[in,out] mod Module to write to.
4396 *
4397 * @return LY_ERR values.
4398 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004399static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004400parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004401{
4402 LY_ERR ret = 0;
4403 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004404 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004405 enum yang_keyword kw, prev_kw = 0;
4406 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4407
4408 /* (sub)module name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004409 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004410 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004411
Radek Krejci44ceedc2018-10-02 15:54:31 +02004412 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004413 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004414 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004415
4416 switch (kw) {
4417 /* module header */
4418 case YANG_NAMESPACE:
4419 case YANG_PREFIX:
4420 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004421 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422 return LY_EVALID;
4423 }
4424 /* fallthrough */
4425 case YANG_BELONGS_TO:
4426 if ((kw == YANG_BELONGS_TO) && !mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004427 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428 return LY_EVALID;
4429 }
4430 /* fallthrough */
4431 case YANG_YANG_VERSION:
4432 if (mod_stmt > Y_MOD_MODULE_HEADER) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004433 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004434 return LY_EVALID;
4435 }
4436 break;
4437 /* linkage */
4438 case YANG_INCLUDE:
4439 case YANG_IMPORT:
4440 if (mod_stmt > Y_MOD_LINKAGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004441 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004442 return LY_EVALID;
4443 }
4444 mod_stmt = Y_MOD_LINKAGE;
4445 break;
4446 /* meta */
4447 case YANG_ORGANIZATION:
4448 case YANG_CONTACT:
4449 case YANG_DESCRIPTION:
4450 case YANG_REFERENCE:
4451 if (mod_stmt > Y_MOD_META) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004452 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004453 return LY_EVALID;
4454 }
4455 mod_stmt = Y_MOD_META;
4456 break;
4457
4458 /* revision */
4459 case YANG_REVISION:
4460 if (mod_stmt > Y_MOD_REVISION) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004461 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004462 return LY_EVALID;
4463 }
4464 mod_stmt = Y_MOD_REVISION;
4465 break;
4466
4467 /* body */
4468 case YANG_ANYDATA:
4469 case YANG_ANYXML:
4470 case YANG_AUGMENT:
4471 case YANG_CHOICE:
4472 case YANG_CONTAINER:
4473 case YANG_DEVIATION:
4474 case YANG_EXTENSION:
4475 case YANG_FEATURE:
4476 case YANG_GROUPING:
4477 case YANG_IDENTITY:
4478 case YANG_LEAF:
4479 case YANG_LEAF_LIST:
4480 case YANG_LIST:
4481 case YANG_NOTIFICATION:
4482 case YANG_RPC:
4483 case YANG_TYPEDEF:
4484 case YANG_USES:
4485 case YANG_CUSTOM:
4486 mod_stmt = Y_MOD_BODY;
4487 break;
4488 default:
4489 /* error handled in the next switch */
4490 break;
4491 }
4492 prev_kw = kw;
4493
4494 switch (kw) {
4495 /* module header */
4496 case YANG_YANG_VERSION:
4497 ret = parse_yangversion(ctx, data, mod);
4498 break;
4499 case YANG_NAMESPACE:
4500 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts);
4501 break;
4502 case YANG_PREFIX:
4503 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts);
4504 break;
4505 case YANG_BELONGS_TO:
4506 ret = parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts);
4507 break;
4508
4509 /* linkage */
4510 case YANG_INCLUDE:
4511 ret = parse_include(ctx, data, &mod->includes);
4512 break;
4513 case YANG_IMPORT:
4514 ret = parse_import(ctx, data, &mod->imports);
4515 break;
4516
4517 /* meta */
4518 case YANG_ORGANIZATION:
4519 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts);
4520 break;
4521 case YANG_CONTACT:
4522 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts);
4523 break;
4524 case YANG_DESCRIPTION:
4525 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts);
4526 break;
4527 case YANG_REFERENCE:
4528 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts);
4529 break;
4530
4531 /* revision */
4532 case YANG_REVISION:
4533 ret = parse_revision(ctx, data, &mod->revs);
4534 break;
4535
4536 /* body */
4537 case YANG_ANYDATA:
4538 case YANG_ANYXML:
4539 ret = parse_any(ctx, data, kw, &mod->data);
4540 break;
4541 case YANG_CHOICE:
4542 ret = parse_choice(ctx, data, &mod->data);
4543 break;
4544 case YANG_CONTAINER:
4545 ret = parse_container(ctx, data, &mod->data);
4546 break;
4547 case YANG_LEAF:
4548 ret = parse_leaf(ctx, data, &mod->data);
4549 break;
4550 case YANG_LEAF_LIST:
4551 ret = parse_leaflist(ctx, data, &mod->data);
4552 break;
4553 case YANG_LIST:
4554 ret = parse_list(ctx, data, &mod->data);
4555 break;
4556 case YANG_USES:
4557 ret = parse_uses(ctx, data, &mod->data);
4558 break;
4559
4560 case YANG_AUGMENT:
4561 ret = parse_augment(ctx, data, &mod->augments);
4562 break;
4563 case YANG_DEVIATION:
4564 ret = parse_deviation(ctx, data, &mod->deviations);
4565 break;
4566 case YANG_EXTENSION:
4567 ret = parse_extension(ctx, data, &mod->extensions);
4568 break;
4569 case YANG_FEATURE:
4570 ret = parse_feature(ctx, data, &mod->features);
4571 break;
4572 case YANG_GROUPING:
4573 ret = parse_grouping(ctx, data, &mod->groupings);
4574 break;
4575 case YANG_IDENTITY:
4576 ret = parse_identity(ctx, data, &mod->identities);
4577 break;
4578 case YANG_NOTIFICATION:
4579 ret = parse_notif(ctx, data, &mod->notifs);
4580 break;
4581 case YANG_RPC:
4582 ret = parse_action(ctx, data, &mod->rpcs);
4583 break;
4584 case YANG_TYPEDEF:
4585 ret = parse_typedef(ctx, data, &mod->typedefs);
4586 break;
4587 case YANG_CUSTOM:
4588 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts);
4589 break;
4590
4591 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004592 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004593 return LY_EVALID;
4594 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004595 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004596 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004597 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004598
4599 /* mandatory substatements */
4600 if (mod->submodule) {
4601 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004602 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004603 return LY_EVALID;
4604 }
4605 } else {
4606 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004607 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004608 return LY_EVALID;
4609 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004610 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004611 return LY_EVALID;
4612 }
4613 }
4614
4615 return ret;
4616}
4617
Radek Krejcid4557c62018-09-17 11:42:09 +02004618LY_ERR
Michal Vasko7fbc8162018-09-17 10:35:16 +02004619yang_parse(struct ly_ctx *ctx, const char *data, struct lysp_module **mod_p)
4620{
4621 LY_ERR ret = 0;
4622 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004623 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004624 enum yang_keyword kw;
4625 struct lysp_module *mod;
Radek Krejci44ceedc2018-10-02 15:54:31 +02004626 struct ly_parser_ctx context;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004627
Radek Krejci44ceedc2018-10-02 15:54:31 +02004628 context.ctx = ctx;
4629 context.line = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004630
4631 /* "module"/"submodule" */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004632 ret = get_keyword(&context, &data, &kw, &word, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004633 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004634
4635 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004636 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004637 ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004638 goto error;
4639 }
4640
4641 mod = calloc(1, sizeof *mod);
4642 LY_CHECK_ERR_GOTO(!mod, LOGMEM(ctx), error);
4643 if (kw == YANG_SUBMODULE) {
4644 mod->submodule = 1;
4645 }
4646
4647 /* substatements */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004648 ret = parse_sub_module(&context, &data, mod);
Radek Krejcic59bc972018-09-17 16:13:06 +02004649 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004650
4651 /* read some trailing spaces or new lines */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004652 ret = get_argument(&context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004653 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004654
4655 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004656 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004657 word_len, word);
4658 free(buf);
4659 goto error;
4660 }
4661 assert(!buf);
4662
4663 *mod_p = mod;
4664 return ret;
4665
4666error:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004667 /* TODO free module */
4668 return ret;
4669}