blob: ab6f7ac84226192a0f3c9318e0ae7644db05cd2f [file] [log] [blame]
Michal Vasko7fbc8162018-09-17 10:35:16 +02001/**
2 * @file parser_yang.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YANG parser
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <errno.h>
22#include <ctype.h>
23#include <string.h>
24#include <dirent.h>
25#include <assert.h>
26
27#include "common.h"
28#include "context.h"
29#include "libyang.h"
Radek Krejci70853c52018-10-15 14:46:16 +020030#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020031
32/* Macro to check YANG's yang-char grammar rule */
33#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
34 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
35 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
36 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
37 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
38 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
39 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
40 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
41 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
42 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
43
44/* These 2 macros checks YANG's identifier grammar rule */
45#define is_yangidentstartchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
46#define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
47 c == '_' || c == '-' || c == '.')
48
Radek Krejcifaa1eac2018-10-30 14:34:55 +010049#define CHECK_UNIQUENESS(CTX, ARRAY, MEMBER, STMT, IDENT) \
50 if (ARRAY) { \
51 for (unsigned int u = 0; u < LY_ARRAY_SIZE(ARRAY) - 1; ++u) { \
52 if (!strcmp((ARRAY)[u].MEMBER, IDENT)) { \
53 LOGVAL_YANG(CTX, LY_VCODE_DUPIDENT, IDENT, STMT); \
54 return LY_EVALID; \
55 } \
56 } \
57 }
58
Radek Krejci9fcacc12018-10-11 15:59:11 +020059#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
60 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
61 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020062
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020063#define MOVE_INPUT(CTX, DATA, COUNT) (*(data))+=COUNT;(CTX)->indent+=COUNT
64
Michal Vaskoea5abea2018-09-18 13:10:54 +020065/**
66 * @brief Loop through all substatements providing, return if there are none.
67 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020068 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020069 * @param[in] DATA Raw data to read from.
70 * @param[out] KW YANG keyword read.
71 * @param[out] WORD Pointer to the keyword itself.
72 * @param[out] WORD_LEN Length of the keyword.
73 * @param[out] ERR Variable for error storing.
74 *
75 * @return In case there are no substatements or a fatal error encountered.
76 */
Michal Vasko7fbc8162018-09-17 10:35:16 +020077#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR) \
78 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
Radek Krejcic59bc972018-09-17 16:13:06 +020079 LY_CHECK_RET(ERR); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020080 \
81 if (KW == YANG_SEMICOLON) { \
82 return ERR; \
83 } \
84 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020085 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020086 return LY_EVALID; \
87 } \
88 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
89 !ERR && (KW != YANG_RIGHT_BRACE); \
90 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
91
Radek Krejci44ceedc2018-10-02 15:54:31 +020092static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
93static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
94static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
95static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
96static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
97static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +020098
Michal Vaskoea5abea2018-09-18 13:10:54 +020099/**
100 * @brief Add another character to dynamic buffer, a low-level function.
101 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200102 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200103 *
Radek Krejci404251e2018-10-09 12:06:44 +0200104 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200105 * @param[in, out] input Input string to process.
106 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200107 * @param[in,out] buf Buffer to use, can be moved by realloc().
108 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200109 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200110 *
111 * @return LY_ERR values.
112 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200113static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200114buf_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 +0200115{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200116 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200117 *buf_len += 16;
118 *buf = ly_realloc(*buf, *buf_len);
119 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
120 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200121 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200122
Radek Krejci44ceedc2018-10-02 15:54:31 +0200123 (*buf_used) += len;
124 (*input) += len;
125
Michal Vasko7fbc8162018-09-17 10:35:16 +0200126 return LY_SUCCESS;
127}
128
Michal Vaskoea5abea2018-09-18 13:10:54 +0200129/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200130 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200131 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200132 * @param[in] ctx yang parser context for logging.
133 * @param[in] c UTF8 code point of a character to check.
134 * @return LY_ERR values.
135 */
136static LY_ERR
137check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
138{
139 if (!is_yangutf8char(c)) {
140 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
141 return LY_EVALID;
142 }
143 return LY_SUCCESS;
144}
145
146/**
147 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
148 *
149 * @param[in] ctx yang parser context for logging.
150 * @param[in] c UTF8 code point of a character to check.
151 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200152 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
153 * 0 - colon not yet found (no prefix)
154 * 1 - \p c is the colon character
155 * 2 - prefix already processed, now processing the identifier
156 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200157 * If the identifier cannot be prefixed, NULL is expected.
158 * @return LY_ERR values.
159 */
160static LY_ERR
161check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
162{
163 if (first || (prefix && (*prefix) == 1)) {
164 if (!is_yangidentstartchar(c)) {
165 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
166 return LY_EVALID;
167 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200168 if (prefix) {
169 if (first) {
170 (*prefix) = 0;
171 } else {
172 (*prefix) = 2;
173 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200174 }
175 } else if (c == ':' && prefix && (*prefix) == 0) {
176 (*prefix) = 1;
177 } else if (!is_yangidentchar(c)) {
178 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
179 return LY_EVALID;
180 }
181
182 return LY_SUCCESS;
183}
184
185/**
186 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
187 *
188 * @param[in] ctx yang parser context for logging.
189 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
190 * when function returns.
191 * @param[in] arg Type of the input string to select method of checking character validity.
192 * @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 +0200193 * 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 +0200194 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
195 * @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 +0200196 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200197 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200198 *
199 * @return LY_ERR values.
200 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200201static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200202buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
203 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200204{
Radek Krejci404251e2018-10-09 12:06:44 +0200205 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200206 unsigned int c;
207 size_t len;
208
209 /* get UTF8 code point (and number of bytes coding the character) */
210 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
211 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
212 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200213 if (c == '\n') {
214 ctx->indent = 0;
215 } else {
216 /* note - even the multibyte character is count as 1 */
217 ++ctx->indent;
218 }
219
Radek Krejci44ceedc2018-10-02 15:54:31 +0200220 /* check character validity */
221 switch (arg) {
222 case Y_IDENTIF_ARG:
223 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
224 break;
225 case Y_PREF_IDENTIF_ARG:
226 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
227 break;
228 case Y_STR_ARG:
229 case Y_MAYBE_STR_ARG:
230 LY_CHECK_RET(check_stringchar(ctx, c));
231 break;
232 }
233
Michal Vasko7fbc8162018-09-17 10:35:16 +0200234 if (word_b && *word_b) {
235 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200236 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200237 return LY_EMEM;
238 }
239
240 /* in case of realloc */
241 *word_p = *word_b;
242 } else if (need_buf) {
243 /* first time we need a buffer, copy everything read up to now */
244 if (*word_len) {
245 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200246 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200247 *buf_len = *word_len;
248 memcpy(*word_b, *word_p, *word_len);
249 }
250
251 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200252 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200253 return LY_EMEM;
254 }
255
256 /* in case of realloc */
257 *word_p = *word_b;
258 } else {
259 /* just remember the first character pointer */
260 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200261 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200262 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200263 /* ... and update the word's length */
264 (*word_len) += len;
265 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200266 }
267
268 return LY_SUCCESS;
269}
270
Michal Vaskoea5abea2018-09-18 13:10:54 +0200271/**
272 * @brief Skip YANG comment in data.
273 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200274 * @param[in] ctx yang parser context for logging.
275 * @param[in,out] data Data to read from, automatically moved after the comment.
276 * @param[in] comment Type of the comment to process:
277 * 1 for a one-line comment,
278 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200279 *
280 * @return LY_ERR values.
281 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200282static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200283skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200284{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200285 /* internal statuses: 0 - comment ended,
286 * 1 - in line comment,
287 * 2 - in block comment,
288 * 3 - in block comment with last read character '*'
289 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200290 while (**data && comment) {
291 switch (comment) {
292 case 1:
293 if (**data == '\n') {
294 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200295 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200296 }
297 break;
298 case 2:
299 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200300 comment = 3;
301 } else if (**data == '\n') {
302 ++ctx->line;
303 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200304 break;
305 case 3:
306 if (**data == '/') {
307 comment = 0;
308 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200309 if (**data == '\n') {
310 ++ctx->line;
311 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200312 comment = 2;
313 }
314 break;
315 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200316 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200317 }
318
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200319 if (**data == '\n') {
320 ctx->indent = 0;
321 } else {
322 ++ctx->indent;
323 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200324 ++(*data);
325 }
326
327 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200328 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200329 return LY_EVALID;
330 }
331
332 return LY_SUCCESS;
333}
334
Michal Vaskoea5abea2018-09-18 13:10:54 +0200335/**
336 * @brief Read a quoted string from data.
337 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200338 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200339 * @param[in,out] data Data to read from, always moved to currently handled character.
340 * @param[in] arg Type of YANG keyword argument expected.
341 * @param[out] word_p Pointer to the read quoted string.
342 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
343 * set to NULL. Otherwise equal to \p word_p.
344 * @param[out] word_len Length of the read quoted string.
345 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
346 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
347 * indenation in the final quoted string.
348 *
349 * @return LY_ERR values.
350 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200351static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200352read_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 +0200353 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200354{
355 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
356 * 4 - string finished, now skipping whitespaces looking for +,
357 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200358 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200359 const char *c;
360
361 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200362 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200363 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200364 } else {
365 assert(**data == '\'');
366 string = 1;
367 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200368 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200369
370 while (**data && string) {
371 switch (string) {
372 case 1:
373 switch (**data) {
374 case '\'':
375 /* string may be finished, but check for + */
376 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200377 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200378 break;
379 default:
380 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200381 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 +0200382 break;
383 }
384 break;
385 case 2:
386 switch (**data) {
387 case '\"':
388 /* string may be finished, but check for + */
389 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200390 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200391 break;
392 case '\\':
393 /* special character following */
394 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200395 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200396 break;
397 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200398 if (current_indent < block_indent) {
399 ++current_indent;
400 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200401 } else {
402 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200403 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 +0200404 }
405 break;
406 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200407 if (current_indent < block_indent) {
408 assert(need_buf);
409 current_indent += 8;
410 ctx->indent += 8;
411 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
412 /* store leftover spaces from the tab */
413 c = " ";
414 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 +0200415 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200416 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200417 } else {
418 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200419 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 +0200420 /* additional characters for indentation - only 1 was count in buf_store_char */
421 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200422 }
423 break;
424 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200425 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200426 /* we will be removing the indents so we need our own buffer */
427 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200428
429 /* remove trailing tabs and spaces */
430 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
431 --(*word_len);
432 }
433
434 /* start indentation */
435 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200436 }
437
438 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200439 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
440
441 /* maintain line number */
442 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200443
444 /* reset context indentation counter for possible string after this one */
445 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200446 break;
447 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200448 /* first non-whitespace character, stop eating indentation */
449 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200450
451 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200452 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 +0200453 break;
454 }
455 break;
456 case 3:
457 /* string encoded characters */
458 switch (**data) {
459 case 'n':
460 c = "\n";
461 break;
462 case 't':
463 c = "\t";
464 break;
465 case '\"':
466 c = *data;
467 break;
468 case '\\':
469 c = *data;
470 break;
471 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200472 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200473 return LY_EVALID;
474 }
475
476 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200477 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 +0200478
479 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200480 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200481 break;
482 case 4:
483 switch (**data) {
484 case '+':
485 /* string continues */
486 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200487 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200488 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200489 case '\n':
490 ++ctx->line;
491 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200492 case ' ':
493 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200494 /* just skip */
495 break;
496 default:
497 /* string is finished */
498 goto string_end;
499 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200500 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200501 break;
502 case 5:
503 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200504 case '\n':
505 ++ctx->line;
506 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200507 case ' ':
508 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200509 /* skip */
510 break;
511 case '\'':
512 string = 1;
513 break;
514 case '\"':
515 string = 2;
516 break;
517 default:
518 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200519 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200520 return LY_EVALID;
521 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200522 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200523 break;
524 default:
525 return LY_EINT;
526 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200527 }
528
529string_end:
530 return LY_SUCCESS;
531}
532
Michal Vaskoea5abea2018-09-18 13:10:54 +0200533/**
534 * @brief Get another YANG string from the raw data.
535 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200536 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200537 * @param[in,out] data Data to read from, always moved to currently handled character.
538 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200539 * @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 +0200540 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
541 * set to NULL. Otherwise equal to \p word_p.
542 * @param[out] word_len Length of the read string.
543 *
544 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200545 */
546static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200547get_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 +0200548{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200549 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200550 LY_ERR ret;
551
552 /* word buffer - dynamically allocated */
553 *word_b = NULL;
554
555 /* word pointer - just a pointer to data */
556 *word_p = NULL;
557
558 *word_len = 0;
559 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200560 switch (**data) {
561 case '\'':
562 case '\"':
563 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200564 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
565 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
566 "unquoted string character, optsep, semicolon or opening brace");
567 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200568 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200569 ret = read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200570 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200571 goto str_end;
572 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200573 if ((*data)[1] == '/') {
574 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200575 MOVE_INPUT(ctx, data, 2);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200576 ret = skip_comment(ctx, data, 1);
577 } else if ((*data)[1] == '*') {
578 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200579 MOVE_INPUT(ctx, data, 2);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200580 ret = skip_comment(ctx, data, 2);
581 } else {
582 /* not a comment after all */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200583 ret = buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0);
584 }
585 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200586 break;
587 case ' ':
588 if (*word_len) {
589 /* word is finished */
590 goto str_end;
591 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200592 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200593 break;
594 case '\t':
595 if (*word_len) {
596 /* word is finished */
597 goto str_end;
598 }
599 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200600 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200601
602 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200603 break;
604 case '\n':
605 if (*word_len) {
606 /* word is finished */
607 goto str_end;
608 }
609 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200610 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200611
612 /* track line numbers */
613 ++ctx->line;
614
615 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200616 break;
617 case ';':
618 case '{':
619 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
620 /* word is finished */
621 goto str_end;
622 }
623
Radek Krejci44ceedc2018-10-02 15:54:31 +0200624 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200625 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200626 case '}':
627 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
628 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
629 "unquoted string character, optsep, semicolon or opening brace");
630 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200631 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200632 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 +0200633 break;
634 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200635 }
636
637str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200638 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200639 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200640 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
641 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
642 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200643 *word_p = *word_b;
644 }
645
646 return LY_SUCCESS;
647}
648
Michal Vaskoea5abea2018-09-18 13:10:54 +0200649/**
650 * @brief Get another YANG keyword from the raw data.
651 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200652 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200653 * @param[in,out] data Data to read from, always moved to currently handled character.
654 * @param[out] kw YANG keyword read.
655 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
656 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
657 *
658 * @return LY_ERR values.
659 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200660static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200661get_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 +0200662{
663 LY_ERR ret;
664 int prefix;
665 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200666 unsigned int c;
667 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200668
669 if (word_p) {
670 *word_p = NULL;
671 *word_len = 0;
672 }
673
674 /* first skip "optsep", comments */
675 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200676 switch (**data) {
677 case '/':
678 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200679 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200680 MOVE_INPUT(ctx, data, 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200681 ret = skip_comment(ctx, data, 1);
682 if (ret) {
683 return ret;
684 }
Radek Krejcidcc7b322018-10-11 14:24:02 +0200685 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200686 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200687 MOVE_INPUT(ctx, data, 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200688 ret = skip_comment(ctx, data, 2);
689 if (ret) {
690 return ret;
691 }
692 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200693 /* error - not a comment after all, keyword cannot start with slash */
694 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
695 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200696 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200697 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200698 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200699 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200700 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200701 ctx->indent = 0;
702 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200703 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200704 /* skip whitespaces (optsep) */
705 ++ctx->indent;
706 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200707 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200708 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200709 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200710 break;
711 default:
712 /* either a keyword start or an invalid character */
713 goto keyword_start;
714 }
715
716 ++(*data);
717 }
718
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200719#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
720#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
721#define IF_KW_PREFIX_END }
722
Michal Vasko7fbc8162018-09-17 10:35:16 +0200723keyword_start:
724 word_start = *data;
725 *kw = YANG_NONE;
726
727 /* read the keyword itself */
728 switch (**data) {
729 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200730 MOVE_INPUT(ctx, data, 1);
731 IF_KW("rgument", 7, YANG_ARGUMENT)
732 else IF_KW("ugment", 6, YANG_AUGMENT)
733 else IF_KW("ction", 5, YANG_ACTION)
734 else IF_KW_PREFIX("ny", 2)
735 IF_KW("data", 4, YANG_ANYDATA)
736 else IF_KW("xml", 3, YANG_ANYXML)
737 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200738 break;
739 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200740 MOVE_INPUT(ctx, data, 1);
741 IF_KW("ase", 3, YANG_BASE)
742 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
743 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200744 break;
745 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200746 MOVE_INPUT(ctx, data, 1);
747 IF_KW("ase", 3, YANG_CASE)
748 else IF_KW("hoice", 5, YANG_CHOICE)
749 else IF_KW_PREFIX("on", 2)
750 IF_KW("fig", 3, YANG_CONFIG)
751 else IF_KW_PREFIX("ta", 2)
752 IF_KW("ct", 2, YANG_CONTACT)
753 else IF_KW("iner", 4, YANG_CONTAINER)
754 IF_KW_PREFIX_END
755 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200756 break;
757 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200758 MOVE_INPUT(ctx, data, 1);
759 IF_KW_PREFIX("e", 1)
760 IF_KW("fault", 5, YANG_DEFAULT)
761 else IF_KW("scription", 9, YANG_DESCRIPTION)
762 else IF_KW_PREFIX("viat", 4)
763 IF_KW("e", 1, YANG_DEVIATE)
764 else IF_KW("ion", 3, YANG_DEVIATION)
765 IF_KW_PREFIX_END
766 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200767 break;
768 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200769 MOVE_INPUT(ctx, data, 1);
770 IF_KW("num", 3, YANG_ENUM)
771 else IF_KW_PREFIX("rror-", 5)
772 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
773 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
774 IF_KW_PREFIX_END
775 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200776 break;
777 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200778 MOVE_INPUT(ctx, data, 1);
779 IF_KW("eature", 6, YANG_FEATURE)
780 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200781 break;
782 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200783 MOVE_INPUT(ctx, data, 1);
784 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200785 break;
786 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200787 MOVE_INPUT(ctx, data, 1);
788 IF_KW("dentity", 7, YANG_IDENTITY)
789 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
790 else IF_KW("mport", 5, YANG_IMPORT)
791 else IF_KW_PREFIX("n", 1)
792 IF_KW("clude", 5, YANG_INCLUDE)
793 else IF_KW("put", 3, YANG_INPUT)
794 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200795 break;
796 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200797 MOVE_INPUT(ctx, data, 1);
798 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200799 break;
800 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200801 MOVE_INPUT(ctx, data, 1);
802 IF_KW_PREFIX("e", 1)
803 IF_KW("af-list", 7, YANG_LEAF_LIST)
804 else IF_KW("af", 2, YANG_LEAF)
805 else IF_KW("ngth", 4, YANG_LENGTH)
806 IF_KW_PREFIX_END
807 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200808 break;
809 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200810 MOVE_INPUT(ctx, data, 1);
811 IF_KW_PREFIX("a", 1)
812 IF_KW("ndatory", 7, YANG_MANDATORY)
813 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
814 IF_KW_PREFIX_END
815 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
816 else IF_KW("ust", 3, YANG_MUST)
817 else IF_KW_PREFIX("od", 2)
818 IF_KW("ule", 3, YANG_MODULE)
819 else IF_KW("ifier", 5, YANG_MODIFIER)
820 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200821 break;
822 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200823 MOVE_INPUT(ctx, data, 1);
824 IF_KW("amespace", 8, YANG_NAMESPACE)
825 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200826 break;
827 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200828 MOVE_INPUT(ctx, data, 1);
829 IF_KW_PREFIX("r", 1)
830 IF_KW("dered-by", 8, YANG_ORDERED_BY)
831 else IF_KW("ganization", 10, YANG_ORGANIZATION)
832 IF_KW_PREFIX_END
833 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200834 break;
835 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200836 MOVE_INPUT(ctx, data, 1);
837 IF_KW("ath", 3, YANG_PATH)
838 else IF_KW("attern", 6, YANG_PATTERN)
839 else IF_KW("osition", 7, YANG_POSITION)
840 else IF_KW_PREFIX("re", 2)
841 IF_KW("fix", 3, YANG_PREFIX)
842 else IF_KW("sence", 5, YANG_PRESENCE)
843 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200844 break;
845 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200846 MOVE_INPUT(ctx, data, 1);
847 IF_KW("ange", 4, YANG_RANGE)
848 else IF_KW_PREFIX("e", 1)
849 IF_KW_PREFIX("f", 1)
850 IF_KW("erence", 6, YANG_REFERENCE)
851 else IF_KW("ine", 3, YANG_REFINE)
852 IF_KW_PREFIX_END
853 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
854 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
855 else IF_KW("vision", 6, YANG_REVISION)
856 IF_KW_PREFIX_END
857 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200858 break;
859 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200860 MOVE_INPUT(ctx, data, 1);
861 IF_KW("tatus", 5, YANG_STATUS)
862 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200863 break;
864 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200865 MOVE_INPUT(ctx, data, 1);
866 IF_KW("ypedef", 6, YANG_TYPEDEF)
867 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200868 break;
869 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200870 MOVE_INPUT(ctx, data, 1);
871 IF_KW_PREFIX("ni", 2)
872 IF_KW("que", 3, YANG_UNIQUE)
873 else IF_KW("ts", 2, YANG_UNITS)
874 IF_KW_PREFIX_END
875 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200876 break;
877 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200878 MOVE_INPUT(ctx, data, 1);
879 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200880 break;
881 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200882 MOVE_INPUT(ctx, data, 1);
883 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200884 break;
885 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200886 MOVE_INPUT(ctx, data, 1);
887 IF_KW("ang-version", 11, YANG_YANG_VERSION)
888 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200889 break;
890 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200891 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200892 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200893 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200894 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200895 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200896 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200897 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200898 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200899 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200900 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200901 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200902 default:
903 break;
904 }
905
906 if (*kw != YANG_NONE) {
907 /* make sure we have the whole keyword */
908 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200909 case '\n':
910 ++ctx->line;
911 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200912 case ' ':
913 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200914 /* mandatory "sep" */
915 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200916 case ':':
917 /* keyword is not actually a keyword, but prefix of an extension.
918 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
919 * and we will be checking the keyword (extension instance) itself */
920 prefix = 1;
921 MOVE_INPUT(ctx, data, 1);
922 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200923 case '{':
924 /* allowed only for input and output statements which can be without arguments */
925 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
926 break;
927 }
928 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200929 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200930 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200931 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
932 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200933 return LY_EVALID;
934 }
935 } else {
936 /* still can be an extension */
937 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200938extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200939 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200940 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
941 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200942 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200943 /* check character validity */
944 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200945 }
946 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200947 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200948 return LY_EVALID;
949 }
950
951 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200952 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200953 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200954 return LY_EVALID;
955 }
956
957 *kw = YANG_CUSTOM;
958 }
Radek Krejci626df482018-10-11 15:06:31 +0200959success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200960 if (word_p) {
961 *word_p = (char *)word_start;
962 *word_len = *data - word_start;
963 }
964
965 return LY_SUCCESS;
966}
967
Michal Vaskoea5abea2018-09-18 13:10:54 +0200968/**
969 * @brief Parse extension instance substatements.
970 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200971 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200972 * @param[in,out] data Data to read from, always moved to currently handled character.
973 * @param[in] word Extension instance substatement name (keyword).
974 * @param[in] word_len Extension instance substatement name length.
975 * @param[in,out] child Children of this extension instance to add to.
976 *
977 * @return LY_ERR values.
978 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200979static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200980parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200981 struct lysp_stmt **child)
982{
983 char *buf;
984 LY_ERR ret = 0;
985 enum yang_keyword kw;
986 struct lysp_stmt *stmt, *par_child;
987
988 stmt = calloc(1, sizeof *stmt);
989 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
990
Radek Krejci44ceedc2018-10-02 15:54:31 +0200991 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200992
993 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200994 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +0200995 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200996
Radek Krejci0ae092d2018-09-20 16:43:19 +0200997 if (word) {
998 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200999 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001000 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001001 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001002 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001003 }
1004
1005 /* insert into parent statements */
1006 if (!*child) {
1007 *child = stmt;
1008 } else {
1009 for (par_child = *child; par_child->next; par_child = par_child->next);
1010 par_child->next = stmt;
1011 }
1012
1013 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001014 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001015
1016 ret = parse_ext_substmt(ctx, data, word, word_len, &stmt->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001017 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001018 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001019 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001020
1021 return ret;
1022}
1023
Michal Vaskoea5abea2018-09-18 13:10:54 +02001024/**
1025 * @brief Parse extension instance.
1026 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001027 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001028 * @param[in,out] data Data to read from, always moved to currently handled character.
1029 * @param[in] ext_name Extension instance substatement name (keyword).
1030 * @param[in] ext_name_len Extension instance substatement name length.
1031 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1032 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1033 * @param[in,out] exts Extension instances to add to.
1034 *
1035 * @return LY_ERR values.
1036 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001037static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001038parse_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 +02001039 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1040{
1041 LY_ERR ret = 0;
1042 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001043 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001044 struct lysp_ext_instance *e;
1045 enum yang_keyword kw;
1046
Radek Krejci2c4e7172018-10-19 15:56:26 +02001047 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001048
1049 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001050 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001051 e->insubstmt = insubstmt;
1052 e->insubstmt_index = insubstmt_index;
1053
1054 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001055 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001056 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001057
Radek Krejci0ae092d2018-09-20 16:43:19 +02001058 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001059 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001060 }
1061
1062 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001063 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001064
1065 ret = parse_ext_substmt(ctx, data, word, word_len, &e->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001066 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001067 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001068 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001069
1070 return ret;
1071}
1072
Michal Vaskoea5abea2018-09-18 13:10:54 +02001073/**
1074 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1075 * description, etc...
1076 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001077 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001078 * @param[in,out] data Data to read from, always moved to currently handled character.
1079 * @param[in] substmt Type of this substatement.
1080 * @param[in] substmt_index Index of this substatement.
1081 * @param[in,out] value Place to store the parsed value.
1082 * @param[in] arg Type of the YANG keyword argument (of the value).
1083 * @param[in,out] exts Extension instances to add to.
1084 *
1085 * @return LY_ERR values.
1086 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001087static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001088parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001089 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1090{
1091 LY_ERR ret = 0;
1092 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001093 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001094 enum yang_keyword kw;
1095
1096 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001097 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001098 return LY_EVALID;
1099 }
1100
1101 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001102 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001103 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001104
1105 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001106 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001107
1108 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001109 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001110
1111 switch (kw) {
1112 case YANG_CUSTOM:
1113 ret = parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001114 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001115 break;
1116 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001117 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001118 return LY_EVALID;
1119 }
1120 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001121 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001122
1123 return ret;
1124}
1125
Michal Vaskoea5abea2018-09-18 13:10:54 +02001126/**
1127 * @brief Parse the yang-version statement.
1128 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001129 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001130 * @param[in,out] data Data to read from, always moved to currently handled character.
1131 * @param[in] mod Module to store the parsed information in.
1132 *
1133 * @return LY_ERR values.
1134 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001135static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001136parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001137{
1138 LY_ERR ret = 0;
1139 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001140 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001141 enum yang_keyword kw;
1142
1143 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001144 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001145 return LY_EVALID;
1146 }
1147
1148 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001149 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001150 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001151
1152 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1153 mod->version = LYS_VERSION_1_0;
1154 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1155 mod->version = LYS_VERSION_1_1;
1156 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001157 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001158 free(buf);
1159 return LY_EVALID;
1160 }
1161 free(buf);
1162
1163 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001164 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001165
1166 switch (kw) {
1167 case YANG_CUSTOM:
1168 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001169 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001170 break;
1171 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001172 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001173 return LY_EVALID;
1174 }
1175 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001176 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001177
1178 return ret;
1179}
1180
Michal Vaskoea5abea2018-09-18 13:10:54 +02001181/**
1182 * @brief Parse the belongs-to statement.
1183 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001184 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001185 * @param[in,out] data Data to read from, always moved to currently handled character.
1186 * @param[in,out] belongsto Place to store the parsed value.
1187 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1188 * @param[in,out] exts Extension instances to add to.
1189 *
1190 * @return LY_ERR values.
1191 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001192static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001193parse_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 +02001194{
1195 LY_ERR ret = 0;
1196 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001197 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001198 enum yang_keyword kw;
1199
1200 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001201 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001202 return LY_EVALID;
1203 }
1204
1205 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001206 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001207 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001208
Radek Krejci44ceedc2018-10-02 15:54:31 +02001209 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001210 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001211 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001212
1213 switch (kw) {
1214 case YANG_PREFIX:
1215 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts);
1216 break;
1217 case YANG_CUSTOM:
1218 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts);
1219 break;
1220 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001221 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001222 return LY_EVALID;
1223 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001224 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001225 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001226 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001227
1228 /* mandatory substatements */
1229 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001230 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001231 return LY_EVALID;
1232 }
1233
1234 return ret;
1235}
1236
Michal Vaskoea5abea2018-09-18 13:10:54 +02001237/**
1238 * @brief Parse the revision-date statement.
1239 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001240 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001241 * @param[in,out] data Data to read from, always moved to currently handled character.
1242 * @param[in,out] rev Array to store the parsed value in.
1243 * @param[in,out] exts Extension instances to add to.
1244 *
1245 * @return LY_ERR values.
1246 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001247static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001248parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001249{
1250 LY_ERR ret = 0;
1251 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001252 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001253 enum yang_keyword kw;
1254
1255 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001256 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001257 return LY_EVALID;
1258 }
1259
1260 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001261 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001262 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001263
1264 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001265 if (lysp_check_date(ctx->ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001266 free(buf);
1267 return LY_EVALID;
1268 }
1269
1270 /* store value and spend buf if allocated */
1271 strncpy(rev, word, word_len);
1272 free(buf);
1273
1274 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001275 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001276
1277 switch (kw) {
1278 case YANG_CUSTOM:
1279 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001280 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001281 break;
1282 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001283 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001284 return LY_EVALID;
1285 }
1286 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001287 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001288
1289 return ret;
1290}
1291
Michal Vaskoea5abea2018-09-18 13:10:54 +02001292/**
1293 * @brief Parse the include statement.
1294 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001295 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001296 * @param[in,out] data Data to read from, always moved to currently handled character.
1297 * @param[in,out] includes Parsed includes to add to.
1298 *
1299 * @return LY_ERR values.
1300 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001301static LY_ERR
Radek Krejcid33273d2018-10-25 14:55:52 +02001302parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001303{
Radek Krejcid33273d2018-10-25 14:55:52 +02001304 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001305 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001306 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001307 enum yang_keyword kw;
1308 struct lysp_include *inc;
1309
Radek Krejcid33273d2018-10-25 14:55:52 +02001310 LY_ARRAY_NEW_RET(ctx->ctx, mod->includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001311
1312 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001313 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001314 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001315
Radek Krejci086c7132018-10-26 15:29:04 +02001316 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1317
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001318 /* submodules share the namespace with the module names, so there must not be
1319 * a module of the same name in the context, no need for revision matching */
1320 if (!strcmp(ctx->mod->name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
1321 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1322 return LY_EVALID;
1323 }
1324
Radek Krejci086c7132018-10-26 15:29:04 +02001325 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001326 switch (kw) {
1327 case YANG_DESCRIPTION:
1328 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts);
1329 break;
1330 case YANG_REFERENCE:
1331 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts);
1332 break;
1333 case YANG_REVISION_DATE:
1334 ret = parse_revisiondate(ctx, data, inc->rev, &inc->exts);
1335 break;
1336 case YANG_CUSTOM:
1337 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts);
1338 break;
1339 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001340 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001341 return LY_EVALID;
1342 }
Radek Krejci086c7132018-10-26 15:29:04 +02001343 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001344 }
Radek Krejci086c7132018-10-26 15:29:04 +02001345 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001346
1347 return ret;
1348}
1349
Michal Vaskoea5abea2018-09-18 13:10:54 +02001350/**
1351 * @brief Parse the import statement.
1352 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001353 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001354 * @param[in,out] data Data to read from, always moved to currently handled character.
1355 * @param[in,out] imports Parsed imports to add to.
1356 *
1357 * @return LY_ERR values.
1358 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001359static LY_ERR
Radek Krejci70853c52018-10-15 14:46:16 +02001360parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *module)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001361{
1362 LY_ERR ret = 0;
1363 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001364 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001365 enum yang_keyword kw;
1366 struct lysp_import *imp;
1367
Radek Krejci2c4e7172018-10-19 15:56:26 +02001368 LY_ARRAY_NEW_RET(ctx->ctx, module->imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001369
1370 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001371 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001372 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001373
Radek Krejci44ceedc2018-10-02 15:54:31 +02001374 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001375
Radek Krejci086c7132018-10-26 15:29:04 +02001376 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001377 switch (kw) {
1378 case YANG_PREFIX:
1379 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts);
Radek Krejci70853c52018-10-15 14:46:16 +02001380 LY_CHECK_RET(lysp_check_prefix(ctx, module, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001381 break;
1382 case YANG_DESCRIPTION:
1383 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts);
1384 break;
1385 case YANG_REFERENCE:
1386 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts);
1387 break;
1388 case YANG_REVISION_DATE:
1389 ret = parse_revisiondate(ctx, data, imp->rev, &imp->exts);
1390 break;
1391 case YANG_CUSTOM:
1392 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts);
1393 break;
1394 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001395 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001396 return LY_EVALID;
1397 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001398 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001399 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001400 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001401
1402 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001403 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001404
1405 return ret;
1406}
1407
Michal Vaskoea5abea2018-09-18 13:10:54 +02001408/**
1409 * @brief Parse the revision statement.
1410 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001411 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001412 * @param[in,out] data Data to read from, always moved to currently handled character.
1413 * @param[in,out] revs Parsed revisions to add to.
1414 *
1415 * @return LY_ERR values.
1416 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001417static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001418parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001419{
1420 LY_ERR ret = 0;
1421 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001422 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001423 enum yang_keyword kw;
1424 struct lysp_revision *rev;
1425
Radek Krejci2c4e7172018-10-19 15:56:26 +02001426 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001427
1428 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001429 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001430 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001431
1432 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001433 if (lysp_check_date(ctx->ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001434 return LY_EVALID;
1435 }
1436
Radek Krejcib7db73a2018-10-24 14:18:40 +02001437 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438 free(buf);
1439
1440 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001441 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001442
1443 switch (kw) {
1444 case YANG_DESCRIPTION:
1445 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts);
1446 break;
1447 case YANG_REFERENCE:
1448 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts);
1449 break;
1450 case YANG_CUSTOM:
1451 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts);
1452 break;
1453 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001454 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001455 return LY_EVALID;
1456 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001457 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001458 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001459 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001460
1461 return ret;
1462}
1463
Michal Vaskoea5abea2018-09-18 13:10:54 +02001464/**
1465 * @brief Parse a generic text field that can have more instances such as base.
1466 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001467 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001468 * @param[in,out] data Data to read from, always moved to currently handled character.
1469 * @param[in] substmt Type of this substatement.
1470 * @param[in,out] texts Parsed values to add to.
1471 * @param[in] arg Type of the expected argument.
1472 * @param[in,out] exts Extension instances to add to.
1473 *
1474 * @return LY_ERR values.
1475 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001476static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001477parse_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 +02001478 struct lysp_ext_instance **exts)
1479{
1480 LY_ERR ret = 0;
1481 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001482 const char **item;
1483 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001484 enum yang_keyword kw;
1485
1486 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001487 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001488
1489 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001490 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001491 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001492
Radek Krejci151a5b72018-10-19 14:21:44 +02001493 INSERT_WORD(ctx, buf, *item, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001494 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001495 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001496
1497 switch (kw) {
1498 case YANG_CUSTOM:
Radek Krejci151a5b72018-10-19 14:21:44 +02001499 ret = parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001500 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001501 break;
1502 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001503 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001504 return LY_EVALID;
1505 }
1506 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001507 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001508
1509 return ret;
1510}
1511
Michal Vaskoea5abea2018-09-18 13:10:54 +02001512/**
1513 * @brief Parse the config statement.
1514 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001515 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001516 * @param[in,out] data Data to read from, always moved to currently handled character.
1517 * @param[in,out] flags Flags to add to.
1518 * @param[in,out] exts Extension instances to add to.
1519 *
1520 * @return LY_ERR values.
1521 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001522static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001523parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001524{
1525 LY_ERR ret = 0;
1526 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001527 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001528 enum yang_keyword kw;
1529
1530 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001531 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001532 return LY_EVALID;
1533 }
1534
1535 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001536 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001537 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001538
1539 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1540 *flags |= LYS_CONFIG_W;
1541 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1542 *flags |= LYS_CONFIG_R;
1543 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001544 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001545 free(buf);
1546 return LY_EVALID;
1547 }
1548 free(buf);
1549
1550 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001551 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001552
1553 switch (kw) {
1554 case YANG_CUSTOM:
1555 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001556 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001557 break;
1558 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001559 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001560 return LY_EVALID;
1561 }
1562 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001563 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001564
1565 return ret;
1566}
1567
Michal Vaskoea5abea2018-09-18 13:10:54 +02001568/**
1569 * @brief Parse the mandatory statement.
1570 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001571 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001572 * @param[in,out] data Data to read from, always moved to currently handled character.
1573 * @param[in,out] flags Flags to add to.
1574 * @param[in,out] exts Extension instances to add to.
1575 *
1576 * @return LY_ERR values.
1577 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001578static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001579parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001580{
1581 LY_ERR ret = 0;
1582 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001583 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001584 enum yang_keyword kw;
1585
1586 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001587 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001588 return LY_EVALID;
1589 }
1590
1591 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001592 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001593 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001594
1595 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1596 *flags |= LYS_MAND_TRUE;
1597 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1598 *flags |= LYS_MAND_FALSE;
1599 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001600 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001601 free(buf);
1602 return LY_EVALID;
1603 }
1604 free(buf);
1605
1606 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001607 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001608
1609 switch (kw) {
1610 case YANG_CUSTOM:
1611 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001612 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001613 break;
1614 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001615 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001616 return LY_EVALID;
1617 }
1618 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001619 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001620
1621 return ret;
1622}
1623
Michal Vaskoea5abea2018-09-18 13:10:54 +02001624/**
1625 * @brief Parse a restriction such as range or length.
1626 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001627 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001628 * @param[in,out] data Data to read from, always moved to currently handled character.
1629 * @param[in] restr_kw Type of this particular restriction.
1630 * @param[in,out] exts Extension instances to add to.
1631 *
1632 * @return LY_ERR values.
1633 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001634static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001635parse_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 +02001636{
1637 LY_ERR ret = 0;
1638 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001639 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001640 enum yang_keyword kw;
1641
1642 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001643 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001644 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001645
Radek Krejci44ceedc2018-10-02 15:54:31 +02001646 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001647 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001648 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001649
1650 switch (kw) {
1651 case YANG_DESCRIPTION:
1652 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
1653 break;
1654 case YANG_REFERENCE:
1655 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
1656 break;
1657 case YANG_ERROR_APP_TAG:
1658 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
1659 break;
1660 case YANG_ERROR_MESSAGE:
1661 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
1662 break;
1663 case YANG_CUSTOM:
1664 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
1665 break;
1666 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001667 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001668 return LY_EVALID;
1669 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001670 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001671 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001672 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001673
1674 return ret;
1675}
1676
Michal Vaskoea5abea2018-09-18 13:10:54 +02001677/**
1678 * @brief Parse a restriction that can have more instances such as must.
1679 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001680 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001681 * @param[in,out] data Data to read from, always moved to currently handled character.
1682 * @param[in] restr_kw Type of this particular restriction.
1683 * @param[in,out] restrs Restrictions to add to.
1684 *
1685 * @return LY_ERR values.
1686 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001687static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001688parse_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 +02001689{
1690 struct lysp_restr *restr;
1691
Radek Krejci2c4e7172018-10-19 15:56:26 +02001692 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001693
1694 return parse_restr(ctx, data, restr_kw, restr);
1695}
1696
Michal Vaskoea5abea2018-09-18 13:10:54 +02001697/**
1698 * @brief Parse the status statement.
1699 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001700 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001701 * @param[in,out] data Data to read from, always moved to currently handled character.
1702 * @param[in,out] flags Flags to add to.
1703 * @param[in,out] exts Extension instances to add to.
1704 *
1705 * @return LY_ERR values.
1706 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001707static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001708parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001709{
1710 LY_ERR ret = 0;
1711 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001712 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001713 enum yang_keyword kw;
1714
1715 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001716 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001717 return LY_EVALID;
1718 }
1719
1720 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001721 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001722 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001723
1724 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1725 *flags |= LYS_STATUS_CURR;
1726 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1727 *flags |= LYS_STATUS_DEPRC;
1728 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1729 *flags |= LYS_STATUS_OBSLT;
1730 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001731 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001732 free(buf);
1733 return LY_EVALID;
1734 }
1735 free(buf);
1736
1737 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001738 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001739
1740 switch (kw) {
1741 case YANG_CUSTOM:
1742 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001743 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001744 break;
1745 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001746 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001747 return LY_EVALID;
1748 }
1749 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001750 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001751
1752 return ret;
1753}
1754
Michal Vaskoea5abea2018-09-18 13:10:54 +02001755/**
1756 * @brief Parse the when statement.
1757 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001758 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001759 * @param[in,out] data Data to read from, always moved to currently handled character.
1760 * @param[in,out] when_p When pointer to parse to.
1761 *
1762 * @return LY_ERR values.
1763 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001764static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001765parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001766{
1767 LY_ERR ret = 0;
1768 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001769 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001770 enum yang_keyword kw;
1771 struct lysp_when *when;
1772
1773 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001774 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001775 return LY_EVALID;
1776 }
1777
1778 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001779 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001780 *when_p = when;
1781
1782 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001783 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001784 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001785
Radek Krejci44ceedc2018-10-02 15:54:31 +02001786 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001787 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001788 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001789
1790 switch (kw) {
1791 case YANG_DESCRIPTION:
1792 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts);
1793 break;
1794 case YANG_REFERENCE:
1795 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts);
1796 break;
1797 case YANG_CUSTOM:
1798 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts);
1799 break;
1800 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001801 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001802 return LY_EVALID;
1803 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001804 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001805 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001806 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001807
1808 return ret;
1809}
1810
Michal Vaskoea5abea2018-09-18 13:10:54 +02001811/**
1812 * @brief Parse the anydata or anyxml statement.
1813 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001814 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001815 * @param[in,out] data Data to read from, always moved to currently handled character.
1816 * @param[in] kw Type of this particular keyword.
1817 * @param[in,out] siblings Siblings to add to.
1818 *
1819 * @return LY_ERR values.
1820 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001821static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001822parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001823{
1824 LY_ERR ret = 0;
1825 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001826 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001827 struct lysp_node *iter;
1828 struct lysp_node_anydata *any;
1829
1830 /* create structure */
1831 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001832 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
1834
1835 /* insert into siblings */
1836 if (!*siblings) {
1837 *siblings = (struct lysp_node *)any;
1838 } else {
1839 for (iter = *siblings; iter->next; iter = iter->next);
1840 iter->next = (struct lysp_node *)any;
1841 }
1842
1843 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001844 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001845 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001846
Radek Krejci44ceedc2018-10-02 15:54:31 +02001847 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001848
1849 /* parse substatements */
1850 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001851 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001852
1853 switch (kw) {
1854 case YANG_CONFIG:
1855 ret = parse_config(ctx, data, &any->flags, &any->exts);
1856 break;
1857 case YANG_DESCRIPTION:
1858 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts);
1859 break;
1860 case YANG_IF_FEATURE:
1861 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts);
1862 break;
1863 case YANG_MANDATORY:
1864 ret = parse_mandatory(ctx, data, &any->flags, &any->exts);
1865 break;
1866 case YANG_MUST:
1867 ret = parse_restrs(ctx, data, kw, &any->musts);
1868 break;
1869 case YANG_REFERENCE:
1870 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts);
1871 break;
1872 case YANG_STATUS:
1873 ret = parse_status(ctx, data, &any->flags, &any->exts);
1874 break;
1875 case YANG_WHEN:
1876 ret = parse_when(ctx, data, &any->when);
1877 break;
1878 case YANG_CUSTOM:
1879 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts);
1880 break;
1881 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001882 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001883 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001884 return LY_EVALID;
1885 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001886 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001887 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001888 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001889
1890 return ret;
1891}
1892
Michal Vaskoea5abea2018-09-18 13:10:54 +02001893/**
1894 * @brief Parse the value or position statement. Substatement of type enum statement.
1895 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001896 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001897 * @param[in,out] data Data to read from, always moved to currently handled character.
1898 * @param[in] val_kw Type of this particular keyword.
1899 * @param[in,out] value Value to write to.
1900 * @param[in,out] flags Flags to write to.
1901 * @param[in,out] exts Extension instances to add to.
1902 *
1903 * @return LY_ERR values.
1904 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001905static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001906parse_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 +02001907 struct lysp_ext_instance **exts)
1908{
1909 LY_ERR ret = 0;
1910 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001911 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001912 long int num;
1913 unsigned long int unum;
1914 enum yang_keyword kw;
1915
1916 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001917 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001918 return LY_EVALID;
1919 }
1920 *flags |= LYS_SET_VALUE;
1921
1922 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001923 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001924 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001925
1926 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 +02001927 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001928 free(buf);
1929 return LY_EVALID;
1930 }
1931
1932 errno = 0;
1933 if (val_kw == YANG_VALUE) {
1934 num = strtol(word, &ptr, 10);
1935 } else {
1936 unum = strtoul(word, &ptr, 10);
1937 }
1938 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001939 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001940 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001941 free(buf);
1942 return LY_EVALID;
1943 }
1944 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001945 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001946 free(buf);
1947 return LY_EVALID;
1948 }
1949 if (val_kw == YANG_VALUE) {
1950 *value = num;
1951 } else {
1952 *value = unum;
1953 }
1954 free(buf);
1955
1956 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001957 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001958
1959 switch (kw) {
1960 case YANG_CUSTOM:
1961 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 +02001962 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001963 break;
1964 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001965 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001966 return LY_EVALID;
1967 }
1968 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001969 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001970
1971 return ret;
1972}
1973
Michal Vaskoea5abea2018-09-18 13:10:54 +02001974/**
1975 * @brief Parse the enum or bit statement. Substatement of type statement.
1976 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001977 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001978 * @param[in,out] data Data to read from, always moved to currently handled character.
1979 * @param[in] enum_kw Type of this particular keyword.
1980 * @param[in,out] enums Enums or bits to add to.
1981 *
1982 * @return LY_ERR values.
1983 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001984static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001985parse_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 +02001986{
1987 LY_ERR ret = 0;
1988 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001989 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001990 enum yang_keyword kw;
1991 struct lysp_type_enum *enm;
1992
Radek Krejci2c4e7172018-10-19 15:56:26 +02001993 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001994
1995 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001996 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001997 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001998
Radek Krejci44ceedc2018-10-02 15:54:31 +02001999 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002000 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002001 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002002
2003 switch (kw) {
2004 case YANG_DESCRIPTION:
2005 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts);
2006 break;
2007 case YANG_IF_FEATURE:
2008 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts);
2009 break;
2010 case YANG_REFERENCE:
2011 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts);
2012 break;
2013 case YANG_STATUS:
2014 ret = parse_status(ctx, data, &enm->flags, &enm->exts);
2015 break;
2016 case YANG_VALUE:
2017 case YANG_POSITION:
2018 ret = parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts);
2019 break;
2020 case YANG_CUSTOM:
2021 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts);
2022 break;
2023 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002024 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002025 return LY_EVALID;
2026 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002027 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002028 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002029 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002030
2031 return ret;
2032}
2033
Michal Vaskoea5abea2018-09-18 13:10:54 +02002034/**
2035 * @brief Parse the fraction-digits statement. Substatement of type statement.
2036 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002037 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002038 * @param[in,out] data Data to read from, always moved to currently handled character.
2039 * @param[in,out] fracdig Value to write to.
2040 * @param[in,out] exts Extension instances to add to.
2041 *
2042 * @return LY_ERR values.
2043 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002044static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002045parse_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 +02002046{
2047 LY_ERR ret = 0;
2048 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002049 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002050 unsigned long int num;
2051 enum yang_keyword kw;
2052
2053 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002054 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002055 return LY_EVALID;
2056 }
2057
2058 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002059 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002060 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002061
2062 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002063 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002064 free(buf);
2065 return LY_EVALID;
2066 }
2067
2068 errno = 0;
2069 num = strtoul(word, &ptr, 10);
2070 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002071 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002072 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002073 free(buf);
2074 return LY_EVALID;
2075 }
2076 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002077 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002078 free(buf);
2079 return LY_EVALID;
2080 }
2081 *fracdig = num;
2082 free(buf);
2083
2084 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002085 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002086
2087 switch (kw) {
2088 case YANG_CUSTOM:
2089 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002090 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002091 break;
2092 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002093 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002094 return LY_EVALID;
2095 }
2096 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002097 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002098
2099 return ret;
2100}
2101
Michal Vaskoea5abea2018-09-18 13:10:54 +02002102/**
2103 * @brief Parse the require-instance statement. Substatement of type statement.
2104 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002105 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002106 * @param[in,out] data Data to read from, always moved to currently handled character.
2107 * @param[in,out] reqinst Value to write to.
2108 * @param[in,out] flags Flags to write to.
2109 * @param[in,out] exts Extension instances to add to.
2110 *
2111 * @return LY_ERR values.
2112 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002113static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002114parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002115 struct lysp_ext_instance **exts)
2116{
2117 LY_ERR ret = 0;
2118 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002119 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002120 enum yang_keyword kw;
2121
2122 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002123 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002124 return LY_EVALID;
2125 }
2126 *flags |= LYS_SET_REQINST;
2127
2128 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002129 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002130 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002131
2132 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2133 *reqinst = 1;
2134 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002135 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002136 free(buf);
2137 return LY_EVALID;
2138 }
2139 free(buf);
2140
2141 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002142 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002143
2144 switch (kw) {
2145 case YANG_CUSTOM:
2146 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002147 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002148 break;
2149 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002150 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002151 return LY_EVALID;
2152 }
2153 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002154 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002155
2156 return ret;
2157}
2158
Michal Vaskoea5abea2018-09-18 13:10:54 +02002159/**
2160 * @brief Parse the modifier statement. Substatement of type pattern statement.
2161 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002162 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002163 * @param[in,out] data Data to read from, always moved to currently handled character.
2164 * @param[in,out] pat Value to write to.
2165 * @param[in,out] exts Extension instances to add to.
2166 *
2167 * @return LY_ERR values.
2168 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002169static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002170parse_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 +02002171{
2172 LY_ERR ret = 0;
2173 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002174 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002175 enum yang_keyword kw;
2176
2177 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002178 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002179 return LY_EVALID;
2180 }
2181
2182 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002183 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002184 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002185
2186 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002187 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002188 free(buf);
2189 return LY_EVALID;
2190 }
2191 free(buf);
2192
2193 /* replace the value in the dictionary */
2194 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002195 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002196 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002197 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002198
2199 assert(buf[0] == 0x06);
2200 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002201 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002202
2203 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002204 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002205
2206 switch (kw) {
2207 case YANG_CUSTOM:
2208 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002209 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002210 break;
2211 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002212 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002213 return LY_EVALID;
2214 }
2215 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002216 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002217
2218 return ret;
2219}
2220
Michal Vaskoea5abea2018-09-18 13:10:54 +02002221/**
2222 * @brief Parse the pattern statement. Substatement of type statement.
2223 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002224 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002225 * @param[in,out] data Data to read from, always moved to currently handled character.
2226 * @param[in,out] patterns Restrictions to add to.
2227 *
2228 * @return LY_ERR values.
2229 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002230static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002231parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002232{
2233 LY_ERR ret = 0;
2234 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002235 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002236 enum yang_keyword kw;
2237 struct lysp_restr *restr;
2238
Radek Krejci2c4e7172018-10-19 15:56:26 +02002239 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002240
2241 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002242 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002243 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002244
2245 /* add special meaning first byte */
2246 if (buf) {
2247 buf = realloc(buf, word_len + 2);
2248 word = buf;
2249 } else {
2250 buf = malloc(word_len + 2);
2251 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002252 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002253 memmove(buf + 1, word, word_len);
2254 buf[0] = 0x06; /* pattern's default regular-match flag */
2255 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2256 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002257
2258 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002259 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002260
2261 switch (kw) {
2262 case YANG_DESCRIPTION:
2263 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
2264 break;
2265 case YANG_REFERENCE:
2266 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
2267 break;
2268 case YANG_ERROR_APP_TAG:
2269 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
2270 break;
2271 case YANG_ERROR_MESSAGE:
2272 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
2273 break;
2274 case YANG_MODIFIER:
2275 ret = parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts);
2276 break;
2277 case YANG_CUSTOM:
2278 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
2279 break;
2280 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002281 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002282 return LY_EVALID;
2283 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002284 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002285 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002286 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002287
2288 return ret;
2289}
2290
Michal Vaskoea5abea2018-09-18 13:10:54 +02002291/**
2292 * @brief Parse the type statement.
2293 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002294 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002295 * @param[in,out] data Data to read from, always moved to currently handled character.
2296 * @param[in,out] type Type to wrote to.
2297 *
2298 * @return LY_ERR values.
2299 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002300static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002301parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002302{
2303 LY_ERR ret = 0;
2304 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002305 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002306 enum yang_keyword kw;
2307 struct lysp_type *nest_type;
2308
2309 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002310 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002311 return LY_EVALID;
2312 }
2313
2314 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002315 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002316 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002317
Radek Krejci44ceedc2018-10-02 15:54:31 +02002318 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002319 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002320 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002321
2322 switch (kw) {
2323 case YANG_BASE:
2324 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts);
2325 break;
2326 case YANG_BIT:
2327 ret = parse_type_enum(ctx, data, kw, &type->bits);
2328 break;
2329 case YANG_ENUM:
2330 ret = parse_type_enum(ctx, data, kw, &type->enums);
2331 break;
2332 case YANG_FRACTION_DIGITS:
2333 ret = parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts);
2334 break;
2335 case YANG_LENGTH:
2336 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002337 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002338 return LY_EVALID;
2339 }
2340 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002341 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002342
2343 ret = parse_restr(ctx, data, kw, type->length);
2344 break;
2345 case YANG_PATH:
2346 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts);
2347 break;
2348 case YANG_PATTERN:
2349 ret = parse_type_pattern(ctx, data, &type->patterns);
2350 break;
2351 case YANG_RANGE:
2352 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002353 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002354 return LY_EVALID;
2355 }
2356 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002357 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002358
2359 ret = parse_restr(ctx, data, kw, type->range);
2360 break;
2361 case YANG_REQUIRE_INSTANCE:
2362 ret = parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts);
2363 break;
2364 case YANG_TYPE:
2365 {
Radek Krejci2c4e7172018-10-19 15:56:26 +02002366 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002367 }
2368 ret = parse_type(ctx, data, nest_type);
2369 break;
2370 case YANG_CUSTOM:
2371 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts);
2372 break;
2373 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002374 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002375 return LY_EVALID;
2376 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002377 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002378 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002379 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002380
2381 return ret;
2382}
2383
Michal Vaskoea5abea2018-09-18 13:10:54 +02002384/**
2385 * @brief Parse the leaf statement.
2386 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002387 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002388 * @param[in,out] data Data to read from, always moved to currently handled character.
2389 * @param[in,out] siblings Siblings to add to.
2390 *
2391 * @return LY_ERR values.
2392 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002393static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002394parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002395{
2396 LY_ERR ret = 0;
2397 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002398 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002399 enum yang_keyword kw;
2400 struct lysp_node *iter;
2401 struct lysp_node_leaf *leaf;
2402
2403 /* create structure */
2404 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002405 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002406 leaf->nodetype = LYS_LEAF;
2407
2408 /* insert into siblings */
2409 if (!*siblings) {
2410 *siblings = (struct lysp_node *)leaf;
2411 } else {
2412 for (iter = *siblings; iter->next; iter = iter->next);
2413 iter->next = (struct lysp_node *)leaf;
2414 }
2415
2416 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002417 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002418 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002419
Radek Krejci44ceedc2018-10-02 15:54:31 +02002420 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002421
2422 /* parse substatements */
2423 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002424 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002425
2426 switch (kw) {
2427 case YANG_CONFIG:
2428 ret = parse_config(ctx, data, &leaf->flags, &leaf->exts);
2429 break;
2430 case YANG_DEFAULT:
2431 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts);
2432 break;
2433 case YANG_DESCRIPTION:
2434 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts);
2435 break;
2436 case YANG_IF_FEATURE:
2437 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts);
2438 break;
2439 case YANG_MANDATORY:
2440 ret = parse_mandatory(ctx, data, &leaf->flags, &leaf->exts);
2441 break;
2442 case YANG_MUST:
2443 ret = parse_restrs(ctx, data, kw, &leaf->musts);
2444 break;
2445 case YANG_REFERENCE:
2446 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts);
2447 break;
2448 case YANG_STATUS:
2449 ret = parse_status(ctx, data, &leaf->flags, &leaf->exts);
2450 break;
2451 case YANG_TYPE:
2452 ret = parse_type(ctx, data, &leaf->type);
2453 break;
2454 case YANG_UNITS:
2455 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts);
2456 break;
2457 case YANG_WHEN:
2458 ret = parse_when(ctx, data, &leaf->when);
2459 break;
2460 case YANG_CUSTOM:
2461 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts);
2462 break;
2463 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002464 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002465 return LY_EVALID;
2466 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002467 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002468 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002469 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002470
2471 /* mandatory substatements */
2472 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002473 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002474 return LY_EVALID;
2475 }
2476
2477 return ret;
2478}
2479
Michal Vaskoea5abea2018-09-18 13:10:54 +02002480/**
2481 * @brief Parse the max-elements statement.
2482 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002483 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002484 * @param[in,out] data Data to read from, always moved to currently handled character.
2485 * @param[in,out] max Value to write to.
2486 * @param[in,out] flags Flags to write to.
2487 * @param[in,out] exts Extension instances to add to.
2488 *
2489 * @return LY_ERR values.
2490 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002491static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002492parse_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 +02002493{
2494 LY_ERR ret = 0;
2495 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002496 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002497 unsigned long int num;
2498 enum yang_keyword kw;
2499
2500 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002501 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002502 return LY_EVALID;
2503 }
2504 *flags |= LYS_SET_MAX;
2505
2506 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002507 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002508 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002509
2510 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002511 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002512 free(buf);
2513 return LY_EVALID;
2514 }
2515
2516 if (strncmp(word, "unbounded", word_len)) {
2517 errno = 0;
2518 num = strtoul(word, &ptr, 10);
2519 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002520 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002521 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002522 free(buf);
2523 return LY_EVALID;
2524 }
2525 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002526 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002527 free(buf);
2528 return LY_EVALID;
2529 }
2530
2531 *max = num;
2532 }
2533 free(buf);
2534
2535 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002536 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002537
2538 switch (kw) {
2539 case YANG_CUSTOM:
2540 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002541 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002542 break;
2543 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002544 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002545 return LY_EVALID;
2546 }
2547 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002548 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002549
2550 return ret;
2551}
2552
Michal Vaskoea5abea2018-09-18 13:10:54 +02002553/**
2554 * @brief Parse the min-elements statement.
2555 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002556 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002557 * @param[in,out] data Data to read from, always moved to currently handled character.
2558 * @param[in,out] min Value to write to.
2559 * @param[in,out] flags Flags to write to.
2560 * @param[in,out] exts Extension instances to add to.
2561 *
2562 * @return LY_ERR values.
2563 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002564static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002565parse_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 +02002566{
2567 LY_ERR ret = 0;
2568 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002569 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002570 unsigned long int num;
2571 enum yang_keyword kw;
2572
2573 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002574 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002575 return LY_EVALID;
2576 }
2577 *flags |= LYS_SET_MIN;
2578
2579 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002580 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002581 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002582
2583 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002584 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002585 free(buf);
2586 return LY_EVALID;
2587 }
2588
2589 errno = 0;
2590 num = strtoul(word, &ptr, 10);
2591 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002592 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002593 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002594 free(buf);
2595 return LY_EVALID;
2596 }
2597 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002598 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002599 free(buf);
2600 return LY_EVALID;
2601 }
2602 *min = num;
2603 free(buf);
2604
2605 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002606 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002607
2608 switch (kw) {
2609 case YANG_CUSTOM:
2610 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002611 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002612 break;
2613 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002614 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002615 return LY_EVALID;
2616 }
2617 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002618 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619
2620 return ret;
2621}
2622
Michal Vaskoea5abea2018-09-18 13:10:54 +02002623/**
2624 * @brief Parse the ordered-by statement.
2625 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002626 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002627 * @param[in,out] data Data to read from, always moved to currently handled character.
2628 * @param[in,out] flags Flags to write to.
2629 * @param[in,out] exts Extension instances to add to.
2630 *
2631 * @return LY_ERR values.
2632 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002633static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002634parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002635{
2636 LY_ERR ret = 0;
2637 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002638 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002639 enum yang_keyword kw;
2640
2641 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002642 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002643 return LY_EVALID;
2644 }
2645
2646 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002647 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002648 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002649
2650 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2651 *flags |= LYS_ORDBY_SYSTEM;
2652 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2653 *flags |= LYS_ORDBY_USER;
2654 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002655 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002656 free(buf);
2657 return LY_EVALID;
2658 }
2659 free(buf);
2660
2661 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002662 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002663
2664 switch (kw) {
2665 case YANG_CUSTOM:
2666 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002667 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002668 break;
2669 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002670 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671 return LY_EVALID;
2672 }
2673 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002674 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002675
2676 return ret;
2677}
2678
Michal Vaskoea5abea2018-09-18 13:10:54 +02002679/**
2680 * @brief Parse the leaf-list statement.
2681 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002682 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002683 * @param[in,out] data Data to read from, always moved to currently handled character.
2684 * @param[in,out] siblings Siblings to add to.
2685 *
2686 * @return LY_ERR values.
2687 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002688static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002689parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002690{
2691 LY_ERR ret = 0;
2692 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002693 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002694 enum yang_keyword kw;
2695 struct lysp_node *iter;
2696 struct lysp_node_leaflist *llist;
2697
2698 /* create structure */
2699 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002700 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002701 llist->nodetype = LYS_LEAFLIST;
2702
2703 /* insert into siblings */
2704 if (!*siblings) {
2705 *siblings = (struct lysp_node *)llist;
2706 } else {
2707 for (iter = *siblings; iter->next; iter = iter->next);
2708 iter->next = (struct lysp_node *)llist;
2709 }
2710
2711 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002712 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002713 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002714
Radek Krejci44ceedc2018-10-02 15:54:31 +02002715 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002716
2717 /* parse substatements */
2718 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002719 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002720
2721 switch (kw) {
2722 case YANG_CONFIG:
2723 ret = parse_config(ctx, data, &llist->flags, &llist->exts);
2724 break;
2725 case YANG_DEFAULT:
2726 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts);
2727 break;
2728 case YANG_DESCRIPTION:
2729 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts);
2730 break;
2731 case YANG_IF_FEATURE:
2732 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts);
2733 break;
2734 case YANG_MAX_ELEMENTS:
2735 ret = parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts);
2736 break;
2737 case YANG_MIN_ELEMENTS:
2738 ret = parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts);
2739 break;
2740 case YANG_MUST:
2741 ret = parse_restrs(ctx, data, kw, &llist->musts);
2742 break;
2743 case YANG_ORDERED_BY:
2744 ret = parse_orderedby(ctx, data, &llist->flags, &llist->exts);
2745 break;
2746 case YANG_REFERENCE:
2747 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts);
2748 break;
2749 case YANG_STATUS:
2750 ret = parse_status(ctx, data, &llist->flags, &llist->exts);
2751 break;
2752 case YANG_TYPE:
2753 ret = parse_type(ctx, data, &llist->type);
2754 break;
2755 case YANG_UNITS:
2756 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts);
2757 break;
2758 case YANG_WHEN:
2759 ret = parse_when(ctx, data, &llist->when);
2760 break;
2761 case YANG_CUSTOM:
2762 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts);
2763 break;
2764 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002765 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002766 return LY_EVALID;
2767 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002768 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002769 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002770 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002771
2772 /* mandatory substatements */
2773 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002774 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002775 return LY_EVALID;
2776 }
2777
2778 return ret;
2779}
2780
Michal Vaskoea5abea2018-09-18 13:10:54 +02002781/**
2782 * @brief Parse the refine statement.
2783 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002784 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002785 * @param[in,out] data Data to read from, always moved to currently handled character.
2786 * @param[in,out] refines Refines to add to.
2787 *
2788 * @return LY_ERR values.
2789 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002791parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002792{
2793 LY_ERR ret = 0;
2794 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002795 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 enum yang_keyword kw;
2797 struct lysp_refine *rf;
2798
Radek Krejci2c4e7172018-10-19 15:56:26 +02002799 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002800
2801 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002802 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002803 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002804
Radek Krejci44ceedc2018-10-02 15:54:31 +02002805 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002806 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002807 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002808
2809 switch (kw) {
2810 case YANG_CONFIG:
2811 ret = parse_config(ctx, data, &rf->flags, &rf->exts);
2812 break;
2813 case YANG_DEFAULT:
2814 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts);
2815 break;
2816 case YANG_DESCRIPTION:
2817 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts);
2818 break;
2819 case YANG_IF_FEATURE:
2820 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts);
2821 break;
2822 case YANG_MAX_ELEMENTS:
2823 ret = parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts);
2824 break;
2825 case YANG_MIN_ELEMENTS:
2826 ret = parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts);
2827 break;
2828 case YANG_MUST:
2829 ret = parse_restrs(ctx, data, kw, &rf->musts);
2830 break;
2831 case YANG_MANDATORY:
2832 ret = parse_mandatory(ctx, data, &rf->flags, &rf->exts);
2833 break;
2834 case YANG_REFERENCE:
2835 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts);
2836 break;
2837 case YANG_PRESENCE:
2838 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts);
2839 break;
2840 case YANG_CUSTOM:
2841 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts);
2842 break;
2843 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002844 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002845 return LY_EVALID;
2846 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002847 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002848 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002849 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002850
2851 return ret;
2852}
2853
Michal Vaskoea5abea2018-09-18 13:10:54 +02002854/**
2855 * @brief Parse the typedef statement.
2856 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002857 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002858 * @param[in,out] data Data to read from, always moved to currently handled character.
2859 * @param[in,out] typedefs Typedefs to add to.
2860 *
2861 * @return LY_ERR values.
2862 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002864parse_typedef(struct ly_parser_ctx *ctx, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002865{
2866 LY_ERR ret = 0;
2867 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002868 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002869 enum yang_keyword kw;
2870 struct lysp_tpdf *tpdf;
2871
Radek Krejci2c4e7172018-10-19 15:56:26 +02002872 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002873
2874 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002875 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002876 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002877
Radek Krejci44ceedc2018-10-02 15:54:31 +02002878 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002879
2880 /* parse substatements */
2881 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002882 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002883
2884 switch (kw) {
2885 case YANG_DEFAULT:
2886 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts);
2887 break;
2888 case YANG_DESCRIPTION:
2889 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts);
2890 break;
2891 case YANG_REFERENCE:
2892 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts);
2893 break;
2894 case YANG_STATUS:
2895 ret = parse_status(ctx, data, &tpdf->flags, &tpdf->exts);
2896 break;
2897 case YANG_TYPE:
2898 ret = parse_type(ctx, data, &tpdf->type);
2899 break;
2900 case YANG_UNITS:
2901 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts);
2902 break;
2903 case YANG_CUSTOM:
2904 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts);
2905 break;
2906 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002907 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002908 return LY_EVALID;
2909 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002910 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002911 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002912 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002913
2914 /* mandatory substatements */
2915 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002916 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002917 return LY_EVALID;
2918 }
2919
2920 return ret;
2921}
2922
Michal Vaskoea5abea2018-09-18 13:10:54 +02002923/**
2924 * @brief Parse the input or output statement.
2925 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002926 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002927 * @param[in,out] data Data to read from, always moved to currently handled character.
2928 * @param[in] kw Type of this particular keyword
2929 * @param[in,out] inout_p Input/output pointer to write to.
2930 *
2931 * @return LY_ERR values.
2932 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002933static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002934parse_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 +02002935{
2936 LY_ERR ret = 0;
2937 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002938 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002939 struct lysp_action_inout *inout;
2940
2941 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002942 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002943 return LY_EVALID;
2944 }
2945
2946 /* create structure */
2947 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002948 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002949 *inout_p = inout;
2950
2951 /* parse substatements */
2952 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002953 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002954
2955 switch (kw) {
2956 case YANG_ANYDATA:
2957 case YANG_ANYXML:
2958 ret = parse_any(ctx, data, kw, &inout->data);
2959 break;
2960 case YANG_CHOICE:
2961 ret = parse_choice(ctx, data, &inout->data);
2962 break;
2963 case YANG_CONTAINER:
2964 ret = parse_container(ctx, data, &inout->data);
2965 break;
2966 case YANG_LEAF:
2967 ret = parse_leaf(ctx, data, &inout->data);
2968 break;
2969 case YANG_LEAF_LIST:
2970 ret = parse_leaflist(ctx, data, &inout->data);
2971 break;
2972 case YANG_LIST:
2973 ret = parse_list(ctx, data, &inout->data);
2974 break;
2975 case YANG_USES:
2976 ret = parse_uses(ctx, data, &inout->data);
2977 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978 case YANG_TYPEDEF:
2979 ret = parse_typedef(ctx, data, &inout->typedefs);
2980 break;
2981 case YANG_MUST:
2982 ret = parse_restrs(ctx, data, kw, &inout->musts);
2983 break;
2984 case YANG_GROUPING:
2985 ret = parse_grouping(ctx, data, &inout->groupings);
2986 break;
2987 case YANG_CUSTOM:
2988 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts);
2989 break;
2990 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002991 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002992 return LY_EVALID;
2993 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002994 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002995 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002996 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002997
2998 return ret;
2999}
3000
Michal Vaskoea5abea2018-09-18 13:10:54 +02003001/**
3002 * @brief Parse the action statement.
3003 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003004 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003005 * @param[in,out] data Data to read from, always moved to currently handled character.
3006 * @param[in,out] actions Actions to add to.
3007 *
3008 * @return LY_ERR values.
3009 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003010static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003011parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003012{
3013 LY_ERR ret = 0;
3014 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003015 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003016 enum yang_keyword kw;
3017 struct lysp_action *act;
3018
Radek Krejci2c4e7172018-10-19 15:56:26 +02003019 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003020
3021 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003022 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003023 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003024
Radek Krejci44ceedc2018-10-02 15:54:31 +02003025 INSERT_WORD(ctx, buf, act->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003026 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003027 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003028
3029 switch (kw) {
3030 case YANG_DESCRIPTION:
3031 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts);
3032 break;
3033 case YANG_IF_FEATURE:
3034 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts);
3035 break;
3036 case YANG_REFERENCE:
3037 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts);
3038 break;
3039 case YANG_STATUS:
3040 ret = parse_status(ctx, data, &act->flags, &act->exts);
3041 break;
3042
3043 case YANG_INPUT:
3044 ret = parse_inout(ctx, data, kw, &act->input);
3045 break;
3046 case YANG_OUTPUT:
3047 ret = parse_inout(ctx, data, kw, &act->output);
3048 break;
3049
3050 case YANG_TYPEDEF:
3051 ret = parse_typedef(ctx, data, &act->typedefs);
3052 break;
3053 case YANG_GROUPING:
3054 ret = parse_grouping(ctx, data, &act->groupings);
3055 break;
3056 case YANG_CUSTOM:
3057 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts);
3058 break;
3059 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003060 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003061 return LY_EVALID;
3062 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003063 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003064 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003065 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003066
3067 return ret;
3068}
3069
Michal Vaskoea5abea2018-09-18 13:10:54 +02003070/**
3071 * @brief Parse the notification statement.
3072 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003073 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003074 * @param[in,out] data Data to read from, always moved to currently handled character.
3075 * @param[in,out] notifs Notifications to add to.
3076 *
3077 * @return LY_ERR values.
3078 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003080parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003081{
3082 LY_ERR ret = 0;
3083 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003084 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003085 enum yang_keyword kw;
3086 struct lysp_notif *notif;
3087
Radek Krejci2c4e7172018-10-19 15:56:26 +02003088 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003089
3090 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003091 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003092 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003093
Radek Krejci44ceedc2018-10-02 15:54:31 +02003094 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003095 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003096 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003097
3098 switch (kw) {
3099 case YANG_DESCRIPTION:
3100 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts);
3101 break;
3102 case YANG_IF_FEATURE:
3103 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts);
3104 break;
3105 case YANG_REFERENCE:
3106 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts);
3107 break;
3108 case YANG_STATUS:
3109 ret = parse_status(ctx, data, &notif->flags, &notif->exts);
3110 break;
3111
3112 case YANG_ANYDATA:
3113 case YANG_ANYXML:
3114 ret = parse_any(ctx, data, kw, &notif->data);
3115 break;
3116 case YANG_CHOICE:
3117 ret = parse_case(ctx, data, &notif->data);
3118 break;
3119 case YANG_CONTAINER:
3120 ret = parse_container(ctx, data, &notif->data);
3121 break;
3122 case YANG_LEAF:
3123 ret = parse_leaf(ctx, data, &notif->data);
3124 break;
3125 case YANG_LEAF_LIST:
3126 ret = parse_leaflist(ctx, data, &notif->data);
3127 break;
3128 case YANG_LIST:
3129 ret = parse_list(ctx, data, &notif->data);
3130 break;
3131 case YANG_USES:
3132 ret = parse_uses(ctx, data, &notif->data);
3133 break;
3134
3135 case YANG_MUST:
3136 ret = parse_restrs(ctx, data, kw, &notif->musts);
3137 break;
3138 case YANG_TYPEDEF:
3139 ret = parse_typedef(ctx, data, &notif->typedefs);
3140 break;
3141 case YANG_GROUPING:
3142 ret = parse_grouping(ctx, data, &notif->groupings);
3143 break;
3144 case YANG_CUSTOM:
3145 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts);
3146 break;
3147 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003148 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003149 return LY_EVALID;
3150 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003151 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003152 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003153 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003154
3155 return ret;
3156}
3157
Michal Vaskoea5abea2018-09-18 13:10:54 +02003158/**
3159 * @brief Parse the grouping statement.
3160 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003161 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003162 * @param[in,out] data Data to read from, always moved to currently handled character.
3163 * @param[in,out] groupings Groupings to add to.
3164 *
3165 * @return LY_ERR values.
3166 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003167static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003168parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003169{
3170 LY_ERR ret = 0;
3171 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003172 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003173 enum yang_keyword kw;
3174 struct lysp_grp *grp;
3175
Radek Krejci2c4e7172018-10-19 15:56:26 +02003176 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003177
3178 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003179 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003180 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003181
Radek Krejci44ceedc2018-10-02 15:54:31 +02003182 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003183
3184 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003185 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003186
3187 switch (kw) {
3188 case YANG_DESCRIPTION:
3189 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts);
3190 break;
3191 case YANG_REFERENCE:
3192 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts);
3193 break;
3194 case YANG_STATUS:
3195 ret = parse_status(ctx, data, &grp->flags, &grp->exts);
3196 break;
3197
3198 case YANG_ANYDATA:
3199 case YANG_ANYXML:
3200 ret = parse_any(ctx, data, kw, &grp->data);
3201 break;
3202 case YANG_CHOICE:
3203 ret = parse_choice(ctx, data, &grp->data);
3204 break;
3205 case YANG_CONTAINER:
3206 ret = parse_container(ctx, data, &grp->data);
3207 break;
3208 case YANG_LEAF:
3209 ret = parse_leaf(ctx, data, &grp->data);
3210 break;
3211 case YANG_LEAF_LIST:
3212 ret = parse_leaflist(ctx, data, &grp->data);
3213 break;
3214 case YANG_LIST:
3215 ret = parse_list(ctx, data, &grp->data);
3216 break;
3217 case YANG_USES:
3218 ret = parse_uses(ctx, data, &grp->data);
3219 break;
3220
3221 case YANG_TYPEDEF:
3222 ret = parse_typedef(ctx, data, &grp->typedefs);
3223 break;
3224 case YANG_ACTION:
3225 ret = parse_action(ctx, data, &grp->actions);
3226 break;
3227 case YANG_GROUPING:
3228 ret = parse_grouping(ctx, data, &grp->groupings);
3229 break;
3230 case YANG_NOTIFICATION:
3231 ret = parse_notif(ctx, data, &grp->notifs);
3232 break;
3233 case YANG_CUSTOM:
3234 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts);
3235 break;
3236 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003237 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003238 return LY_EVALID;
3239 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003240 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003241 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003242 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003243
3244 return ret;
3245}
3246
Michal Vaskoea5abea2018-09-18 13:10:54 +02003247/**
3248 * @brief Parse the refine statement.
3249 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003250 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003251 * @param[in,out] data Data to read from, always moved to currently handled character.
3252 * @param[in,out] augments Augments to add to.
3253 *
3254 * @return LY_ERR values.
3255 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003256static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003257parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003258{
3259 LY_ERR ret = 0;
3260 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003261 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003262 enum yang_keyword kw;
3263 struct lysp_augment *aug;
3264
Radek Krejci2c4e7172018-10-19 15:56:26 +02003265 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003266
3267 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003268 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003269 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003270
Radek Krejci44ceedc2018-10-02 15:54:31 +02003271 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003272 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003273 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003274
3275 switch (kw) {
3276 case YANG_DESCRIPTION:
3277 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts);
3278 break;
3279 case YANG_IF_FEATURE:
3280 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts);
3281 break;
3282 case YANG_REFERENCE:
3283 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts);
3284 break;
3285 case YANG_STATUS:
3286 ret = parse_status(ctx, data, &aug->flags, &aug->exts);
3287 break;
3288 case YANG_WHEN:
3289 ret = parse_when(ctx, data, &aug->when);
3290 break;
3291
3292 case YANG_ANYDATA:
3293 case YANG_ANYXML:
3294 ret = parse_any(ctx, data, kw, &aug->child);
3295 break;
3296 case YANG_CASE:
3297 ret = parse_case(ctx, data, &aug->child);
3298 break;
3299 case YANG_CHOICE:
3300 ret = parse_choice(ctx, data, &aug->child);
3301 break;
3302 case YANG_CONTAINER:
3303 ret = parse_container(ctx, data, &aug->child);
3304 break;
3305 case YANG_LEAF:
3306 ret = parse_leaf(ctx, data, &aug->child);
3307 break;
3308 case YANG_LEAF_LIST:
3309 ret = parse_leaflist(ctx, data, &aug->child);
3310 break;
3311 case YANG_LIST:
3312 ret = parse_list(ctx, data, &aug->child);
3313 break;
3314 case YANG_USES:
3315 ret = parse_uses(ctx, data, &aug->child);
3316 break;
3317
3318 case YANG_ACTION:
3319 ret = parse_action(ctx, data, &aug->actions);
3320 break;
3321 case YANG_NOTIFICATION:
3322 ret = parse_notif(ctx, data, &aug->notifs);
3323 break;
3324 case YANG_CUSTOM:
3325 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts);
3326 break;
3327 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003328 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003329 return LY_EVALID;
3330 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003331 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003332 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003333 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003334
3335 return ret;
3336}
3337
Michal Vaskoea5abea2018-09-18 13:10:54 +02003338/**
3339 * @brief Parse the uses statement.
3340 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003341 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003342 * @param[in,out] data Data to read from, always moved to currently handled character.
3343 * @param[in,out] siblings Siblings to add to.
3344 *
3345 * @return LY_ERR values.
3346 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003347static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003348parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003349{
3350 LY_ERR ret = 0;
3351 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003352 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003353 enum yang_keyword kw;
3354 struct lysp_node *iter;
3355 struct lysp_node_uses *uses;
3356
3357 /* create structure */
3358 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003359 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003360 uses->nodetype = LYS_USES;
3361
3362 /* insert into siblings */
3363 if (!*siblings) {
3364 *siblings = (struct lysp_node *)uses;
3365 } else {
3366 for (iter = *siblings; iter->next; iter = iter->next);
3367 iter->next = (struct lysp_node *)uses;
3368 }
3369
3370 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003371 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003372 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373
Radek Krejci44ceedc2018-10-02 15:54:31 +02003374 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003375
3376 /* parse substatements */
3377 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003378 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003379
3380 switch (kw) {
3381 case YANG_DESCRIPTION:
3382 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts);
3383 break;
3384 case YANG_IF_FEATURE:
3385 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts);
3386 break;
3387 case YANG_REFERENCE:
3388 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts);
3389 break;
3390 case YANG_STATUS:
3391 ret = parse_status(ctx, data, &uses->flags, &uses->exts);
3392 break;
3393 case YANG_WHEN:
3394 ret = parse_when(ctx, data, &uses->when);
3395 break;
3396
3397 case YANG_REFINE:
3398 ret = parse_refine(ctx, data, &uses->refines);
3399 break;
3400 case YANG_AUGMENT:
3401 ret = parse_augment(ctx, data, &uses->augments);
3402 break;
3403 case YANG_CUSTOM:
3404 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts);
3405 break;
3406 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003407 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003408 return LY_EVALID;
3409 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003410 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003411 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003412 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003413
3414 return ret;
3415}
3416
Michal Vaskoea5abea2018-09-18 13:10:54 +02003417/**
3418 * @brief Parse the case statement.
3419 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003420 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003421 * @param[in,out] data Data to read from, always moved to currently handled character.
3422 * @param[in,out] siblings Siblings to add to.
3423 *
3424 * @return LY_ERR values.
3425 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003426static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003427parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003428{
3429 LY_ERR ret = 0;
3430 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003431 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003432 enum yang_keyword kw;
3433 struct lysp_node *iter;
3434 struct lysp_node_case *cas;
3435
3436 /* create structure */
3437 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003438 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003439 cas->nodetype = LYS_CASE;
3440
3441 /* insert into siblings */
3442 if (!*siblings) {
3443 *siblings = (struct lysp_node *)cas;
3444 } else {
3445 for (iter = *siblings; iter->next; iter = iter->next);
3446 iter->next = (struct lysp_node *)cas;
3447 }
3448
3449 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003450 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003451 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003452
Radek Krejci44ceedc2018-10-02 15:54:31 +02003453 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003454
3455 /* parse substatements */
3456 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003457 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003458
3459 switch (kw) {
3460 case YANG_DESCRIPTION:
3461 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts);
3462 break;
3463 case YANG_IF_FEATURE:
3464 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts);
3465 break;
3466 case YANG_REFERENCE:
3467 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts);
3468 break;
3469 case YANG_STATUS:
3470 ret = parse_status(ctx, data, &cas->flags, &cas->exts);
3471 break;
3472 case YANG_WHEN:
3473 ret = parse_when(ctx, data, &cas->when);
3474 break;
3475
3476 case YANG_ANYDATA:
3477 case YANG_ANYXML:
3478 ret = parse_any(ctx, data, kw, &cas->child);
3479 break;
3480 case YANG_CHOICE:
3481 ret = parse_case(ctx, data, &cas->child);
3482 break;
3483 case YANG_CONTAINER:
3484 ret = parse_container(ctx, data, &cas->child);
3485 break;
3486 case YANG_LEAF:
3487 ret = parse_leaf(ctx, data, &cas->child);
3488 break;
3489 case YANG_LEAF_LIST:
3490 ret = parse_leaflist(ctx, data, &cas->child);
3491 break;
3492 case YANG_LIST:
3493 ret = parse_list(ctx, data, &cas->child);
3494 break;
3495 case YANG_USES:
3496 ret = parse_uses(ctx, data, &cas->child);
3497 break;
3498 case YANG_CUSTOM:
3499 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts);
3500 break;
3501 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003502 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003503 return LY_EVALID;
3504 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003505 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003506 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003507 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003508
3509 return ret;
3510}
3511
Michal Vaskoea5abea2018-09-18 13:10:54 +02003512/**
3513 * @brief Parse the choice statement.
3514 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003515 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003516 * @param[in,out] data Data to read from, always moved to currently handled character.
3517 * @param[in,out] siblings Siblings to add to.
3518 *
3519 * @return LY_ERR values.
3520 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003521static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003522parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003523{
3524 LY_ERR ret = 0;
3525 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003526 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003527 enum yang_keyword kw;
3528 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003529 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530
3531 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003532 choice = calloc(1, sizeof *choice);
3533 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3534 choice->nodetype = LYS_CHOICE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003535
3536 /* insert into siblings */
3537 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003538 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003539 } else {
3540 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003541 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003542 }
3543
3544 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003545 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003546 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003547
Radek Krejci44ceedc2018-10-02 15:54:31 +02003548 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003549
3550 /* parse substatements */
3551 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003552 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003553
3554 switch (kw) {
3555 case YANG_CONFIG:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003556 ret = parse_config(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003557 break;
3558 case YANG_DESCRIPTION:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003559 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003560 break;
3561 case YANG_IF_FEATURE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003562 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563 break;
3564 case YANG_MANDATORY:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003565 ret = parse_mandatory(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003566 break;
3567 case YANG_REFERENCE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003568 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569 break;
3570 case YANG_STATUS:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003571 ret = parse_status(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003572 break;
3573 case YANG_WHEN:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003574 ret = parse_when(ctx, data, &choice->when);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003575 break;
3576 case YANG_DEFAULT:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003577 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_IDENTIF_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578 break;
3579
3580 case YANG_ANYDATA:
3581 case YANG_ANYXML:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003582 ret = parse_any(ctx, data, kw, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003583 break;
3584 case YANG_CASE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003585 ret = parse_case(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003586 break;
3587 case YANG_CHOICE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003588 ret = parse_choice(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003589 break;
3590 case YANG_CONTAINER:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003591 ret = parse_container(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003592 break;
3593 case YANG_LEAF:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003594 ret = parse_leaf(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003595 break;
3596 case YANG_LEAF_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003597 ret = parse_leaflist(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003598 break;
3599 case YANG_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003600 ret = parse_list(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003601 break;
3602 case YANG_CUSTOM:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003603 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604 break;
3605 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003606 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003607 return LY_EVALID;
3608 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003609 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003611 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003612
3613 return ret;
3614}
3615
Michal Vaskoea5abea2018-09-18 13:10:54 +02003616/**
3617 * @brief Parse the container statement.
3618 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003619 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003620 * @param[in,out] data Data to read from, always moved to currently handled character.
3621 * @param[in,out] siblings Siblings to add to.
3622 *
3623 * @return LY_ERR values.
3624 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003625static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003626parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003627{
3628 LY_ERR ret = 0;
3629 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003630 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003631 enum yang_keyword kw;
3632 struct lysp_node *iter;
3633 struct lysp_node_container *cont;
3634
3635 /* create structure */
3636 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003637 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003638 cont->nodetype = LYS_CONTAINER;
3639
3640 /* insert into siblings */
3641 if (!*siblings) {
3642 *siblings = (struct lysp_node *)cont;
3643 } else {
3644 for (iter = *siblings; iter->next; iter = iter->next);
3645 iter->next = (struct lysp_node *)cont;
3646 }
3647
3648 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003649 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003650 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003651
Radek Krejci44ceedc2018-10-02 15:54:31 +02003652 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003653
3654 /* parse substatements */
3655 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003656 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003657
3658 switch (kw) {
3659 case YANG_CONFIG:
3660 ret = parse_config(ctx, data, &cont->flags, &cont->exts);
3661 break;
3662 case YANG_DESCRIPTION:
3663 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts);
3664 break;
3665 case YANG_IF_FEATURE:
3666 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts);
3667 break;
3668 case YANG_REFERENCE:
3669 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts);
3670 break;
3671 case YANG_STATUS:
3672 ret = parse_status(ctx, data, &cont->flags, &cont->exts);
3673 break;
3674 case YANG_WHEN:
3675 ret = parse_when(ctx, data, &cont->when);
3676 break;
3677 case YANG_PRESENCE:
3678 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts);
3679 break;
3680
3681 case YANG_ANYDATA:
3682 case YANG_ANYXML:
3683 ret = parse_any(ctx, data, kw, &cont->child);
3684 break;
3685 case YANG_CHOICE:
3686 ret = parse_choice(ctx, data, &cont->child);
3687 break;
3688 case YANG_CONTAINER:
3689 ret = parse_container(ctx, data, &cont->child);
3690 break;
3691 case YANG_LEAF:
3692 ret = parse_leaf(ctx, data, &cont->child);
3693 break;
3694 case YANG_LEAF_LIST:
3695 ret = parse_leaflist(ctx, data, &cont->child);
3696 break;
3697 case YANG_LIST:
3698 ret = parse_list(ctx, data, &cont->child);
3699 break;
3700 case YANG_USES:
3701 ret = parse_uses(ctx, data, &cont->child);
3702 break;
3703
3704 case YANG_TYPEDEF:
3705 ret = parse_typedef(ctx, data, &cont->typedefs);
3706 break;
3707 case YANG_MUST:
3708 ret = parse_restrs(ctx, data, kw, &cont->musts);
3709 break;
3710 case YANG_ACTION:
3711 ret = parse_action(ctx, data, &cont->actions);
3712 break;
3713 case YANG_GROUPING:
3714 ret = parse_grouping(ctx, data, &cont->groupings);
3715 break;
3716 case YANG_NOTIFICATION:
3717 ret = parse_notif(ctx, data, &cont->notifs);
3718 break;
3719 case YANG_CUSTOM:
3720 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts);
3721 break;
3722 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003723 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003724 return LY_EVALID;
3725 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003726 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003727 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003728 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003729
3730 return ret;
3731}
3732
Michal Vaskoea5abea2018-09-18 13:10:54 +02003733/**
3734 * @brief Parse the list statement.
3735 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003736 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003737 * @param[in,out] data Data to read from, always moved to currently handled character.
3738 * @param[in,out] siblings Siblings to add to.
3739 *
3740 * @return LY_ERR values.
3741 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003742static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003743parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003744{
3745 LY_ERR ret = 0;
3746 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003747 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003748 enum yang_keyword kw;
3749 struct lysp_node *iter;
3750 struct lysp_node_list *list;
3751
3752 /* create structure */
3753 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003754 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003755 list->nodetype = LYS_LIST;
3756
3757 /* insert into siblings */
3758 if (!*siblings) {
3759 *siblings = (struct lysp_node *)list;
3760 } else {
3761 for (iter = *siblings; iter->next; iter = iter->next);
3762 iter->next = (struct lysp_node *)list;
3763 }
3764
3765 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003766 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003767 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003768
Radek Krejci44ceedc2018-10-02 15:54:31 +02003769 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003770
3771 /* parse substatements */
3772 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003773 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003774
3775 switch (kw) {
3776 case YANG_CONFIG:
3777 ret = parse_config(ctx, data, &list->flags, &list->exts);
3778 break;
3779 case YANG_DESCRIPTION:
3780 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts);
3781 break;
3782 case YANG_IF_FEATURE:
3783 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts);
3784 break;
3785 case YANG_REFERENCE:
3786 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts);
3787 break;
3788 case YANG_STATUS:
3789 ret = parse_status(ctx, data, &list->flags, &list->exts);
3790 break;
3791 case YANG_WHEN:
3792 ret = parse_when(ctx, data, &list->when);
3793 break;
3794 case YANG_KEY:
3795 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts);
3796 break;
3797 case YANG_MAX_ELEMENTS:
3798 ret = parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts);
3799 break;
3800 case YANG_MIN_ELEMENTS:
3801 ret = parse_minelements(ctx, data, &list->min, &list->flags, &list->exts);
3802 break;
3803 case YANG_ORDERED_BY:
3804 ret = parse_orderedby(ctx, data, &list->flags, &list->exts);
3805 break;
3806 case YANG_UNIQUE:
3807 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts);
3808 break;
3809
3810 case YANG_ANYDATA:
3811 case YANG_ANYXML:
3812 ret = parse_any(ctx, data, kw, &list->child);
3813 break;
3814 case YANG_CHOICE:
3815 ret = parse_choice(ctx, data, &list->child);
3816 break;
3817 case YANG_CONTAINER:
3818 ret = parse_container(ctx, data, &list->child);
3819 break;
3820 case YANG_LEAF:
3821 ret = parse_leaf(ctx, data, &list->child);
3822 break;
3823 case YANG_LEAF_LIST:
3824 ret = parse_leaflist(ctx, data, &list->child);
3825 break;
3826 case YANG_LIST:
3827 ret = parse_list(ctx, data, &list->child);
3828 break;
3829 case YANG_USES:
3830 ret = parse_uses(ctx, data, &list->child);
3831 break;
3832
3833 case YANG_TYPEDEF:
3834 ret = parse_typedef(ctx, data, &list->typedefs);
3835 break;
3836 case YANG_MUST:
3837 ret = parse_restrs(ctx, data, kw, &list->musts);
3838 break;
3839 case YANG_ACTION:
3840 ret = parse_action(ctx, data, &list->actions);
3841 break;
3842 case YANG_GROUPING:
3843 ret = parse_grouping(ctx, data, &list->groupings);
3844 break;
3845 case YANG_NOTIFICATION:
3846 ret = parse_notif(ctx, data, &list->notifs);
3847 break;
3848 case YANG_CUSTOM:
3849 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts);
3850 break;
3851 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003852 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003853 return LY_EVALID;
3854 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003855 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003856 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003857 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003858
3859 return ret;
3860}
3861
Michal Vaskoea5abea2018-09-18 13:10:54 +02003862/**
3863 * @brief Parse the yin-element statement.
3864 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003865 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003866 * @param[in,out] data Data to read from, always moved to currently handled character.
3867 * @param[in,out] flags Flags to write to.
3868 * @param[in,out] exts Extension instances to add to.
3869 *
3870 * @return LY_ERR values.
3871 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003872static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003873parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003874{
3875 LY_ERR ret = 0;
3876 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003877 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003878 enum yang_keyword kw;
3879
3880 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003881 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003882 return LY_EVALID;
3883 }
3884
3885 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003886 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003887 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003888
3889 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3890 *flags |= LYS_YINELEM_TRUE;
3891 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3892 *flags |= LYS_YINELEM_FALSE;
3893 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003894 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003895 free(buf);
3896 return LY_EVALID;
3897 }
3898 free(buf);
3899
3900 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003901 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003902
3903 switch (kw) {
3904 case YANG_CUSTOM:
3905 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02003906 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003907 break;
3908 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003909 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003910 return LY_EVALID;
3911 }
3912 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003913 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003914
3915 return ret;
3916}
3917
Michal Vaskoea5abea2018-09-18 13:10:54 +02003918/**
3919 * @brief Parse the yin-element statement.
3920 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003921 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003922 * @param[in,out] data Data to read from, always moved to currently handled character.
3923 * @param[in,out] argument Value to write to.
3924 * @param[in,out] flags Flags to write to.
3925 * @param[in,out] exts Extension instances to add to.
3926 *
3927 * @return LY_ERR values.
3928 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003929static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003930parse_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 +02003931{
3932 LY_ERR ret = 0;
3933 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003934 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003935 enum yang_keyword kw;
3936
3937 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003938 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003939 return LY_EVALID;
3940 }
3941
3942 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003943 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003944 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003945
Radek Krejci44ceedc2018-10-02 15:54:31 +02003946 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003947 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003948 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003949
3950 switch (kw) {
3951 case YANG_YIN_ELEMENT:
3952 ret = parse_yinelement(ctx, data, flags, exts);
3953 break;
3954 case YANG_CUSTOM:
3955 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts);
3956 break;
3957 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003958 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003959 return LY_EVALID;
3960 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003961 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003962 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003963 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003964
3965 return ret;
3966}
3967
Michal Vaskoea5abea2018-09-18 13:10:54 +02003968/**
3969 * @brief Parse the extension statement.
3970 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003971 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003972 * @param[in,out] data Data to read from, always moved to currently handled character.
3973 * @param[in,out] extensions Extensions to add to.
3974 *
3975 * @return LY_ERR values.
3976 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003977static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003978parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003979{
3980 LY_ERR ret = 0;
3981 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003982 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003983 enum yang_keyword kw;
3984 struct lysp_ext *ex;
3985
Radek Krejci2c4e7172018-10-19 15:56:26 +02003986 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003987
3988 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003989 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003990 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003991
Radek Krejci44ceedc2018-10-02 15:54:31 +02003992 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003993 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003994 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003995
3996 switch (kw) {
3997 case YANG_DESCRIPTION:
3998 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts);
3999 break;
4000 case YANG_REFERENCE:
4001 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts);
4002 break;
4003 case YANG_STATUS:
4004 ret = parse_status(ctx, data, &ex->flags, &ex->exts);
4005 break;
4006 case YANG_ARGUMENT:
4007 ret = parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts);
4008 break;
4009 case YANG_CUSTOM:
4010 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts);
4011 break;
4012 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004013 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004014 return LY_EVALID;
4015 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004016 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004018 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004019
4020 return ret;
4021}
4022
Michal Vaskoea5abea2018-09-18 13:10:54 +02004023/**
4024 * @brief Parse the deviate statement.
4025 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004026 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004027 * @param[in,out] data Data to read from, always moved to currently handled character.
4028 * @param[in,out] deviates Deviates to add to.
4029 *
4030 * @return LY_ERR values.
4031 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004032static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004033parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004034{
4035 LY_ERR ret = 0;
4036 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004037 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004038 enum yang_keyword kw;
4039 struct lysp_deviate *iter, *d;
4040 struct lysp_deviate_add *d_add = NULL;
4041 struct lysp_deviate_rpl *d_rpl = NULL;
4042 struct lysp_deviate_del *d_del = NULL;
4043 const char **d_units, ***d_uniques, ***d_dflts;
4044 struct lysp_restr **d_musts;
4045 uint16_t *d_flags;
4046 uint32_t *d_min, *d_max;
4047
4048 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004049 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004050 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004051
4052 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4053 dev_mod = LYS_DEV_NOT_SUPPORTED;
4054 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4055 dev_mod = LYS_DEV_ADD;
4056 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4057 dev_mod = LYS_DEV_REPLACE;
4058 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4059 dev_mod = LYS_DEV_DELETE;
4060 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004061 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004062 free(buf);
4063 return LY_EVALID;
4064 }
4065 free(buf);
4066
4067 /* create structure */
4068 switch (dev_mod) {
4069 case LYS_DEV_NOT_SUPPORTED:
4070 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004071 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004072 break;
4073 case LYS_DEV_ADD:
4074 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004075 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004076 d = (struct lysp_deviate *)d_add;
4077 d_units = &d_add->units;
4078 d_uniques = &d_add->uniques;
4079 d_dflts = &d_add->dflts;
4080 d_musts = &d_add->musts;
4081 d_flags = &d_add->flags;
4082 d_min = &d_add->min;
4083 d_max = &d_add->max;
4084 break;
4085 case LYS_DEV_REPLACE:
4086 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004087 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004088 d = (struct lysp_deviate *)d_rpl;
4089 d_units = &d_rpl->units;
4090 d_flags = &d_rpl->flags;
4091 d_min = &d_rpl->min;
4092 d_max = &d_rpl->max;
4093 break;
4094 case LYS_DEV_DELETE:
4095 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004096 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004097 d = (struct lysp_deviate *)d_del;
4098 d_units = &d_del->units;
4099 d_uniques = &d_del->uniques;
4100 d_dflts = &d_del->dflts;
4101 d_musts = &d_del->musts;
4102 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004103 break;
4104 default:
4105 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004106 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004107 }
4108 d->mod = dev_mod;
4109
4110 /* insert into siblings */
4111 if (!*deviates) {
4112 *deviates = d;
4113 } else {
4114 for (iter = *deviates; iter->next; iter = iter->next);
4115 iter->next = d;
4116 }
4117
4118 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004119 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004120
4121 switch (kw) {
4122 case YANG_CONFIG:
4123 switch (dev_mod) {
4124 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004125 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004126 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004127 return LY_EVALID;
4128 default:
4129 ret = parse_config(ctx, data, d_flags, &d->exts);
4130 break;
4131 }
4132 break;
4133 case YANG_DEFAULT:
4134 switch (dev_mod) {
4135 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004136 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004137 return LY_EVALID;
4138 case LYS_DEV_REPLACE:
4139 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts);
4140 break;
4141 default:
4142 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts);
4143 break;
4144 }
4145 break;
4146 case YANG_MANDATORY:
4147 switch (dev_mod) {
4148 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004149 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004150 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004151 return LY_EVALID;
4152 default:
4153 ret = parse_mandatory(ctx, data, d_flags, &d->exts);
4154 break;
4155 }
4156 break;
4157 case YANG_MAX_ELEMENTS:
4158 switch (dev_mod) {
4159 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004160 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004161 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004162 return LY_EVALID;
4163 default:
4164 ret = parse_maxelements(ctx, data, d_max, d_flags, &d->exts);
4165 break;
4166 }
4167 break;
4168 case YANG_MIN_ELEMENTS:
4169 switch (dev_mod) {
4170 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004171 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004172 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004173 return LY_EVALID;
4174 default:
4175 ret = parse_minelements(ctx, data, d_min, d_flags, &d->exts);
4176 break;
4177 }
4178 break;
4179 case YANG_MUST:
4180 switch (dev_mod) {
4181 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004182 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004183 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004184 return LY_EVALID;
4185 default:
4186 ret = parse_restrs(ctx, data, kw, d_musts);
4187 break;
4188 }
4189 break;
4190 case YANG_TYPE:
4191 switch (dev_mod) {
4192 case LYS_DEV_NOT_SUPPORTED:
4193 case LYS_DEV_ADD:
4194 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004195 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004196 return LY_EVALID;
4197 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004198 if (d_rpl->type) {
4199 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4200 return LY_EVALID;
4201 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004202 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004203 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004204 ret = parse_type(ctx, data, d_rpl->type);
4205 break;
4206 }
4207 break;
4208 case YANG_UNIQUE:
4209 switch (dev_mod) {
4210 case LYS_DEV_NOT_SUPPORTED:
4211 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004212 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004213 return LY_EVALID;
4214 default:
4215 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts);
4216 break;
4217 }
4218 break;
4219 case YANG_UNITS:
4220 switch (dev_mod) {
4221 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004222 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004223 return LY_EVALID;
4224 default:
4225 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts);
4226 break;
4227 }
4228 break;
4229 case YANG_CUSTOM:
4230 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts);
4231 break;
4232 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004233 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004234 return LY_EVALID;
4235 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004236 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004237 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004238 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004239
4240 return ret;
4241}
4242
Michal Vaskoea5abea2018-09-18 13:10:54 +02004243/**
4244 * @brief Parse the deviation statement.
4245 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004246 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004247 * @param[in,out] data Data to read from, always moved to currently handled character.
4248 * @param[in,out] deviations Deviations to add to.
4249 *
4250 * @return LY_ERR values.
4251 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004252static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004253parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004254{
4255 LY_ERR ret = 0;
4256 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004257 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004258 enum yang_keyword kw;
4259 struct lysp_deviation *dev;
4260
Radek Krejci2c4e7172018-10-19 15:56:26 +02004261 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004262
4263 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004264 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004265 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004266
Radek Krejci44ceedc2018-10-02 15:54:31 +02004267 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004268 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004269 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004270
4271 switch (kw) {
4272 case YANG_DESCRIPTION:
4273 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts);
4274 break;
4275 case YANG_DEVIATE:
4276 ret = parse_deviate(ctx, data, &dev->deviates);
4277 break;
4278 case YANG_REFERENCE:
4279 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts);
4280 break;
4281 case YANG_CUSTOM:
4282 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts);
4283 break;
4284 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004285 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004286 return LY_EVALID;
4287 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004288 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004289 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004290 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004291
4292 /* mandatory substatements */
4293 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004294 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004295 return LY_EVALID;
4296 }
4297
4298 return ret;
4299}
4300
Michal Vaskoea5abea2018-09-18 13:10:54 +02004301/**
4302 * @brief Parse the feature statement.
4303 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004304 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004305 * @param[in,out] data Data to read from, always moved to currently handled character.
4306 * @param[in,out] features Features to add to.
4307 *
4308 * @return LY_ERR values.
4309 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004310static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004311parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004312{
4313 LY_ERR ret = 0;
4314 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004315 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316 enum yang_keyword kw;
4317 struct lysp_feature *feat;
4318
Radek Krejci2c4e7172018-10-19 15:56:26 +02004319 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004320
4321 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004322 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004323 LY_CHECK_RET(ret);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004324 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004325
4326 CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
4327
Michal Vasko7fbc8162018-09-17 10:35:16 +02004328 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004329 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004330
4331 switch (kw) {
4332 case YANG_DESCRIPTION:
4333 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts);
4334 break;
4335 case YANG_IF_FEATURE:
4336 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts);
4337 break;
4338 case YANG_REFERENCE:
4339 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts);
4340 break;
4341 case YANG_STATUS:
4342 ret = parse_status(ctx, data, &feat->flags, &feat->exts);
4343 break;
4344 case YANG_CUSTOM:
4345 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts);
4346 break;
4347 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004348 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004349 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004350 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004351 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004352 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004353 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004354
4355 return ret;
4356}
4357
Michal Vaskoea5abea2018-09-18 13:10:54 +02004358/**
4359 * @brief Parse the identity statement.
4360 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004361 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004362 * @param[in,out] data Data to read from, always moved to currently handled character.
4363 * @param[in,out] identities Identities to add to.
4364 *
4365 * @return LY_ERR values.
4366 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004367static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004368parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004369{
4370 LY_ERR ret = 0;
4371 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004372 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004373 enum yang_keyword kw;
4374 struct lysp_ident *ident;
4375
Radek Krejci2c4e7172018-10-19 15:56:26 +02004376 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004377
4378 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004379 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004380 LY_CHECK_RET(ret);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004381 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004382
4383 CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
4384
Michal Vasko7fbc8162018-09-17 10:35:16 +02004385 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004386 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004387
4388 switch (kw) {
4389 case YANG_DESCRIPTION:
4390 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts);
4391 break;
4392 case YANG_IF_FEATURE:
4393 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts);
4394 break;
4395 case YANG_REFERENCE:
4396 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts);
4397 break;
4398 case YANG_STATUS:
4399 ret = parse_status(ctx, data, &ident->flags, &ident->exts);
4400 break;
4401 case YANG_BASE:
4402 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts);
4403 break;
4404 case YANG_CUSTOM:
4405 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts);
4406 break;
4407 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004408 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004409 return LY_EVALID;
4410 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004411 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004412 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004413
4414 return ret;
4415}
4416
Michal Vaskoea5abea2018-09-18 13:10:54 +02004417/**
4418 * @brief Parse the module or submodule statement.
4419 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004420 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004421 * @param[in,out] data Data to read from, always moved to currently handled character.
4422 * @param[in,out] mod Module to write to.
4423 *
4424 * @return LY_ERR values.
4425 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004426static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004427parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428{
4429 LY_ERR ret = 0;
4430 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004431 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004432 enum yang_keyword kw, prev_kw = 0;
4433 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4434
4435 /* (sub)module name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004436 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004437 LY_CHECK_RET(ret);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004438 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004439
4440 /* submodules share the namespace with the module names, so there must not be
4441 * a submodule of the same name in the context, no need for revision matching */
4442 if (ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL)) {
4443 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4444 mod->submodule ? "submodules" : "module and submodule", mod->name);
4445 return LY_EVALID;
4446 }
4447
Michal Vasko7fbc8162018-09-17 10:35:16 +02004448 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004449 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004450
Radek Krejcie3846472018-10-15 15:24:51 +02004451#define CHECK_ORDER(SECTION) \
4452 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4453
Michal Vasko7fbc8162018-09-17 10:35:16 +02004454 switch (kw) {
4455 /* module header */
4456 case YANG_NAMESPACE:
4457 case YANG_PREFIX:
4458 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004459 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004460 return LY_EVALID;
4461 }
Radek Krejcie3846472018-10-15 15:24:51 +02004462 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4463 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004464 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004465 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004466 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004467 return LY_EVALID;
4468 }
Radek Krejcie3846472018-10-15 15:24:51 +02004469 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4470 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004471 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004472 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004473 break;
4474 /* linkage */
4475 case YANG_INCLUDE:
4476 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004477 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004478 break;
4479 /* meta */
4480 case YANG_ORGANIZATION:
4481 case YANG_CONTACT:
4482 case YANG_DESCRIPTION:
4483 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004484 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004485 break;
4486
4487 /* revision */
4488 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004489 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004490 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004491 /* body */
4492 case YANG_ANYDATA:
4493 case YANG_ANYXML:
4494 case YANG_AUGMENT:
4495 case YANG_CHOICE:
4496 case YANG_CONTAINER:
4497 case YANG_DEVIATION:
4498 case YANG_EXTENSION:
4499 case YANG_FEATURE:
4500 case YANG_GROUPING:
4501 case YANG_IDENTITY:
4502 case YANG_LEAF:
4503 case YANG_LEAF_LIST:
4504 case YANG_LIST:
4505 case YANG_NOTIFICATION:
4506 case YANG_RPC:
4507 case YANG_TYPEDEF:
4508 case YANG_USES:
4509 case YANG_CUSTOM:
4510 mod_stmt = Y_MOD_BODY;
4511 break;
4512 default:
4513 /* error handled in the next switch */
4514 break;
4515 }
Radek Krejcie3846472018-10-15 15:24:51 +02004516#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004517
Radek Krejcie3846472018-10-15 15:24:51 +02004518 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004519 switch (kw) {
4520 /* module header */
4521 case YANG_YANG_VERSION:
4522 ret = parse_yangversion(ctx, data, mod);
4523 break;
4524 case YANG_NAMESPACE:
4525 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts);
4526 break;
4527 case YANG_PREFIX:
4528 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts);
Radek Krejci70853c52018-10-15 14:46:16 +02004529 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004530 break;
4531 case YANG_BELONGS_TO:
4532 ret = parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts);
4533 break;
4534
4535 /* linkage */
4536 case YANG_INCLUDE:
Radek Krejcid33273d2018-10-25 14:55:52 +02004537 ret = parse_include(ctx, data, mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004538 break;
4539 case YANG_IMPORT:
Radek Krejci70853c52018-10-15 14:46:16 +02004540 ret = parse_import(ctx, data, mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004541 break;
4542
4543 /* meta */
4544 case YANG_ORGANIZATION:
4545 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts);
4546 break;
4547 case YANG_CONTACT:
4548 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts);
4549 break;
4550 case YANG_DESCRIPTION:
4551 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts);
4552 break;
4553 case YANG_REFERENCE:
4554 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts);
4555 break;
4556
4557 /* revision */
4558 case YANG_REVISION:
4559 ret = parse_revision(ctx, data, &mod->revs);
4560 break;
4561
4562 /* body */
4563 case YANG_ANYDATA:
4564 case YANG_ANYXML:
4565 ret = parse_any(ctx, data, kw, &mod->data);
4566 break;
4567 case YANG_CHOICE:
4568 ret = parse_choice(ctx, data, &mod->data);
4569 break;
4570 case YANG_CONTAINER:
4571 ret = parse_container(ctx, data, &mod->data);
4572 break;
4573 case YANG_LEAF:
4574 ret = parse_leaf(ctx, data, &mod->data);
4575 break;
4576 case YANG_LEAF_LIST:
4577 ret = parse_leaflist(ctx, data, &mod->data);
4578 break;
4579 case YANG_LIST:
4580 ret = parse_list(ctx, data, &mod->data);
4581 break;
4582 case YANG_USES:
4583 ret = parse_uses(ctx, data, &mod->data);
4584 break;
4585
4586 case YANG_AUGMENT:
4587 ret = parse_augment(ctx, data, &mod->augments);
4588 break;
4589 case YANG_DEVIATION:
4590 ret = parse_deviation(ctx, data, &mod->deviations);
4591 break;
4592 case YANG_EXTENSION:
4593 ret = parse_extension(ctx, data, &mod->extensions);
4594 break;
4595 case YANG_FEATURE:
4596 ret = parse_feature(ctx, data, &mod->features);
4597 break;
4598 case YANG_GROUPING:
4599 ret = parse_grouping(ctx, data, &mod->groupings);
4600 break;
4601 case YANG_IDENTITY:
4602 ret = parse_identity(ctx, data, &mod->identities);
4603 break;
4604 case YANG_NOTIFICATION:
4605 ret = parse_notif(ctx, data, &mod->notifs);
4606 break;
4607 case YANG_RPC:
4608 ret = parse_action(ctx, data, &mod->rpcs);
4609 break;
4610 case YANG_TYPEDEF:
4611 ret = parse_typedef(ctx, data, &mod->typedefs);
4612 break;
4613 case YANG_CUSTOM:
4614 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts);
4615 break;
4616
4617 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004618 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004619 return LY_EVALID;
4620 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004621 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004622 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004623 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004624
4625 /* mandatory substatements */
4626 if (mod->submodule) {
4627 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004628 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004629 return LY_EVALID;
4630 }
4631 } else {
4632 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004633 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004634 return LY_EVALID;
4635 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004636 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004637 return LY_EVALID;
4638 }
4639 }
4640
4641 return ret;
4642}
4643
Radek Krejcid4557c62018-09-17 11:42:09 +02004644LY_ERR
Michal Vasko7fbc8162018-09-17 10:35:16 +02004645yang_parse(struct ly_ctx *ctx, const char *data, struct lysp_module **mod_p)
4646{
4647 LY_ERR ret = 0;
4648 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004649 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004650 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004651 struct lysp_module *mod = NULL;
Radek Krejci86d106e2018-10-18 09:53:19 +02004652 struct ly_parser_ctx context = {0};
Michal Vasko7fbc8162018-09-17 10:35:16 +02004653
Radek Krejci44ceedc2018-10-02 15:54:31 +02004654 context.ctx = ctx;
4655 context.line = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004656
4657 /* "module"/"submodule" */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004658 ret = get_keyword(&context, &data, &kw, &word, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004659 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004660
4661 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004662 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004663 ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004664 goto error;
4665 }
4666
4667 mod = calloc(1, sizeof *mod);
4668 LY_CHECK_ERR_GOTO(!mod, LOGMEM(ctx), error);
4669 if (kw == YANG_SUBMODULE) {
4670 mod->submodule = 1;
4671 }
Radek Krejci9fcacc12018-10-11 15:59:11 +02004672 mod->ctx = ctx;
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004673 context.mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004674
4675 /* substatements */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004676 ret = parse_sub_module(&context, &data, mod);
Radek Krejcic59bc972018-09-17 16:13:06 +02004677 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004678
4679 /* read some trailing spaces or new lines */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004680 ret = get_argument(&context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004681 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004682
4683 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004684 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004685 word_len, word);
4686 free(buf);
4687 goto error;
4688 }
4689 assert(!buf);
4690
4691 *mod_p = mod;
4692 return ret;
4693
4694error:
Radek Krejci9fcacc12018-10-11 15:59:11 +02004695 lysp_module_free(mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004696 return ret;
4697}