blob: c0ef8068ada6b1172654b6e08656ccc55373cd86 [file] [log] [blame]
Michal Vasko7fbc8162018-09-17 10:35:16 +02001/**
2 * @file parser_yang.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YANG parser
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <errno.h>
22#include <ctype.h>
23#include <string.h>
24#include <dirent.h>
25#include <assert.h>
26
27#include "common.h"
28#include "context.h"
29#include "libyang.h"
Radek Krejci70853c52018-10-15 14:46:16 +020030#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020031
32/* Macro to check YANG's yang-char grammar rule */
33#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
34 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
35 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
36 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
37 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
38 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
39 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
40 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
41 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
42 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
43
44/* These 2 macros checks YANG's identifier grammar rule */
45#define is_yangidentstartchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
46#define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
47 c == '_' || c == '-' || c == '.')
48
Radek Krejci9fcacc12018-10-11 15:59:11 +020049#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
50 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
51 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020052
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020053#define MOVE_INPUT(CTX, DATA, COUNT) (*(data))+=COUNT;(CTX)->indent+=COUNT
54
Michal Vaskoea5abea2018-09-18 13:10:54 +020055/**
56 * @brief Loop through all substatements providing, return if there are none.
57 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020058 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020059 * @param[in] DATA Raw data to read from.
60 * @param[out] KW YANG keyword read.
61 * @param[out] WORD Pointer to the keyword itself.
62 * @param[out] WORD_LEN Length of the keyword.
63 * @param[out] ERR Variable for error storing.
64 *
65 * @return In case there are no substatements or a fatal error encountered.
66 */
Michal Vasko7fbc8162018-09-17 10:35:16 +020067#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR) \
68 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
Radek Krejcic59bc972018-09-17 16:13:06 +020069 LY_CHECK_RET(ERR); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020070 \
71 if (KW == YANG_SEMICOLON) { \
72 return ERR; \
73 } \
74 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020075 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020076 return LY_EVALID; \
77 } \
78 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
79 !ERR && (KW != YANG_RIGHT_BRACE); \
80 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
81
Radek Krejci44ceedc2018-10-02 15:54:31 +020082static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
83static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
84static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
85static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
86static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
87static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +020088
Michal Vaskoea5abea2018-09-18 13:10:54 +020089/**
90 * @brief Add another character to dynamic buffer, a low-level function.
91 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020092 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +020093 *
Radek Krejci404251e2018-10-09 12:06:44 +020094 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +020095 * @param[in, out] input Input string to process.
96 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +020097 * @param[in,out] buf Buffer to use, can be moved by realloc().
98 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +020099 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200100 *
101 * @return LY_ERR values.
102 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200103static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200104buf_add_char(struct ly_ctx *ctx, const char **input, size_t len, char **buf, size_t *buf_len, size_t *buf_used)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200105{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200106 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200107 *buf_len += 16;
108 *buf = ly_realloc(*buf, *buf_len);
109 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
110 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200111 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200112
Radek Krejci44ceedc2018-10-02 15:54:31 +0200113 (*buf_used) += len;
114 (*input) += len;
115
Michal Vasko7fbc8162018-09-17 10:35:16 +0200116 return LY_SUCCESS;
117}
118
Michal Vaskoea5abea2018-09-18 13:10:54 +0200119/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200120 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200121 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200122 * @param[in] ctx yang parser context for logging.
123 * @param[in] c UTF8 code point of a character to check.
124 * @return LY_ERR values.
125 */
126static LY_ERR
127check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
128{
129 if (!is_yangutf8char(c)) {
130 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
131 return LY_EVALID;
132 }
133 return LY_SUCCESS;
134}
135
136/**
137 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
138 *
139 * @param[in] ctx yang parser context for logging.
140 * @param[in] c UTF8 code point of a character to check.
141 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200142 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
143 * 0 - colon not yet found (no prefix)
144 * 1 - \p c is the colon character
145 * 2 - prefix already processed, now processing the identifier
146 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200147 * If the identifier cannot be prefixed, NULL is expected.
148 * @return LY_ERR values.
149 */
150static LY_ERR
151check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
152{
153 if (first || (prefix && (*prefix) == 1)) {
154 if (!is_yangidentstartchar(c)) {
155 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
156 return LY_EVALID;
157 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200158 if (prefix) {
159 if (first) {
160 (*prefix) = 0;
161 } else {
162 (*prefix) = 2;
163 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200164 }
165 } else if (c == ':' && prefix && (*prefix) == 0) {
166 (*prefix) = 1;
167 } else if (!is_yangidentchar(c)) {
168 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
169 return LY_EVALID;
170 }
171
172 return LY_SUCCESS;
173}
174
175/**
176 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
177 *
178 * @param[in] ctx yang parser context for logging.
179 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
180 * when function returns.
181 * @param[in] arg Type of the input string to select method of checking character validity.
182 * @param[in,out] word_p Word pointer. If buffer (\p word_b) was not yet needed, it is just a pointer to the first
Michal Vaskoea5abea2018-09-18 13:10:54 +0200183 * stored character. If buffer was needed (\p word_b is non-NULL or \p need_buf is set), it is pointing to the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200184 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
185 * @param[in,out] word_b Word buffer. Is kept NULL as long as it is not requested (word is a substring of the data).
Michal Vaskoea5abea2018-09-18 13:10:54 +0200186 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200187 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200188 *
189 * @return LY_ERR values.
190 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200191static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200192buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
193 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200194{
Radek Krejci404251e2018-10-09 12:06:44 +0200195 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200196 unsigned int c;
197 size_t len;
198
199 /* get UTF8 code point (and number of bytes coding the character) */
200 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
201 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
202 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200203 if (c == '\n') {
204 ctx->indent = 0;
205 } else {
206 /* note - even the multibyte character is count as 1 */
207 ++ctx->indent;
208 }
209
Radek Krejci44ceedc2018-10-02 15:54:31 +0200210 /* check character validity */
211 switch (arg) {
212 case Y_IDENTIF_ARG:
213 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
214 break;
215 case Y_PREF_IDENTIF_ARG:
216 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
217 break;
218 case Y_STR_ARG:
219 case Y_MAYBE_STR_ARG:
220 LY_CHECK_RET(check_stringchar(ctx, c));
221 break;
222 }
223
Michal Vasko7fbc8162018-09-17 10:35:16 +0200224 if (word_b && *word_b) {
225 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200226 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200227 return LY_EMEM;
228 }
229
230 /* in case of realloc */
231 *word_p = *word_b;
232 } else if (need_buf) {
233 /* first time we need a buffer, copy everything read up to now */
234 if (*word_len) {
235 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200236 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200237 *buf_len = *word_len;
238 memcpy(*word_b, *word_p, *word_len);
239 }
240
241 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200242 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200243 return LY_EMEM;
244 }
245
246 /* in case of realloc */
247 *word_p = *word_b;
248 } else {
249 /* just remember the first character pointer */
250 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200251 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200252 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200253 /* ... and update the word's length */
254 (*word_len) += len;
255 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200256 }
257
258 return LY_SUCCESS;
259}
260
Michal Vaskoea5abea2018-09-18 13:10:54 +0200261/**
262 * @brief Skip YANG comment in data.
263 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200264 * @param[in] ctx yang parser context for logging.
265 * @param[in,out] data Data to read from, automatically moved after the comment.
266 * @param[in] comment Type of the comment to process:
267 * 1 for a one-line comment,
268 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200269 *
270 * @return LY_ERR values.
271 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200272static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200273skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200274{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200275 /* internal statuses: 0 - comment ended,
276 * 1 - in line comment,
277 * 2 - in block comment,
278 * 3 - in block comment with last read character '*'
279 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200280 while (**data && comment) {
281 switch (comment) {
282 case 1:
283 if (**data == '\n') {
284 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200285 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200286 }
287 break;
288 case 2:
289 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200290 comment = 3;
291 } else if (**data == '\n') {
292 ++ctx->line;
293 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200294 break;
295 case 3:
296 if (**data == '/') {
297 comment = 0;
298 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200299 if (**data == '\n') {
300 ++ctx->line;
301 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200302 comment = 2;
303 }
304 break;
305 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200306 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200307 }
308
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200309 if (**data == '\n') {
310 ctx->indent = 0;
311 } else {
312 ++ctx->indent;
313 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200314 ++(*data);
315 }
316
317 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200318 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200319 return LY_EVALID;
320 }
321
322 return LY_SUCCESS;
323}
324
Michal Vaskoea5abea2018-09-18 13:10:54 +0200325/**
326 * @brief Read a quoted string from data.
327 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200328 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200329 * @param[in,out] data Data to read from, always moved to currently handled character.
330 * @param[in] arg Type of YANG keyword argument expected.
331 * @param[out] word_p Pointer to the read quoted string.
332 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
333 * set to NULL. Otherwise equal to \p word_p.
334 * @param[out] word_len Length of the read quoted string.
335 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
336 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
337 * indenation in the final quoted string.
338 *
339 * @return LY_ERR values.
340 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200341static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200342read_qstring(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len,
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200343 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200344{
345 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
346 * 4 - string finished, now skipping whitespaces looking for +,
347 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200348 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200349 const char *c;
350
351 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200352 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200353 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200354 } else {
355 assert(**data == '\'');
356 string = 1;
357 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200358 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200359
360 while (**data && string) {
361 switch (string) {
362 case 1:
363 switch (**data) {
364 case '\'':
365 /* string may be finished, but check for + */
366 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200367 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200368 break;
369 default:
370 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200371 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200372 break;
373 }
374 break;
375 case 2:
376 switch (**data) {
377 case '\"':
378 /* string may be finished, but check for + */
379 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200380 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200381 break;
382 case '\\':
383 /* special character following */
384 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200385 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200386 break;
387 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200388 if (current_indent < block_indent) {
389 ++current_indent;
390 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200391 } else {
392 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200393 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200394 }
395 break;
396 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200397 if (current_indent < block_indent) {
398 assert(need_buf);
399 current_indent += 8;
400 ctx->indent += 8;
401 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
402 /* store leftover spaces from the tab */
403 c = " ";
404 LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200405 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200406 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200407 } else {
408 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200409 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200410 /* additional characters for indentation - only 1 was count in buf_store_char */
411 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200412 }
413 break;
414 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200415 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200416 /* we will be removing the indents so we need our own buffer */
417 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200418
419 /* remove trailing tabs and spaces */
420 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
421 --(*word_len);
422 }
423
424 /* start indentation */
425 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200426 }
427
428 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200429 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
430
431 /* maintain line number */
432 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200433
434 /* reset context indentation counter for possible string after this one */
435 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200436 break;
437 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200438 /* first non-whitespace character, stop eating indentation */
439 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200440
441 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200442 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200443 break;
444 }
445 break;
446 case 3:
447 /* string encoded characters */
448 switch (**data) {
449 case 'n':
450 c = "\n";
451 break;
452 case 't':
453 c = "\t";
454 break;
455 case '\"':
456 c = *data;
457 break;
458 case '\\':
459 c = *data;
460 break;
461 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200462 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200463 return LY_EVALID;
464 }
465
466 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200467 LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200468
469 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200470 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200471 break;
472 case 4:
473 switch (**data) {
474 case '+':
475 /* string continues */
476 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200477 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200478 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200479 case '\n':
480 ++ctx->line;
481 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200482 case ' ':
483 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200484 /* just skip */
485 break;
486 default:
487 /* string is finished */
488 goto string_end;
489 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200490 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200491 break;
492 case 5:
493 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200494 case '\n':
495 ++ctx->line;
496 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200497 case ' ':
498 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200499 /* skip */
500 break;
501 case '\'':
502 string = 1;
503 break;
504 case '\"':
505 string = 2;
506 break;
507 default:
508 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200509 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200510 return LY_EVALID;
511 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200512 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200513 break;
514 default:
515 return LY_EINT;
516 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200517 }
518
519string_end:
520 return LY_SUCCESS;
521}
522
Michal Vaskoea5abea2018-09-18 13:10:54 +0200523/**
524 * @brief Get another YANG string from the raw data.
525 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200526 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200527 * @param[in,out] data Data to read from, always moved to currently handled character.
528 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200529 * @param[out] word_p Pointer to the read string. Can return NULL if \p arg is #Y_MAYBE_STR_ARG.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200530 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
531 * set to NULL. Otherwise equal to \p word_p.
532 * @param[out] word_len Length of the read string.
533 *
534 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200535 */
536static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200537get_argument(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200538{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200539 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200540 LY_ERR ret;
541
542 /* word buffer - dynamically allocated */
543 *word_b = NULL;
544
545 /* word pointer - just a pointer to data */
546 *word_p = NULL;
547
548 *word_len = 0;
549 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200550 switch (**data) {
551 case '\'':
552 case '\"':
553 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200554 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
555 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
556 "unquoted string character, optsep, semicolon or opening brace");
557 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200558 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200559 ret = read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200560 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200561 goto str_end;
562 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200563 if ((*data)[1] == '/') {
564 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200565 MOVE_INPUT(ctx, data, 2);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200566 ret = skip_comment(ctx, data, 1);
567 } else if ((*data)[1] == '*') {
568 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200569 MOVE_INPUT(ctx, data, 2);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200570 ret = skip_comment(ctx, data, 2);
571 } else {
572 /* not a comment after all */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200573 ret = buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0);
574 }
575 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200576 break;
577 case ' ':
578 if (*word_len) {
579 /* word is finished */
580 goto str_end;
581 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200582 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200583 break;
584 case '\t':
585 if (*word_len) {
586 /* word is finished */
587 goto str_end;
588 }
589 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200590 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200591
592 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200593 break;
594 case '\n':
595 if (*word_len) {
596 /* word is finished */
597 goto str_end;
598 }
599 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200600 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200601
602 /* track line numbers */
603 ++ctx->line;
604
605 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200606 break;
607 case ';':
608 case '{':
609 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
610 /* word is finished */
611 goto str_end;
612 }
613
Radek Krejci44ceedc2018-10-02 15:54:31 +0200614 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200615 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200616 case '}':
617 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
618 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
619 "unquoted string character, optsep, semicolon or opening brace");
620 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200621 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200622 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200623 break;
624 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200625 }
626
627str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200628 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200629 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200630 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
631 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
632 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200633 *word_p = *word_b;
634 }
635
636 return LY_SUCCESS;
637}
638
Michal Vaskoea5abea2018-09-18 13:10:54 +0200639/**
640 * @brief Get another YANG keyword from the raw data.
641 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200642 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200643 * @param[in,out] data Data to read from, always moved to currently handled character.
644 * @param[out] kw YANG keyword read.
645 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
646 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
647 *
648 * @return LY_ERR values.
649 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200650static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200651get_keyword(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200652{
653 LY_ERR ret;
654 int prefix;
655 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200656 unsigned int c;
657 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200658
659 if (word_p) {
660 *word_p = NULL;
661 *word_len = 0;
662 }
663
664 /* first skip "optsep", comments */
665 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200666 switch (**data) {
667 case '/':
668 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200669 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200670 MOVE_INPUT(ctx, data, 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200671 ret = skip_comment(ctx, data, 1);
672 if (ret) {
673 return ret;
674 }
Radek Krejcidcc7b322018-10-11 14:24:02 +0200675 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200676 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200677 MOVE_INPUT(ctx, data, 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200678 ret = skip_comment(ctx, data, 2);
679 if (ret) {
680 return ret;
681 }
682 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200683 /* error - not a comment after all, keyword cannot start with slash */
684 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
685 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200686 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200687 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200688 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200689 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200690 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200691 ctx->indent = 0;
692 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200693 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200694 /* skip whitespaces (optsep) */
695 ++ctx->indent;
696 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200697 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200698 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200699 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200700 break;
701 default:
702 /* either a keyword start or an invalid character */
703 goto keyword_start;
704 }
705
706 ++(*data);
707 }
708
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200709#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
710#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
711#define IF_KW_PREFIX_END }
712
Michal Vasko7fbc8162018-09-17 10:35:16 +0200713keyword_start:
714 word_start = *data;
715 *kw = YANG_NONE;
716
717 /* read the keyword itself */
718 switch (**data) {
719 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200720 MOVE_INPUT(ctx, data, 1);
721 IF_KW("rgument", 7, YANG_ARGUMENT)
722 else IF_KW("ugment", 6, YANG_AUGMENT)
723 else IF_KW("ction", 5, YANG_ACTION)
724 else IF_KW_PREFIX("ny", 2)
725 IF_KW("data", 4, YANG_ANYDATA)
726 else IF_KW("xml", 3, YANG_ANYXML)
727 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200728 break;
729 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200730 MOVE_INPUT(ctx, data, 1);
731 IF_KW("ase", 3, YANG_BASE)
732 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
733 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200734 break;
735 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200736 MOVE_INPUT(ctx, data, 1);
737 IF_KW("ase", 3, YANG_CASE)
738 else IF_KW("hoice", 5, YANG_CHOICE)
739 else IF_KW_PREFIX("on", 2)
740 IF_KW("fig", 3, YANG_CONFIG)
741 else IF_KW_PREFIX("ta", 2)
742 IF_KW("ct", 2, YANG_CONTACT)
743 else IF_KW("iner", 4, YANG_CONTAINER)
744 IF_KW_PREFIX_END
745 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200746 break;
747 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200748 MOVE_INPUT(ctx, data, 1);
749 IF_KW_PREFIX("e", 1)
750 IF_KW("fault", 5, YANG_DEFAULT)
751 else IF_KW("scription", 9, YANG_DESCRIPTION)
752 else IF_KW_PREFIX("viat", 4)
753 IF_KW("e", 1, YANG_DEVIATE)
754 else IF_KW("ion", 3, YANG_DEVIATION)
755 IF_KW_PREFIX_END
756 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200757 break;
758 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200759 MOVE_INPUT(ctx, data, 1);
760 IF_KW("num", 3, YANG_ENUM)
761 else IF_KW_PREFIX("rror-", 5)
762 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
763 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
764 IF_KW_PREFIX_END
765 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200766 break;
767 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200768 MOVE_INPUT(ctx, data, 1);
769 IF_KW("eature", 6, YANG_FEATURE)
770 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200771 break;
772 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200773 MOVE_INPUT(ctx, data, 1);
774 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200775 break;
776 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200777 MOVE_INPUT(ctx, data, 1);
778 IF_KW("dentity", 7, YANG_IDENTITY)
779 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
780 else IF_KW("mport", 5, YANG_IMPORT)
781 else IF_KW_PREFIX("n", 1)
782 IF_KW("clude", 5, YANG_INCLUDE)
783 else IF_KW("put", 3, YANG_INPUT)
784 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200785 break;
786 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200787 MOVE_INPUT(ctx, data, 1);
788 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200789 break;
790 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200791 MOVE_INPUT(ctx, data, 1);
792 IF_KW_PREFIX("e", 1)
793 IF_KW("af-list", 7, YANG_LEAF_LIST)
794 else IF_KW("af", 2, YANG_LEAF)
795 else IF_KW("ngth", 4, YANG_LENGTH)
796 IF_KW_PREFIX_END
797 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200798 break;
799 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200800 MOVE_INPUT(ctx, data, 1);
801 IF_KW_PREFIX("a", 1)
802 IF_KW("ndatory", 7, YANG_MANDATORY)
803 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
804 IF_KW_PREFIX_END
805 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
806 else IF_KW("ust", 3, YANG_MUST)
807 else IF_KW_PREFIX("od", 2)
808 IF_KW("ule", 3, YANG_MODULE)
809 else IF_KW("ifier", 5, YANG_MODIFIER)
810 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200811 break;
812 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200813 MOVE_INPUT(ctx, data, 1);
814 IF_KW("amespace", 8, YANG_NAMESPACE)
815 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200816 break;
817 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200818 MOVE_INPUT(ctx, data, 1);
819 IF_KW_PREFIX("r", 1)
820 IF_KW("dered-by", 8, YANG_ORDERED_BY)
821 else IF_KW("ganization", 10, YANG_ORGANIZATION)
822 IF_KW_PREFIX_END
823 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200824 break;
825 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200826 MOVE_INPUT(ctx, data, 1);
827 IF_KW("ath", 3, YANG_PATH)
828 else IF_KW("attern", 6, YANG_PATTERN)
829 else IF_KW("osition", 7, YANG_POSITION)
830 else IF_KW_PREFIX("re", 2)
831 IF_KW("fix", 3, YANG_PREFIX)
832 else IF_KW("sence", 5, YANG_PRESENCE)
833 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200834 break;
835 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200836 MOVE_INPUT(ctx, data, 1);
837 IF_KW("ange", 4, YANG_RANGE)
838 else IF_KW_PREFIX("e", 1)
839 IF_KW_PREFIX("f", 1)
840 IF_KW("erence", 6, YANG_REFERENCE)
841 else IF_KW("ine", 3, YANG_REFINE)
842 IF_KW_PREFIX_END
843 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
844 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
845 else IF_KW("vision", 6, YANG_REVISION)
846 IF_KW_PREFIX_END
847 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200848 break;
849 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200850 MOVE_INPUT(ctx, data, 1);
851 IF_KW("tatus", 5, YANG_STATUS)
852 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200853 break;
854 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200855 MOVE_INPUT(ctx, data, 1);
856 IF_KW("ypedef", 6, YANG_TYPEDEF)
857 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200858 break;
859 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200860 MOVE_INPUT(ctx, data, 1);
861 IF_KW_PREFIX("ni", 2)
862 IF_KW("que", 3, YANG_UNIQUE)
863 else IF_KW("ts", 2, YANG_UNITS)
864 IF_KW_PREFIX_END
865 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200866 break;
867 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200868 MOVE_INPUT(ctx, data, 1);
869 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200870 break;
871 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200872 MOVE_INPUT(ctx, data, 1);
873 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200874 break;
875 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200876 MOVE_INPUT(ctx, data, 1);
877 IF_KW("ang-version", 11, YANG_YANG_VERSION)
878 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200879 break;
880 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200881 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200882 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200883 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200884 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200885 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200886 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200887 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200888 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200889 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200890 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200891 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200892 default:
893 break;
894 }
895
896 if (*kw != YANG_NONE) {
897 /* make sure we have the whole keyword */
898 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200899 case '\n':
900 ++ctx->line;
901 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200902 case ' ':
903 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200904 /* mandatory "sep" */
905 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200906 case ':':
907 /* keyword is not actually a keyword, but prefix of an extension.
908 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
909 * and we will be checking the keyword (extension instance) itself */
910 prefix = 1;
911 MOVE_INPUT(ctx, data, 1);
912 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200913 case '{':
914 /* allowed only for input and output statements which can be without arguments */
915 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
916 break;
917 }
918 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200919 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200920 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200921 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
922 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200923 return LY_EVALID;
924 }
925 } else {
926 /* still can be an extension */
927 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200928extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200929 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200930 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
931 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200932 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200933 /* check character validity */
934 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200935 }
936 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200937 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200938 return LY_EVALID;
939 }
940
941 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200942 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200943 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200944 return LY_EVALID;
945 }
946
947 *kw = YANG_CUSTOM;
948 }
Radek Krejci626df482018-10-11 15:06:31 +0200949success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200950 if (word_p) {
951 *word_p = (char *)word_start;
952 *word_len = *data - word_start;
953 }
954
955 return LY_SUCCESS;
956}
957
Michal Vaskoea5abea2018-09-18 13:10:54 +0200958/**
959 * @brief Parse extension instance substatements.
960 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200961 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200962 * @param[in,out] data Data to read from, always moved to currently handled character.
963 * @param[in] word Extension instance substatement name (keyword).
964 * @param[in] word_len Extension instance substatement name length.
965 * @param[in,out] child Children of this extension instance to add to.
966 *
967 * @return LY_ERR values.
968 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200969static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200970parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200971 struct lysp_stmt **child)
972{
973 char *buf;
974 LY_ERR ret = 0;
975 enum yang_keyword kw;
976 struct lysp_stmt *stmt, *par_child;
977
978 stmt = calloc(1, sizeof *stmt);
979 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
980
Radek Krejci44ceedc2018-10-02 15:54:31 +0200981 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200982
983 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200984 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +0200985 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200986
Radek Krejci0ae092d2018-09-20 16:43:19 +0200987 if (word) {
988 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200989 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200990 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200991 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200992 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200993 }
994
995 /* insert into parent statements */
996 if (!*child) {
997 *child = stmt;
998 } else {
999 for (par_child = *child; par_child->next; par_child = par_child->next);
1000 par_child->next = stmt;
1001 }
1002
1003 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001004 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001005
1006 ret = parse_ext_substmt(ctx, data, word, word_len, &stmt->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001007 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001008 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001009 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001010
1011 return ret;
1012}
1013
Michal Vaskoea5abea2018-09-18 13:10:54 +02001014/**
1015 * @brief Parse extension instance.
1016 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001017 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001018 * @param[in,out] data Data to read from, always moved to currently handled character.
1019 * @param[in] ext_name Extension instance substatement name (keyword).
1020 * @param[in] ext_name_len Extension instance substatement name length.
1021 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1022 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1023 * @param[in,out] exts Extension instances to add to.
1024 *
1025 * @return LY_ERR values.
1026 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001027static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001028parse_ext(struct ly_parser_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001029 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1030{
1031 LY_ERR ret = 0;
1032 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001033 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001034 struct lysp_ext_instance *e;
1035 enum yang_keyword kw;
1036
Radek Krejci2c4e7172018-10-19 15:56:26 +02001037 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001038
1039 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001040 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001041 e->insubstmt = insubstmt;
1042 e->insubstmt_index = insubstmt_index;
1043
1044 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001045 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001046 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001047
Radek Krejci0ae092d2018-09-20 16:43:19 +02001048 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001049 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001050 }
1051
1052 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001053 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001054
1055 ret = parse_ext_substmt(ctx, data, word, word_len, &e->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001056 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001057 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001058 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001059
1060 return ret;
1061}
1062
Michal Vaskoea5abea2018-09-18 13:10:54 +02001063/**
1064 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1065 * description, etc...
1066 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001067 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001068 * @param[in,out] data Data to read from, always moved to currently handled character.
1069 * @param[in] substmt Type of this substatement.
1070 * @param[in] substmt_index Index of this substatement.
1071 * @param[in,out] value Place to store the parsed value.
1072 * @param[in] arg Type of the YANG keyword argument (of the value).
1073 * @param[in,out] exts Extension instances to add to.
1074 *
1075 * @return LY_ERR values.
1076 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001077static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001078parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001079 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1080{
1081 LY_ERR ret = 0;
1082 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001083 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001084 enum yang_keyword kw;
1085
1086 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001087 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001088 return LY_EVALID;
1089 }
1090
1091 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001092 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001093 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001094
1095 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001096 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001097
1098 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001099 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001100
1101 switch (kw) {
1102 case YANG_CUSTOM:
1103 ret = parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001104 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001105 break;
1106 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001107 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001108 return LY_EVALID;
1109 }
1110 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001111 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001112
1113 return ret;
1114}
1115
Michal Vaskoea5abea2018-09-18 13:10:54 +02001116/**
1117 * @brief Parse the yang-version statement.
1118 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001119 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001120 * @param[in,out] data Data to read from, always moved to currently handled character.
1121 * @param[in] mod Module to store the parsed information in.
1122 *
1123 * @return LY_ERR values.
1124 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001125static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001126parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001127{
1128 LY_ERR ret = 0;
1129 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001130 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131 enum yang_keyword kw;
1132
1133 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001134 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001135 return LY_EVALID;
1136 }
1137
1138 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001139 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001140 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001141
1142 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1143 mod->version = LYS_VERSION_1_0;
1144 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1145 mod->version = LYS_VERSION_1_1;
1146 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001147 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001148 free(buf);
1149 return LY_EVALID;
1150 }
1151 free(buf);
1152
1153 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001154 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001155
1156 switch (kw) {
1157 case YANG_CUSTOM:
1158 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001159 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001160 break;
1161 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001162 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001163 return LY_EVALID;
1164 }
1165 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001166 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001167
1168 return ret;
1169}
1170
Michal Vaskoea5abea2018-09-18 13:10:54 +02001171/**
1172 * @brief Parse the belongs-to statement.
1173 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001174 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001175 * @param[in,out] data Data to read from, always moved to currently handled character.
1176 * @param[in,out] belongsto Place to store the parsed value.
1177 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1178 * @param[in,out] exts Extension instances to add to.
1179 *
1180 * @return LY_ERR values.
1181 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001182static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001183parse_belongsto(struct ly_parser_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184{
1185 LY_ERR ret = 0;
1186 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001187 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001188 enum yang_keyword kw;
1189
1190 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001191 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001192 return LY_EVALID;
1193 }
1194
1195 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001196 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001197 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001198
Radek Krejci44ceedc2018-10-02 15:54:31 +02001199 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001200 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001201 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001202
1203 switch (kw) {
1204 case YANG_PREFIX:
1205 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts);
1206 break;
1207 case YANG_CUSTOM:
1208 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts);
1209 break;
1210 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001211 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001212 return LY_EVALID;
1213 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001214 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001215 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001216 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001217
1218 /* mandatory substatements */
1219 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001220 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001221 return LY_EVALID;
1222 }
1223
1224 return ret;
1225}
1226
Michal Vaskoea5abea2018-09-18 13:10:54 +02001227/**
1228 * @brief Parse the revision-date statement.
1229 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001230 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001231 * @param[in,out] data Data to read from, always moved to currently handled character.
1232 * @param[in,out] rev Array to store the parsed value in.
1233 * @param[in,out] exts Extension instances to add to.
1234 *
1235 * @return LY_ERR values.
1236 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001237static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001238parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001239{
1240 LY_ERR ret = 0;
1241 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001242 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001243 enum yang_keyword kw;
1244
1245 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001246 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001247 return LY_EVALID;
1248 }
1249
1250 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001251 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001252 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001253
1254 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001255 if (lysp_check_date(ctx->ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001256 free(buf);
1257 return LY_EVALID;
1258 }
1259
1260 /* store value and spend buf if allocated */
1261 strncpy(rev, word, word_len);
1262 free(buf);
1263
1264 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001265 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001266
1267 switch (kw) {
1268 case YANG_CUSTOM:
1269 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001270 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001271 break;
1272 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001273 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001274 return LY_EVALID;
1275 }
1276 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001277 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001278
1279 return ret;
1280}
1281
Michal Vaskoea5abea2018-09-18 13:10:54 +02001282/**
1283 * @brief Parse the include statement.
1284 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001285 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001286 * @param[in,out] data Data to read from, always moved to currently handled character.
1287 * @param[in,out] includes Parsed includes to add to.
1288 *
1289 * @return LY_ERR values.
1290 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001291static LY_ERR
Radek Krejcid33273d2018-10-25 14:55:52 +02001292parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001293{
Radek Krejcid33273d2018-10-25 14:55:52 +02001294 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001295 char *buf, *word;
Radek Krejcid33273d2018-10-25 14:55:52 +02001296 const char *name = NULL;
Radek Krejciefd22f62018-09-27 11:47:58 +02001297 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001298 enum yang_keyword kw;
1299 struct lysp_include *inc;
1300
Radek Krejcid33273d2018-10-25 14:55:52 +02001301 LY_ARRAY_NEW_RET(ctx->ctx, mod->includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001302
1303 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001304 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001305 LY_CHECK_RET(ret);
Radek Krejcid33273d2018-10-25 14:55:52 +02001306 INSERT_WORD(ctx, buf, name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001307
Radek Krejcid33273d2018-10-25 14:55:52 +02001308 ret = get_keyword(ctx, data, &kw, &word, &word_len);
1309 LY_CHECK_GOTO(ret, cleanup);
1310 LY_CHECK_GOTO(kw == YANG_SEMICOLON, parse_include);
1311 LY_CHECK_ERR_GOTO(kw != YANG_LEFT_BRACE,
1312 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(kw));
1313 ret = LY_EVALID, cleanup);
1314 for (ret = get_keyword(ctx, data, &kw, &word, &word_len);
1315 !ret && (kw != YANG_RIGHT_BRACE);
1316 ret = get_keyword(ctx, data, &kw, &word, &word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001317 switch (kw) {
1318 case YANG_DESCRIPTION:
1319 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts);
1320 break;
1321 case YANG_REFERENCE:
1322 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts);
1323 break;
1324 case YANG_REVISION_DATE:
1325 ret = parse_revisiondate(ctx, data, inc->rev, &inc->exts);
1326 break;
1327 case YANG_CUSTOM:
1328 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts);
1329 break;
1330 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001331 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Radek Krejcid33273d2018-10-25 14:55:52 +02001332 lydict_remove(ctx->ctx, name);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001333 return LY_EVALID;
1334 }
Radek Krejcid33273d2018-10-25 14:55:52 +02001335 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001336 }
Radek Krejcid33273d2018-10-25 14:55:52 +02001337 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001338
Radek Krejcid33273d2018-10-25 14:55:52 +02001339parse_include:
1340 ret = lysp_parse_include(ctx, mod, name, inc);
1341
1342cleanup:
1343 lydict_remove(ctx->ctx, name);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001344 return ret;
1345}
1346
Michal Vaskoea5abea2018-09-18 13:10:54 +02001347/**
1348 * @brief Parse the import statement.
1349 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001350 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001351 * @param[in,out] data Data to read from, always moved to currently handled character.
1352 * @param[in,out] imports Parsed imports to add to.
1353 *
1354 * @return LY_ERR values.
1355 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001356static LY_ERR
Radek Krejci70853c52018-10-15 14:46:16 +02001357parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *module)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001358{
1359 LY_ERR ret = 0;
1360 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001361 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001362 enum yang_keyword kw;
1363 struct lysp_import *imp;
1364
Radek Krejci2c4e7172018-10-19 15:56:26 +02001365 LY_ARRAY_NEW_RET(ctx->ctx, module->imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001366
1367 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001368 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001369 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001370
Radek Krejci44ceedc2018-10-02 15:54:31 +02001371 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001372 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001373 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001374
1375 switch (kw) {
1376 case YANG_PREFIX:
1377 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts);
Radek Krejci70853c52018-10-15 14:46:16 +02001378 LY_CHECK_RET(lysp_check_prefix(ctx, module, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001379 break;
1380 case YANG_DESCRIPTION:
1381 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts);
1382 break;
1383 case YANG_REFERENCE:
1384 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts);
1385 break;
1386 case YANG_REVISION_DATE:
1387 ret = parse_revisiondate(ctx, data, imp->rev, &imp->exts);
1388 break;
1389 case YANG_CUSTOM:
1390 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts);
1391 break;
1392 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001393 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001394 return LY_EVALID;
1395 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001396 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001397 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001398 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001399
1400 /* mandatory substatements */
1401 if (!imp->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001402 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001403 return LY_EVALID;
1404 }
1405
1406 return ret;
1407}
1408
Michal Vaskoea5abea2018-09-18 13:10:54 +02001409/**
1410 * @brief Parse the revision statement.
1411 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001412 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001413 * @param[in,out] data Data to read from, always moved to currently handled character.
1414 * @param[in,out] revs Parsed revisions to add to.
1415 *
1416 * @return LY_ERR values.
1417 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001418static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001419parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001420{
1421 LY_ERR ret = 0;
1422 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001423 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001424 enum yang_keyword kw;
1425 struct lysp_revision *rev;
1426
Radek Krejci2c4e7172018-10-19 15:56:26 +02001427 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001428
1429 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001430 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001431 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001432
1433 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001434 if (lysp_check_date(ctx->ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001435 return LY_EVALID;
1436 }
1437
Radek Krejcib7db73a2018-10-24 14:18:40 +02001438 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001439 free(buf);
1440
1441 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001442 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001443
1444 switch (kw) {
1445 case YANG_DESCRIPTION:
1446 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts);
1447 break;
1448 case YANG_REFERENCE:
1449 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts);
1450 break;
1451 case YANG_CUSTOM:
1452 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts);
1453 break;
1454 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001455 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001456 return LY_EVALID;
1457 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001458 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001459 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001460 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001461
1462 return ret;
1463}
1464
Michal Vaskoea5abea2018-09-18 13:10:54 +02001465/**
1466 * @brief Parse a generic text field that can have more instances such as base.
1467 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001468 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001469 * @param[in,out] data Data to read from, always moved to currently handled character.
1470 * @param[in] substmt Type of this substatement.
1471 * @param[in,out] texts Parsed values to add to.
1472 * @param[in] arg Type of the expected argument.
1473 * @param[in,out] exts Extension instances to add to.
1474 *
1475 * @return LY_ERR values.
1476 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001477static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001478parse_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 +02001479 struct lysp_ext_instance **exts)
1480{
1481 LY_ERR ret = 0;
1482 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001483 const char **item;
1484 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001485 enum yang_keyword kw;
1486
1487 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001488 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001489
1490 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001491 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001492 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001493
Radek Krejci151a5b72018-10-19 14:21:44 +02001494 INSERT_WORD(ctx, buf, *item, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001495 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001496 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001497
1498 switch (kw) {
1499 case YANG_CUSTOM:
Radek Krejci151a5b72018-10-19 14:21:44 +02001500 ret = parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001501 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001502 break;
1503 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001504 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001505 return LY_EVALID;
1506 }
1507 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001508 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001509
1510 return ret;
1511}
1512
Michal Vaskoea5abea2018-09-18 13:10:54 +02001513/**
1514 * @brief Parse the config statement.
1515 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001516 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001517 * @param[in,out] data Data to read from, always moved to currently handled character.
1518 * @param[in,out] flags Flags to add to.
1519 * @param[in,out] exts Extension instances to add to.
1520 *
1521 * @return LY_ERR values.
1522 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001523static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001524parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001525{
1526 LY_ERR ret = 0;
1527 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001528 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001529 enum yang_keyword kw;
1530
1531 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001532 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001533 return LY_EVALID;
1534 }
1535
1536 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001537 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001538 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001539
1540 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1541 *flags |= LYS_CONFIG_W;
1542 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1543 *flags |= LYS_CONFIG_R;
1544 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001545 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001546 free(buf);
1547 return LY_EVALID;
1548 }
1549 free(buf);
1550
1551 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001552 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001553
1554 switch (kw) {
1555 case YANG_CUSTOM:
1556 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001557 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001558 break;
1559 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001560 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001561 return LY_EVALID;
1562 }
1563 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001564 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001565
1566 return ret;
1567}
1568
Michal Vaskoea5abea2018-09-18 13:10:54 +02001569/**
1570 * @brief Parse the mandatory statement.
1571 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001572 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001573 * @param[in,out] data Data to read from, always moved to currently handled character.
1574 * @param[in,out] flags Flags to add to.
1575 * @param[in,out] exts Extension instances to add to.
1576 *
1577 * @return LY_ERR values.
1578 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001579static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001580parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001581{
1582 LY_ERR ret = 0;
1583 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001584 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001585 enum yang_keyword kw;
1586
1587 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001588 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001589 return LY_EVALID;
1590 }
1591
1592 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001593 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001594 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001595
1596 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1597 *flags |= LYS_MAND_TRUE;
1598 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1599 *flags |= LYS_MAND_FALSE;
1600 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001601 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001602 free(buf);
1603 return LY_EVALID;
1604 }
1605 free(buf);
1606
1607 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001608 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001609
1610 switch (kw) {
1611 case YANG_CUSTOM:
1612 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001613 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001614 break;
1615 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001616 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001617 return LY_EVALID;
1618 }
1619 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001620 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001621
1622 return ret;
1623}
1624
Michal Vaskoea5abea2018-09-18 13:10:54 +02001625/**
1626 * @brief Parse a restriction such as range or length.
1627 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001628 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001629 * @param[in,out] data Data to read from, always moved to currently handled character.
1630 * @param[in] restr_kw Type of this particular restriction.
1631 * @param[in,out] exts Extension instances to add to.
1632 *
1633 * @return LY_ERR values.
1634 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001635static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001636parse_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 +02001637{
1638 LY_ERR ret = 0;
1639 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001640 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001641 enum yang_keyword kw;
1642
1643 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001644 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001645 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001646
Radek Krejci44ceedc2018-10-02 15:54:31 +02001647 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001648 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001649 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001650
1651 switch (kw) {
1652 case YANG_DESCRIPTION:
1653 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
1654 break;
1655 case YANG_REFERENCE:
1656 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
1657 break;
1658 case YANG_ERROR_APP_TAG:
1659 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
1660 break;
1661 case YANG_ERROR_MESSAGE:
1662 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
1663 break;
1664 case YANG_CUSTOM:
1665 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
1666 break;
1667 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001668 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001669 return LY_EVALID;
1670 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001671 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001672 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001673 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001674
1675 return ret;
1676}
1677
Michal Vaskoea5abea2018-09-18 13:10:54 +02001678/**
1679 * @brief Parse a restriction that can have more instances such as must.
1680 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001681 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001682 * @param[in,out] data Data to read from, always moved to currently handled character.
1683 * @param[in] restr_kw Type of this particular restriction.
1684 * @param[in,out] restrs Restrictions to add to.
1685 *
1686 * @return LY_ERR values.
1687 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001688static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001689parse_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 +02001690{
1691 struct lysp_restr *restr;
1692
Radek Krejci2c4e7172018-10-19 15:56:26 +02001693 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001694
1695 return parse_restr(ctx, data, restr_kw, restr);
1696}
1697
Michal Vaskoea5abea2018-09-18 13:10:54 +02001698/**
1699 * @brief Parse the status statement.
1700 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001701 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001702 * @param[in,out] data Data to read from, always moved to currently handled character.
1703 * @param[in,out] flags Flags to add to.
1704 * @param[in,out] exts Extension instances to add to.
1705 *
1706 * @return LY_ERR values.
1707 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001708static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001709parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001710{
1711 LY_ERR ret = 0;
1712 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001713 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001714 enum yang_keyword kw;
1715
1716 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001717 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001718 return LY_EVALID;
1719 }
1720
1721 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001722 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001723 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001724
1725 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1726 *flags |= LYS_STATUS_CURR;
1727 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1728 *flags |= LYS_STATUS_DEPRC;
1729 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1730 *flags |= LYS_STATUS_OBSLT;
1731 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001732 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001733 free(buf);
1734 return LY_EVALID;
1735 }
1736 free(buf);
1737
1738 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001739 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001740
1741 switch (kw) {
1742 case YANG_CUSTOM:
1743 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001744 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001745 break;
1746 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001747 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001748 return LY_EVALID;
1749 }
1750 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001751 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001752
1753 return ret;
1754}
1755
Michal Vaskoea5abea2018-09-18 13:10:54 +02001756/**
1757 * @brief Parse the when statement.
1758 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001759 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001760 * @param[in,out] data Data to read from, always moved to currently handled character.
1761 * @param[in,out] when_p When pointer to parse to.
1762 *
1763 * @return LY_ERR values.
1764 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001765static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001766parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001767{
1768 LY_ERR ret = 0;
1769 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001770 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001771 enum yang_keyword kw;
1772 struct lysp_when *when;
1773
1774 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001775 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001776 return LY_EVALID;
1777 }
1778
1779 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001780 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001781 *when_p = when;
1782
1783 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001784 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001785 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001786
Radek Krejci44ceedc2018-10-02 15:54:31 +02001787 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001788 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001789 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001790
1791 switch (kw) {
1792 case YANG_DESCRIPTION:
1793 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts);
1794 break;
1795 case YANG_REFERENCE:
1796 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts);
1797 break;
1798 case YANG_CUSTOM:
1799 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts);
1800 break;
1801 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001802 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001803 return LY_EVALID;
1804 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001805 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001806 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001807 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001808
1809 return ret;
1810}
1811
Michal Vaskoea5abea2018-09-18 13:10:54 +02001812/**
1813 * @brief Parse the anydata or anyxml statement.
1814 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001815 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001816 * @param[in,out] data Data to read from, always moved to currently handled character.
1817 * @param[in] kw Type of this particular keyword.
1818 * @param[in,out] siblings Siblings to add to.
1819 *
1820 * @return LY_ERR values.
1821 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001822static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001823parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001824{
1825 LY_ERR ret = 0;
1826 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001827 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001828 struct lysp_node *iter;
1829 struct lysp_node_anydata *any;
1830
1831 /* create structure */
1832 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001833 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001834 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
1835
1836 /* insert into siblings */
1837 if (!*siblings) {
1838 *siblings = (struct lysp_node *)any;
1839 } else {
1840 for (iter = *siblings; iter->next; iter = iter->next);
1841 iter->next = (struct lysp_node *)any;
1842 }
1843
1844 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001845 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001846 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001847
Radek Krejci44ceedc2018-10-02 15:54:31 +02001848 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001849
1850 /* parse substatements */
1851 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001852 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001853
1854 switch (kw) {
1855 case YANG_CONFIG:
1856 ret = parse_config(ctx, data, &any->flags, &any->exts);
1857 break;
1858 case YANG_DESCRIPTION:
1859 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts);
1860 break;
1861 case YANG_IF_FEATURE:
1862 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts);
1863 break;
1864 case YANG_MANDATORY:
1865 ret = parse_mandatory(ctx, data, &any->flags, &any->exts);
1866 break;
1867 case YANG_MUST:
1868 ret = parse_restrs(ctx, data, kw, &any->musts);
1869 break;
1870 case YANG_REFERENCE:
1871 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts);
1872 break;
1873 case YANG_STATUS:
1874 ret = parse_status(ctx, data, &any->flags, &any->exts);
1875 break;
1876 case YANG_WHEN:
1877 ret = parse_when(ctx, data, &any->when);
1878 break;
1879 case YANG_CUSTOM:
1880 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts);
1881 break;
1882 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001883 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001884 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001885 return LY_EVALID;
1886 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001887 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001888 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001889 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001890
1891 return ret;
1892}
1893
Michal Vaskoea5abea2018-09-18 13:10:54 +02001894/**
1895 * @brief Parse the value or position statement. Substatement of type enum statement.
1896 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001897 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001898 * @param[in,out] data Data to read from, always moved to currently handled character.
1899 * @param[in] val_kw Type of this particular keyword.
1900 * @param[in,out] value Value to write to.
1901 * @param[in,out] flags Flags to write to.
1902 * @param[in,out] exts Extension instances to add to.
1903 *
1904 * @return LY_ERR values.
1905 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001906static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001907parse_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 +02001908 struct lysp_ext_instance **exts)
1909{
1910 LY_ERR ret = 0;
1911 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001912 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001913 long int num;
1914 unsigned long int unum;
1915 enum yang_keyword kw;
1916
1917 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001918 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001919 return LY_EVALID;
1920 }
1921 *flags |= LYS_SET_VALUE;
1922
1923 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001924 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001925 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001926
1927 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 +02001928 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001929 free(buf);
1930 return LY_EVALID;
1931 }
1932
1933 errno = 0;
1934 if (val_kw == YANG_VALUE) {
1935 num = strtol(word, &ptr, 10);
1936 } else {
1937 unum = strtoul(word, &ptr, 10);
1938 }
1939 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001940 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001941 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001942 free(buf);
1943 return LY_EVALID;
1944 }
1945 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001946 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001947 free(buf);
1948 return LY_EVALID;
1949 }
1950 if (val_kw == YANG_VALUE) {
1951 *value = num;
1952 } else {
1953 *value = unum;
1954 }
1955 free(buf);
1956
1957 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001958 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001959
1960 switch (kw) {
1961 case YANG_CUSTOM:
1962 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 +02001963 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001964 break;
1965 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001966 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001967 return LY_EVALID;
1968 }
1969 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001970 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001971
1972 return ret;
1973}
1974
Michal Vaskoea5abea2018-09-18 13:10:54 +02001975/**
1976 * @brief Parse the enum or bit statement. Substatement of type statement.
1977 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001978 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001979 * @param[in,out] data Data to read from, always moved to currently handled character.
1980 * @param[in] enum_kw Type of this particular keyword.
1981 * @param[in,out] enums Enums or bits to add to.
1982 *
1983 * @return LY_ERR values.
1984 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001985static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001986parse_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 +02001987{
1988 LY_ERR ret = 0;
1989 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001990 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001991 enum yang_keyword kw;
1992 struct lysp_type_enum *enm;
1993
Radek Krejci2c4e7172018-10-19 15:56:26 +02001994 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001995
1996 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001997 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001998 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001999
Radek Krejci44ceedc2018-10-02 15:54:31 +02002000 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002001 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002002 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002003
2004 switch (kw) {
2005 case YANG_DESCRIPTION:
2006 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts);
2007 break;
2008 case YANG_IF_FEATURE:
2009 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts);
2010 break;
2011 case YANG_REFERENCE:
2012 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts);
2013 break;
2014 case YANG_STATUS:
2015 ret = parse_status(ctx, data, &enm->flags, &enm->exts);
2016 break;
2017 case YANG_VALUE:
2018 case YANG_POSITION:
2019 ret = parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts);
2020 break;
2021 case YANG_CUSTOM:
2022 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts);
2023 break;
2024 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002025 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002026 return LY_EVALID;
2027 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002028 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002029 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002030 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002031
2032 return ret;
2033}
2034
Michal Vaskoea5abea2018-09-18 13:10:54 +02002035/**
2036 * @brief Parse the fraction-digits statement. Substatement of type statement.
2037 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002038 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002039 * @param[in,out] data Data to read from, always moved to currently handled character.
2040 * @param[in,out] fracdig Value to write to.
2041 * @param[in,out] exts Extension instances to add to.
2042 *
2043 * @return LY_ERR values.
2044 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002045static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002046parse_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 +02002047{
2048 LY_ERR ret = 0;
2049 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002050 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002051 unsigned long int num;
2052 enum yang_keyword kw;
2053
2054 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002055 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002056 return LY_EVALID;
2057 }
2058
2059 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002060 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002061 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002062
2063 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002064 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002065 free(buf);
2066 return LY_EVALID;
2067 }
2068
2069 errno = 0;
2070 num = strtoul(word, &ptr, 10);
2071 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002072 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002073 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002074 free(buf);
2075 return LY_EVALID;
2076 }
2077 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002078 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002079 free(buf);
2080 return LY_EVALID;
2081 }
2082 *fracdig = num;
2083 free(buf);
2084
2085 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002086 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002087
2088 switch (kw) {
2089 case YANG_CUSTOM:
2090 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002091 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002092 break;
2093 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002094 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002095 return LY_EVALID;
2096 }
2097 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002098 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002099
2100 return ret;
2101}
2102
Michal Vaskoea5abea2018-09-18 13:10:54 +02002103/**
2104 * @brief Parse the require-instance statement. Substatement of type statement.
2105 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002106 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002107 * @param[in,out] data Data to read from, always moved to currently handled character.
2108 * @param[in,out] reqinst Value to write to.
2109 * @param[in,out] flags Flags to write to.
2110 * @param[in,out] exts Extension instances to add to.
2111 *
2112 * @return LY_ERR values.
2113 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002114static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002115parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002116 struct lysp_ext_instance **exts)
2117{
2118 LY_ERR ret = 0;
2119 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002120 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002121 enum yang_keyword kw;
2122
2123 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002124 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002125 return LY_EVALID;
2126 }
2127 *flags |= LYS_SET_REQINST;
2128
2129 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002130 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002131 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002132
2133 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2134 *reqinst = 1;
2135 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002136 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002137 free(buf);
2138 return LY_EVALID;
2139 }
2140 free(buf);
2141
2142 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002143 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002144
2145 switch (kw) {
2146 case YANG_CUSTOM:
2147 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002148 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002149 break;
2150 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002151 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002152 return LY_EVALID;
2153 }
2154 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002155 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002156
2157 return ret;
2158}
2159
Michal Vaskoea5abea2018-09-18 13:10:54 +02002160/**
2161 * @brief Parse the modifier statement. Substatement of type pattern statement.
2162 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002163 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002164 * @param[in,out] data Data to read from, always moved to currently handled character.
2165 * @param[in,out] pat Value to write to.
2166 * @param[in,out] exts Extension instances to add to.
2167 *
2168 * @return LY_ERR values.
2169 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002170static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002171parse_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 +02002172{
2173 LY_ERR ret = 0;
2174 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002175 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002176 enum yang_keyword kw;
2177
2178 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002179 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002180 return LY_EVALID;
2181 }
2182
2183 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002184 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002185 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002186
2187 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002188 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189 free(buf);
2190 return LY_EVALID;
2191 }
2192 free(buf);
2193
2194 /* replace the value in the dictionary */
2195 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002196 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002197 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002198 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002199
2200 assert(buf[0] == 0x06);
2201 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002202 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002203
2204 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002205 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002206
2207 switch (kw) {
2208 case YANG_CUSTOM:
2209 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002210 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002211 break;
2212 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002213 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002214 return LY_EVALID;
2215 }
2216 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002217 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002218
2219 return ret;
2220}
2221
Michal Vaskoea5abea2018-09-18 13:10:54 +02002222/**
2223 * @brief Parse the pattern statement. Substatement of type statement.
2224 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002225 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002226 * @param[in,out] data Data to read from, always moved to currently handled character.
2227 * @param[in,out] patterns Restrictions to add to.
2228 *
2229 * @return LY_ERR values.
2230 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002231static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002232parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002233{
2234 LY_ERR ret = 0;
2235 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002236 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002237 enum yang_keyword kw;
2238 struct lysp_restr *restr;
2239
Radek Krejci2c4e7172018-10-19 15:56:26 +02002240 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002241
2242 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002243 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002244 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002245
2246 /* add special meaning first byte */
2247 if (buf) {
2248 buf = realloc(buf, word_len + 2);
2249 word = buf;
2250 } else {
2251 buf = malloc(word_len + 2);
2252 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002253 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002254 memmove(buf + 1, word, word_len);
2255 buf[0] = 0x06; /* pattern's default regular-match flag */
2256 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2257 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002258
2259 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002260 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002261
2262 switch (kw) {
2263 case YANG_DESCRIPTION:
2264 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
2265 break;
2266 case YANG_REFERENCE:
2267 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
2268 break;
2269 case YANG_ERROR_APP_TAG:
2270 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
2271 break;
2272 case YANG_ERROR_MESSAGE:
2273 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
2274 break;
2275 case YANG_MODIFIER:
2276 ret = parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts);
2277 break;
2278 case YANG_CUSTOM:
2279 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
2280 break;
2281 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002282 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002283 return LY_EVALID;
2284 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002285 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002286 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002287 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002288
2289 return ret;
2290}
2291
Michal Vaskoea5abea2018-09-18 13:10:54 +02002292/**
2293 * @brief Parse the type statement.
2294 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002295 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002296 * @param[in,out] data Data to read from, always moved to currently handled character.
2297 * @param[in,out] type Type to wrote to.
2298 *
2299 * @return LY_ERR values.
2300 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002301static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002302parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002303{
2304 LY_ERR ret = 0;
2305 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002306 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002307 enum yang_keyword kw;
2308 struct lysp_type *nest_type;
2309
2310 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002311 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002312 return LY_EVALID;
2313 }
2314
2315 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002316 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002317 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002318
Radek Krejci44ceedc2018-10-02 15:54:31 +02002319 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002320 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002321 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002322
2323 switch (kw) {
2324 case YANG_BASE:
2325 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts);
2326 break;
2327 case YANG_BIT:
2328 ret = parse_type_enum(ctx, data, kw, &type->bits);
2329 break;
2330 case YANG_ENUM:
2331 ret = parse_type_enum(ctx, data, kw, &type->enums);
2332 break;
2333 case YANG_FRACTION_DIGITS:
2334 ret = parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts);
2335 break;
2336 case YANG_LENGTH:
2337 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002338 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002339 return LY_EVALID;
2340 }
2341 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002342 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002343
2344 ret = parse_restr(ctx, data, kw, type->length);
2345 break;
2346 case YANG_PATH:
2347 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts);
2348 break;
2349 case YANG_PATTERN:
2350 ret = parse_type_pattern(ctx, data, &type->patterns);
2351 break;
2352 case YANG_RANGE:
2353 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002354 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002355 return LY_EVALID;
2356 }
2357 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002358 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002359
2360 ret = parse_restr(ctx, data, kw, type->range);
2361 break;
2362 case YANG_REQUIRE_INSTANCE:
2363 ret = parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts);
2364 break;
2365 case YANG_TYPE:
2366 {
Radek Krejci2c4e7172018-10-19 15:56:26 +02002367 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002368 }
2369 ret = parse_type(ctx, data, nest_type);
2370 break;
2371 case YANG_CUSTOM:
2372 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts);
2373 break;
2374 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002375 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002376 return LY_EVALID;
2377 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002378 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002379 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002380 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002381
2382 return ret;
2383}
2384
Michal Vaskoea5abea2018-09-18 13:10:54 +02002385/**
2386 * @brief Parse the leaf statement.
2387 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002388 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002389 * @param[in,out] data Data to read from, always moved to currently handled character.
2390 * @param[in,out] siblings Siblings to add to.
2391 *
2392 * @return LY_ERR values.
2393 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002394static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002395parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002396{
2397 LY_ERR ret = 0;
2398 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002399 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002400 enum yang_keyword kw;
2401 struct lysp_node *iter;
2402 struct lysp_node_leaf *leaf;
2403
2404 /* create structure */
2405 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002406 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002407 leaf->nodetype = LYS_LEAF;
2408
2409 /* insert into siblings */
2410 if (!*siblings) {
2411 *siblings = (struct lysp_node *)leaf;
2412 } else {
2413 for (iter = *siblings; iter->next; iter = iter->next);
2414 iter->next = (struct lysp_node *)leaf;
2415 }
2416
2417 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002418 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002419 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002420
Radek Krejci44ceedc2018-10-02 15:54:31 +02002421 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002422
2423 /* parse substatements */
2424 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002425 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002426
2427 switch (kw) {
2428 case YANG_CONFIG:
2429 ret = parse_config(ctx, data, &leaf->flags, &leaf->exts);
2430 break;
2431 case YANG_DEFAULT:
2432 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts);
2433 break;
2434 case YANG_DESCRIPTION:
2435 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts);
2436 break;
2437 case YANG_IF_FEATURE:
2438 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts);
2439 break;
2440 case YANG_MANDATORY:
2441 ret = parse_mandatory(ctx, data, &leaf->flags, &leaf->exts);
2442 break;
2443 case YANG_MUST:
2444 ret = parse_restrs(ctx, data, kw, &leaf->musts);
2445 break;
2446 case YANG_REFERENCE:
2447 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts);
2448 break;
2449 case YANG_STATUS:
2450 ret = parse_status(ctx, data, &leaf->flags, &leaf->exts);
2451 break;
2452 case YANG_TYPE:
2453 ret = parse_type(ctx, data, &leaf->type);
2454 break;
2455 case YANG_UNITS:
2456 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts);
2457 break;
2458 case YANG_WHEN:
2459 ret = parse_when(ctx, data, &leaf->when);
2460 break;
2461 case YANG_CUSTOM:
2462 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts);
2463 break;
2464 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002465 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002466 return LY_EVALID;
2467 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002468 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002469 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002470 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002471
2472 /* mandatory substatements */
2473 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002474 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002475 return LY_EVALID;
2476 }
2477
2478 return ret;
2479}
2480
Michal Vaskoea5abea2018-09-18 13:10:54 +02002481/**
2482 * @brief Parse the max-elements statement.
2483 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002484 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002485 * @param[in,out] data Data to read from, always moved to currently handled character.
2486 * @param[in,out] max Value to write to.
2487 * @param[in,out] flags Flags to write to.
2488 * @param[in,out] exts Extension instances to add to.
2489 *
2490 * @return LY_ERR values.
2491 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002492static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002493parse_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 +02002494{
2495 LY_ERR ret = 0;
2496 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002497 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002498 unsigned long int num;
2499 enum yang_keyword kw;
2500
2501 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002502 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002503 return LY_EVALID;
2504 }
2505 *flags |= LYS_SET_MAX;
2506
2507 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002508 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002509 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002510
2511 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002512 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002513 free(buf);
2514 return LY_EVALID;
2515 }
2516
2517 if (strncmp(word, "unbounded", word_len)) {
2518 errno = 0;
2519 num = strtoul(word, &ptr, 10);
2520 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002521 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002522 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002523 free(buf);
2524 return LY_EVALID;
2525 }
2526 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002527 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002528 free(buf);
2529 return LY_EVALID;
2530 }
2531
2532 *max = num;
2533 }
2534 free(buf);
2535
2536 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002537 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002538
2539 switch (kw) {
2540 case YANG_CUSTOM:
2541 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002542 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002543 break;
2544 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002545 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002546 return LY_EVALID;
2547 }
2548 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002549 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002550
2551 return ret;
2552}
2553
Michal Vaskoea5abea2018-09-18 13:10:54 +02002554/**
2555 * @brief Parse the min-elements statement.
2556 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002557 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002558 * @param[in,out] data Data to read from, always moved to currently handled character.
2559 * @param[in,out] min Value to write to.
2560 * @param[in,out] flags Flags to write to.
2561 * @param[in,out] exts Extension instances to add to.
2562 *
2563 * @return LY_ERR values.
2564 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002565static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002566parse_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 +02002567{
2568 LY_ERR ret = 0;
2569 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002570 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002571 unsigned long int num;
2572 enum yang_keyword kw;
2573
2574 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002575 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002576 return LY_EVALID;
2577 }
2578 *flags |= LYS_SET_MIN;
2579
2580 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002581 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002582 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002583
2584 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002585 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002586 free(buf);
2587 return LY_EVALID;
2588 }
2589
2590 errno = 0;
2591 num = strtoul(word, &ptr, 10);
2592 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002593 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002594 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002595 free(buf);
2596 return LY_EVALID;
2597 }
2598 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002599 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002600 free(buf);
2601 return LY_EVALID;
2602 }
2603 *min = num;
2604 free(buf);
2605
2606 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002607 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002608
2609 switch (kw) {
2610 case YANG_CUSTOM:
2611 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002612 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002613 break;
2614 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002615 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002616 return LY_EVALID;
2617 }
2618 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002619 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002620
2621 return ret;
2622}
2623
Michal Vaskoea5abea2018-09-18 13:10:54 +02002624/**
2625 * @brief Parse the ordered-by statement.
2626 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002627 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002628 * @param[in,out] data Data to read from, always moved to currently handled character.
2629 * @param[in,out] flags Flags to write to.
2630 * @param[in,out] exts Extension instances to add to.
2631 *
2632 * @return LY_ERR values.
2633 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002634static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002635parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636{
2637 LY_ERR ret = 0;
2638 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002639 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002640 enum yang_keyword kw;
2641
2642 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002643 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002644 return LY_EVALID;
2645 }
2646
2647 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002648 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002649 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002650
2651 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2652 *flags |= LYS_ORDBY_SYSTEM;
2653 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2654 *flags |= LYS_ORDBY_USER;
2655 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002656 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002657 free(buf);
2658 return LY_EVALID;
2659 }
2660 free(buf);
2661
2662 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002663 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002664
2665 switch (kw) {
2666 case YANG_CUSTOM:
2667 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002668 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002669 break;
2670 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002671 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002672 return LY_EVALID;
2673 }
2674 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002675 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002676
2677 return ret;
2678}
2679
Michal Vaskoea5abea2018-09-18 13:10:54 +02002680/**
2681 * @brief Parse the leaf-list statement.
2682 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002683 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002684 * @param[in,out] data Data to read from, always moved to currently handled character.
2685 * @param[in,out] siblings Siblings to add to.
2686 *
2687 * @return LY_ERR values.
2688 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002689static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002690parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002691{
2692 LY_ERR ret = 0;
2693 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002694 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695 enum yang_keyword kw;
2696 struct lysp_node *iter;
2697 struct lysp_node_leaflist *llist;
2698
2699 /* create structure */
2700 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002701 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002702 llist->nodetype = LYS_LEAFLIST;
2703
2704 /* insert into siblings */
2705 if (!*siblings) {
2706 *siblings = (struct lysp_node *)llist;
2707 } else {
2708 for (iter = *siblings; iter->next; iter = iter->next);
2709 iter->next = (struct lysp_node *)llist;
2710 }
2711
2712 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002713 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002714 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002715
Radek Krejci44ceedc2018-10-02 15:54:31 +02002716 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002717
2718 /* parse substatements */
2719 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002720 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002721
2722 switch (kw) {
2723 case YANG_CONFIG:
2724 ret = parse_config(ctx, data, &llist->flags, &llist->exts);
2725 break;
2726 case YANG_DEFAULT:
2727 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts);
2728 break;
2729 case YANG_DESCRIPTION:
2730 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts);
2731 break;
2732 case YANG_IF_FEATURE:
2733 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts);
2734 break;
2735 case YANG_MAX_ELEMENTS:
2736 ret = parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts);
2737 break;
2738 case YANG_MIN_ELEMENTS:
2739 ret = parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts);
2740 break;
2741 case YANG_MUST:
2742 ret = parse_restrs(ctx, data, kw, &llist->musts);
2743 break;
2744 case YANG_ORDERED_BY:
2745 ret = parse_orderedby(ctx, data, &llist->flags, &llist->exts);
2746 break;
2747 case YANG_REFERENCE:
2748 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts);
2749 break;
2750 case YANG_STATUS:
2751 ret = parse_status(ctx, data, &llist->flags, &llist->exts);
2752 break;
2753 case YANG_TYPE:
2754 ret = parse_type(ctx, data, &llist->type);
2755 break;
2756 case YANG_UNITS:
2757 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts);
2758 break;
2759 case YANG_WHEN:
2760 ret = parse_when(ctx, data, &llist->when);
2761 break;
2762 case YANG_CUSTOM:
2763 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts);
2764 break;
2765 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002766 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002767 return LY_EVALID;
2768 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002769 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002770 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002771 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002772
2773 /* mandatory substatements */
2774 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002775 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002776 return LY_EVALID;
2777 }
2778
2779 return ret;
2780}
2781
Michal Vaskoea5abea2018-09-18 13:10:54 +02002782/**
2783 * @brief Parse the refine statement.
2784 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002785 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002786 * @param[in,out] data Data to read from, always moved to currently handled character.
2787 * @param[in,out] refines Refines to add to.
2788 *
2789 * @return LY_ERR values.
2790 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002791static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002792parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002793{
2794 LY_ERR ret = 0;
2795 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002796 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002797 enum yang_keyword kw;
2798 struct lysp_refine *rf;
2799
Radek Krejci2c4e7172018-10-19 15:56:26 +02002800 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002801
2802 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002803 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002804 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002805
Radek Krejci44ceedc2018-10-02 15:54:31 +02002806 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002807 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002808 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809
2810 switch (kw) {
2811 case YANG_CONFIG:
2812 ret = parse_config(ctx, data, &rf->flags, &rf->exts);
2813 break;
2814 case YANG_DEFAULT:
2815 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts);
2816 break;
2817 case YANG_DESCRIPTION:
2818 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts);
2819 break;
2820 case YANG_IF_FEATURE:
2821 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts);
2822 break;
2823 case YANG_MAX_ELEMENTS:
2824 ret = parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts);
2825 break;
2826 case YANG_MIN_ELEMENTS:
2827 ret = parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts);
2828 break;
2829 case YANG_MUST:
2830 ret = parse_restrs(ctx, data, kw, &rf->musts);
2831 break;
2832 case YANG_MANDATORY:
2833 ret = parse_mandatory(ctx, data, &rf->flags, &rf->exts);
2834 break;
2835 case YANG_REFERENCE:
2836 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts);
2837 break;
2838 case YANG_PRESENCE:
2839 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts);
2840 break;
2841 case YANG_CUSTOM:
2842 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts);
2843 break;
2844 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002845 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846 return LY_EVALID;
2847 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002848 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002849 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002850 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002851
2852 return ret;
2853}
2854
Michal Vaskoea5abea2018-09-18 13:10:54 +02002855/**
2856 * @brief Parse the typedef statement.
2857 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002858 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002859 * @param[in,out] data Data to read from, always moved to currently handled character.
2860 * @param[in,out] typedefs Typedefs to add to.
2861 *
2862 * @return LY_ERR values.
2863 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002864static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002865parse_typedef(struct ly_parser_ctx *ctx, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002866{
2867 LY_ERR ret = 0;
2868 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002869 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002870 enum yang_keyword kw;
2871 struct lysp_tpdf *tpdf;
2872
Radek Krejci2c4e7172018-10-19 15:56:26 +02002873 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002874
2875 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002876 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002877 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002878
Radek Krejci44ceedc2018-10-02 15:54:31 +02002879 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002880
2881 /* parse substatements */
2882 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002883 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002884
2885 switch (kw) {
2886 case YANG_DEFAULT:
2887 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts);
2888 break;
2889 case YANG_DESCRIPTION:
2890 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts);
2891 break;
2892 case YANG_REFERENCE:
2893 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts);
2894 break;
2895 case YANG_STATUS:
2896 ret = parse_status(ctx, data, &tpdf->flags, &tpdf->exts);
2897 break;
2898 case YANG_TYPE:
2899 ret = parse_type(ctx, data, &tpdf->type);
2900 break;
2901 case YANG_UNITS:
2902 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts);
2903 break;
2904 case YANG_CUSTOM:
2905 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts);
2906 break;
2907 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002908 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002909 return LY_EVALID;
2910 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002911 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002912 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002913 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002914
2915 /* mandatory substatements */
2916 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002917 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918 return LY_EVALID;
2919 }
2920
2921 return ret;
2922}
2923
Michal Vaskoea5abea2018-09-18 13:10:54 +02002924/**
2925 * @brief Parse the input or output statement.
2926 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002927 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002928 * @param[in,out] data Data to read from, always moved to currently handled character.
2929 * @param[in] kw Type of this particular keyword
2930 * @param[in,out] inout_p Input/output pointer to write to.
2931 *
2932 * @return LY_ERR values.
2933 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002934static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002935parse_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 +02002936{
2937 LY_ERR ret = 0;
2938 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002939 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002940 struct lysp_action_inout *inout;
2941
2942 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002943 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002944 return LY_EVALID;
2945 }
2946
2947 /* create structure */
2948 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002949 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002950 *inout_p = inout;
2951
2952 /* parse substatements */
2953 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002954 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002955
2956 switch (kw) {
2957 case YANG_ANYDATA:
2958 case YANG_ANYXML:
2959 ret = parse_any(ctx, data, kw, &inout->data);
2960 break;
2961 case YANG_CHOICE:
2962 ret = parse_choice(ctx, data, &inout->data);
2963 break;
2964 case YANG_CONTAINER:
2965 ret = parse_container(ctx, data, &inout->data);
2966 break;
2967 case YANG_LEAF:
2968 ret = parse_leaf(ctx, data, &inout->data);
2969 break;
2970 case YANG_LEAF_LIST:
2971 ret = parse_leaflist(ctx, data, &inout->data);
2972 break;
2973 case YANG_LIST:
2974 ret = parse_list(ctx, data, &inout->data);
2975 break;
2976 case YANG_USES:
2977 ret = parse_uses(ctx, data, &inout->data);
2978 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002979 case YANG_TYPEDEF:
2980 ret = parse_typedef(ctx, data, &inout->typedefs);
2981 break;
2982 case YANG_MUST:
2983 ret = parse_restrs(ctx, data, kw, &inout->musts);
2984 break;
2985 case YANG_GROUPING:
2986 ret = parse_grouping(ctx, data, &inout->groupings);
2987 break;
2988 case YANG_CUSTOM:
2989 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts);
2990 break;
2991 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002992 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002993 return LY_EVALID;
2994 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002995 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002996 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002997 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002998
2999 return ret;
3000}
3001
Michal Vaskoea5abea2018-09-18 13:10:54 +02003002/**
3003 * @brief Parse the action statement.
3004 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003005 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003006 * @param[in,out] data Data to read from, always moved to currently handled character.
3007 * @param[in,out] actions Actions to add to.
3008 *
3009 * @return LY_ERR values.
3010 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003011static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003012parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003013{
3014 LY_ERR ret = 0;
3015 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003016 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003017 enum yang_keyword kw;
3018 struct lysp_action *act;
3019
Radek Krejci2c4e7172018-10-19 15:56:26 +02003020 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003021
3022 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003023 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003024 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003025
Radek Krejci44ceedc2018-10-02 15:54:31 +02003026 INSERT_WORD(ctx, buf, act->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003027 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003028 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003029
3030 switch (kw) {
3031 case YANG_DESCRIPTION:
3032 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts);
3033 break;
3034 case YANG_IF_FEATURE:
3035 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts);
3036 break;
3037 case YANG_REFERENCE:
3038 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts);
3039 break;
3040 case YANG_STATUS:
3041 ret = parse_status(ctx, data, &act->flags, &act->exts);
3042 break;
3043
3044 case YANG_INPUT:
3045 ret = parse_inout(ctx, data, kw, &act->input);
3046 break;
3047 case YANG_OUTPUT:
3048 ret = parse_inout(ctx, data, kw, &act->output);
3049 break;
3050
3051 case YANG_TYPEDEF:
3052 ret = parse_typedef(ctx, data, &act->typedefs);
3053 break;
3054 case YANG_GROUPING:
3055 ret = parse_grouping(ctx, data, &act->groupings);
3056 break;
3057 case YANG_CUSTOM:
3058 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts);
3059 break;
3060 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003061 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003062 return LY_EVALID;
3063 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003064 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003065 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003066 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003067
3068 return ret;
3069}
3070
Michal Vaskoea5abea2018-09-18 13:10:54 +02003071/**
3072 * @brief Parse the notification statement.
3073 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003074 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003075 * @param[in,out] data Data to read from, always moved to currently handled character.
3076 * @param[in,out] notifs Notifications to add to.
3077 *
3078 * @return LY_ERR values.
3079 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003080static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003081parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003082{
3083 LY_ERR ret = 0;
3084 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003085 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003086 enum yang_keyword kw;
3087 struct lysp_notif *notif;
3088
Radek Krejci2c4e7172018-10-19 15:56:26 +02003089 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003090
3091 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003092 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003093 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003094
Radek Krejci44ceedc2018-10-02 15:54:31 +02003095 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003096 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003097 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003098
3099 switch (kw) {
3100 case YANG_DESCRIPTION:
3101 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts);
3102 break;
3103 case YANG_IF_FEATURE:
3104 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts);
3105 break;
3106 case YANG_REFERENCE:
3107 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts);
3108 break;
3109 case YANG_STATUS:
3110 ret = parse_status(ctx, data, &notif->flags, &notif->exts);
3111 break;
3112
3113 case YANG_ANYDATA:
3114 case YANG_ANYXML:
3115 ret = parse_any(ctx, data, kw, &notif->data);
3116 break;
3117 case YANG_CHOICE:
3118 ret = parse_case(ctx, data, &notif->data);
3119 break;
3120 case YANG_CONTAINER:
3121 ret = parse_container(ctx, data, &notif->data);
3122 break;
3123 case YANG_LEAF:
3124 ret = parse_leaf(ctx, data, &notif->data);
3125 break;
3126 case YANG_LEAF_LIST:
3127 ret = parse_leaflist(ctx, data, &notif->data);
3128 break;
3129 case YANG_LIST:
3130 ret = parse_list(ctx, data, &notif->data);
3131 break;
3132 case YANG_USES:
3133 ret = parse_uses(ctx, data, &notif->data);
3134 break;
3135
3136 case YANG_MUST:
3137 ret = parse_restrs(ctx, data, kw, &notif->musts);
3138 break;
3139 case YANG_TYPEDEF:
3140 ret = parse_typedef(ctx, data, &notif->typedefs);
3141 break;
3142 case YANG_GROUPING:
3143 ret = parse_grouping(ctx, data, &notif->groupings);
3144 break;
3145 case YANG_CUSTOM:
3146 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts);
3147 break;
3148 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003149 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003150 return LY_EVALID;
3151 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003152 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003153 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003154 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003155
3156 return ret;
3157}
3158
Michal Vaskoea5abea2018-09-18 13:10:54 +02003159/**
3160 * @brief Parse the grouping statement.
3161 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003162 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003163 * @param[in,out] data Data to read from, always moved to currently handled character.
3164 * @param[in,out] groupings Groupings to add to.
3165 *
3166 * @return LY_ERR values.
3167 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003168static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003169parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003170{
3171 LY_ERR ret = 0;
3172 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003173 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003174 enum yang_keyword kw;
3175 struct lysp_grp *grp;
3176
Radek Krejci2c4e7172018-10-19 15:56:26 +02003177 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003178
3179 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003180 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003181 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003182
Radek Krejci44ceedc2018-10-02 15:54:31 +02003183 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003184
3185 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003186 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003187
3188 switch (kw) {
3189 case YANG_DESCRIPTION:
3190 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts);
3191 break;
3192 case YANG_REFERENCE:
3193 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts);
3194 break;
3195 case YANG_STATUS:
3196 ret = parse_status(ctx, data, &grp->flags, &grp->exts);
3197 break;
3198
3199 case YANG_ANYDATA:
3200 case YANG_ANYXML:
3201 ret = parse_any(ctx, data, kw, &grp->data);
3202 break;
3203 case YANG_CHOICE:
3204 ret = parse_choice(ctx, data, &grp->data);
3205 break;
3206 case YANG_CONTAINER:
3207 ret = parse_container(ctx, data, &grp->data);
3208 break;
3209 case YANG_LEAF:
3210 ret = parse_leaf(ctx, data, &grp->data);
3211 break;
3212 case YANG_LEAF_LIST:
3213 ret = parse_leaflist(ctx, data, &grp->data);
3214 break;
3215 case YANG_LIST:
3216 ret = parse_list(ctx, data, &grp->data);
3217 break;
3218 case YANG_USES:
3219 ret = parse_uses(ctx, data, &grp->data);
3220 break;
3221
3222 case YANG_TYPEDEF:
3223 ret = parse_typedef(ctx, data, &grp->typedefs);
3224 break;
3225 case YANG_ACTION:
3226 ret = parse_action(ctx, data, &grp->actions);
3227 break;
3228 case YANG_GROUPING:
3229 ret = parse_grouping(ctx, data, &grp->groupings);
3230 break;
3231 case YANG_NOTIFICATION:
3232 ret = parse_notif(ctx, data, &grp->notifs);
3233 break;
3234 case YANG_CUSTOM:
3235 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts);
3236 break;
3237 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003238 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003239 return LY_EVALID;
3240 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003241 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003242 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003243 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003244
3245 return ret;
3246}
3247
Michal Vaskoea5abea2018-09-18 13:10:54 +02003248/**
3249 * @brief Parse the refine statement.
3250 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003251 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003252 * @param[in,out] data Data to read from, always moved to currently handled character.
3253 * @param[in,out] augments Augments to add to.
3254 *
3255 * @return LY_ERR values.
3256 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003257static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003258parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003259{
3260 LY_ERR ret = 0;
3261 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003262 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003263 enum yang_keyword kw;
3264 struct lysp_augment *aug;
3265
Radek Krejci2c4e7172018-10-19 15:56:26 +02003266 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003267
3268 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003269 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003270 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003271
Radek Krejci44ceedc2018-10-02 15:54:31 +02003272 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003273 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003274 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003275
3276 switch (kw) {
3277 case YANG_DESCRIPTION:
3278 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts);
3279 break;
3280 case YANG_IF_FEATURE:
3281 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts);
3282 break;
3283 case YANG_REFERENCE:
3284 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts);
3285 break;
3286 case YANG_STATUS:
3287 ret = parse_status(ctx, data, &aug->flags, &aug->exts);
3288 break;
3289 case YANG_WHEN:
3290 ret = parse_when(ctx, data, &aug->when);
3291 break;
3292
3293 case YANG_ANYDATA:
3294 case YANG_ANYXML:
3295 ret = parse_any(ctx, data, kw, &aug->child);
3296 break;
3297 case YANG_CASE:
3298 ret = parse_case(ctx, data, &aug->child);
3299 break;
3300 case YANG_CHOICE:
3301 ret = parse_choice(ctx, data, &aug->child);
3302 break;
3303 case YANG_CONTAINER:
3304 ret = parse_container(ctx, data, &aug->child);
3305 break;
3306 case YANG_LEAF:
3307 ret = parse_leaf(ctx, data, &aug->child);
3308 break;
3309 case YANG_LEAF_LIST:
3310 ret = parse_leaflist(ctx, data, &aug->child);
3311 break;
3312 case YANG_LIST:
3313 ret = parse_list(ctx, data, &aug->child);
3314 break;
3315 case YANG_USES:
3316 ret = parse_uses(ctx, data, &aug->child);
3317 break;
3318
3319 case YANG_ACTION:
3320 ret = parse_action(ctx, data, &aug->actions);
3321 break;
3322 case YANG_NOTIFICATION:
3323 ret = parse_notif(ctx, data, &aug->notifs);
3324 break;
3325 case YANG_CUSTOM:
3326 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts);
3327 break;
3328 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003329 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003330 return LY_EVALID;
3331 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003332 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003333 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003334 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003335
3336 return ret;
3337}
3338
Michal Vaskoea5abea2018-09-18 13:10:54 +02003339/**
3340 * @brief Parse the uses statement.
3341 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003342 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003343 * @param[in,out] data Data to read from, always moved to currently handled character.
3344 * @param[in,out] siblings Siblings to add to.
3345 *
3346 * @return LY_ERR values.
3347 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003348static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003349parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003350{
3351 LY_ERR ret = 0;
3352 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003353 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003354 enum yang_keyword kw;
3355 struct lysp_node *iter;
3356 struct lysp_node_uses *uses;
3357
3358 /* create structure */
3359 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003360 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003361 uses->nodetype = LYS_USES;
3362
3363 /* insert into siblings */
3364 if (!*siblings) {
3365 *siblings = (struct lysp_node *)uses;
3366 } else {
3367 for (iter = *siblings; iter->next; iter = iter->next);
3368 iter->next = (struct lysp_node *)uses;
3369 }
3370
3371 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003372 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003373 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003374
Radek Krejci44ceedc2018-10-02 15:54:31 +02003375 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003376
3377 /* parse substatements */
3378 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003379 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003380
3381 switch (kw) {
3382 case YANG_DESCRIPTION:
3383 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts);
3384 break;
3385 case YANG_IF_FEATURE:
3386 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts);
3387 break;
3388 case YANG_REFERENCE:
3389 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts);
3390 break;
3391 case YANG_STATUS:
3392 ret = parse_status(ctx, data, &uses->flags, &uses->exts);
3393 break;
3394 case YANG_WHEN:
3395 ret = parse_when(ctx, data, &uses->when);
3396 break;
3397
3398 case YANG_REFINE:
3399 ret = parse_refine(ctx, data, &uses->refines);
3400 break;
3401 case YANG_AUGMENT:
3402 ret = parse_augment(ctx, data, &uses->augments);
3403 break;
3404 case YANG_CUSTOM:
3405 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts);
3406 break;
3407 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003408 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003409 return LY_EVALID;
3410 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003411 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003412 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003413 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003414
3415 return ret;
3416}
3417
Michal Vaskoea5abea2018-09-18 13:10:54 +02003418/**
3419 * @brief Parse the case statement.
3420 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003421 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003422 * @param[in,out] data Data to read from, always moved to currently handled character.
3423 * @param[in,out] siblings Siblings to add to.
3424 *
3425 * @return LY_ERR values.
3426 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003427static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003428parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003429{
3430 LY_ERR ret = 0;
3431 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003432 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003433 enum yang_keyword kw;
3434 struct lysp_node *iter;
3435 struct lysp_node_case *cas;
3436
3437 /* create structure */
3438 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003439 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003440 cas->nodetype = LYS_CASE;
3441
3442 /* insert into siblings */
3443 if (!*siblings) {
3444 *siblings = (struct lysp_node *)cas;
3445 } else {
3446 for (iter = *siblings; iter->next; iter = iter->next);
3447 iter->next = (struct lysp_node *)cas;
3448 }
3449
3450 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003451 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003452 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003453
Radek Krejci44ceedc2018-10-02 15:54:31 +02003454 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003455
3456 /* parse substatements */
3457 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003458 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003459
3460 switch (kw) {
3461 case YANG_DESCRIPTION:
3462 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts);
3463 break;
3464 case YANG_IF_FEATURE:
3465 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts);
3466 break;
3467 case YANG_REFERENCE:
3468 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts);
3469 break;
3470 case YANG_STATUS:
3471 ret = parse_status(ctx, data, &cas->flags, &cas->exts);
3472 break;
3473 case YANG_WHEN:
3474 ret = parse_when(ctx, data, &cas->when);
3475 break;
3476
3477 case YANG_ANYDATA:
3478 case YANG_ANYXML:
3479 ret = parse_any(ctx, data, kw, &cas->child);
3480 break;
3481 case YANG_CHOICE:
3482 ret = parse_case(ctx, data, &cas->child);
3483 break;
3484 case YANG_CONTAINER:
3485 ret = parse_container(ctx, data, &cas->child);
3486 break;
3487 case YANG_LEAF:
3488 ret = parse_leaf(ctx, data, &cas->child);
3489 break;
3490 case YANG_LEAF_LIST:
3491 ret = parse_leaflist(ctx, data, &cas->child);
3492 break;
3493 case YANG_LIST:
3494 ret = parse_list(ctx, data, &cas->child);
3495 break;
3496 case YANG_USES:
3497 ret = parse_uses(ctx, data, &cas->child);
3498 break;
3499 case YANG_CUSTOM:
3500 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts);
3501 break;
3502 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003503 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003504 return LY_EVALID;
3505 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003506 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003507 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003508 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003509
3510 return ret;
3511}
3512
Michal Vaskoea5abea2018-09-18 13:10:54 +02003513/**
3514 * @brief Parse the choice statement.
3515 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003516 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003517 * @param[in,out] data Data to read from, always moved to currently handled character.
3518 * @param[in,out] siblings Siblings to add to.
3519 *
3520 * @return LY_ERR values.
3521 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003522static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003523parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003524{
3525 LY_ERR ret = 0;
3526 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003527 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003528 enum yang_keyword kw;
3529 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003530 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003531
3532 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003533 choice = calloc(1, sizeof *choice);
3534 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3535 choice->nodetype = LYS_CHOICE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536
3537 /* insert into siblings */
3538 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003539 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003540 } else {
3541 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003542 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 }
3544
3545 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003546 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003547 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003548
Radek Krejci44ceedc2018-10-02 15:54:31 +02003549 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003550
3551 /* parse substatements */
3552 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003553 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003554
3555 switch (kw) {
3556 case YANG_CONFIG:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003557 ret = parse_config(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 break;
3559 case YANG_DESCRIPTION:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003560 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561 break;
3562 case YANG_IF_FEATURE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003563 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003564 break;
3565 case YANG_MANDATORY:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003566 ret = parse_mandatory(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567 break;
3568 case YANG_REFERENCE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003569 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003570 break;
3571 case YANG_STATUS:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003572 ret = parse_status(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003573 break;
3574 case YANG_WHEN:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003575 ret = parse_when(ctx, data, &choice->when);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003576 break;
3577 case YANG_DEFAULT:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003578 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_IDENTIF_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003579 break;
3580
3581 case YANG_ANYDATA:
3582 case YANG_ANYXML:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003583 ret = parse_any(ctx, data, kw, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584 break;
3585 case YANG_CASE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003586 ret = parse_case(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003587 break;
3588 case YANG_CHOICE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003589 ret = parse_choice(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590 break;
3591 case YANG_CONTAINER:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003592 ret = parse_container(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003593 break;
3594 case YANG_LEAF:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003595 ret = parse_leaf(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003596 break;
3597 case YANG_LEAF_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003598 ret = parse_leaflist(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003599 break;
3600 case YANG_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003601 ret = parse_list(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003602 break;
3603 case YANG_CUSTOM:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003604 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003605 break;
3606 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003607 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003608 return LY_EVALID;
3609 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003610 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003611 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003612 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613
3614 return ret;
3615}
3616
Michal Vaskoea5abea2018-09-18 13:10:54 +02003617/**
3618 * @brief Parse the container statement.
3619 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003620 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003621 * @param[in,out] data Data to read from, always moved to currently handled character.
3622 * @param[in,out] siblings Siblings to add to.
3623 *
3624 * @return LY_ERR values.
3625 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003626static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003627parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003628{
3629 LY_ERR ret = 0;
3630 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003631 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003632 enum yang_keyword kw;
3633 struct lysp_node *iter;
3634 struct lysp_node_container *cont;
3635
3636 /* create structure */
3637 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003638 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003639 cont->nodetype = LYS_CONTAINER;
3640
3641 /* insert into siblings */
3642 if (!*siblings) {
3643 *siblings = (struct lysp_node *)cont;
3644 } else {
3645 for (iter = *siblings; iter->next; iter = iter->next);
3646 iter->next = (struct lysp_node *)cont;
3647 }
3648
3649 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003650 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003651 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003652
Radek Krejci44ceedc2018-10-02 15:54:31 +02003653 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003654
3655 /* parse substatements */
3656 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003657 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003658
3659 switch (kw) {
3660 case YANG_CONFIG:
3661 ret = parse_config(ctx, data, &cont->flags, &cont->exts);
3662 break;
3663 case YANG_DESCRIPTION:
3664 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts);
3665 break;
3666 case YANG_IF_FEATURE:
3667 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts);
3668 break;
3669 case YANG_REFERENCE:
3670 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts);
3671 break;
3672 case YANG_STATUS:
3673 ret = parse_status(ctx, data, &cont->flags, &cont->exts);
3674 break;
3675 case YANG_WHEN:
3676 ret = parse_when(ctx, data, &cont->when);
3677 break;
3678 case YANG_PRESENCE:
3679 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts);
3680 break;
3681
3682 case YANG_ANYDATA:
3683 case YANG_ANYXML:
3684 ret = parse_any(ctx, data, kw, &cont->child);
3685 break;
3686 case YANG_CHOICE:
3687 ret = parse_choice(ctx, data, &cont->child);
3688 break;
3689 case YANG_CONTAINER:
3690 ret = parse_container(ctx, data, &cont->child);
3691 break;
3692 case YANG_LEAF:
3693 ret = parse_leaf(ctx, data, &cont->child);
3694 break;
3695 case YANG_LEAF_LIST:
3696 ret = parse_leaflist(ctx, data, &cont->child);
3697 break;
3698 case YANG_LIST:
3699 ret = parse_list(ctx, data, &cont->child);
3700 break;
3701 case YANG_USES:
3702 ret = parse_uses(ctx, data, &cont->child);
3703 break;
3704
3705 case YANG_TYPEDEF:
3706 ret = parse_typedef(ctx, data, &cont->typedefs);
3707 break;
3708 case YANG_MUST:
3709 ret = parse_restrs(ctx, data, kw, &cont->musts);
3710 break;
3711 case YANG_ACTION:
3712 ret = parse_action(ctx, data, &cont->actions);
3713 break;
3714 case YANG_GROUPING:
3715 ret = parse_grouping(ctx, data, &cont->groupings);
3716 break;
3717 case YANG_NOTIFICATION:
3718 ret = parse_notif(ctx, data, &cont->notifs);
3719 break;
3720 case YANG_CUSTOM:
3721 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts);
3722 break;
3723 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003724 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725 return LY_EVALID;
3726 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003727 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003728 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003729 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003730
3731 return ret;
3732}
3733
Michal Vaskoea5abea2018-09-18 13:10:54 +02003734/**
3735 * @brief Parse the list statement.
3736 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003737 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003738 * @param[in,out] data Data to read from, always moved to currently handled character.
3739 * @param[in,out] siblings Siblings to add to.
3740 *
3741 * @return LY_ERR values.
3742 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003743static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003744parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003745{
3746 LY_ERR ret = 0;
3747 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003748 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003749 enum yang_keyword kw;
3750 struct lysp_node *iter;
3751 struct lysp_node_list *list;
3752
3753 /* create structure */
3754 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003755 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003756 list->nodetype = LYS_LIST;
3757
3758 /* insert into siblings */
3759 if (!*siblings) {
3760 *siblings = (struct lysp_node *)list;
3761 } else {
3762 for (iter = *siblings; iter->next; iter = iter->next);
3763 iter->next = (struct lysp_node *)list;
3764 }
3765
3766 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003767 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003768 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003769
Radek Krejci44ceedc2018-10-02 15:54:31 +02003770 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003771
3772 /* parse substatements */
3773 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003774 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003775
3776 switch (kw) {
3777 case YANG_CONFIG:
3778 ret = parse_config(ctx, data, &list->flags, &list->exts);
3779 break;
3780 case YANG_DESCRIPTION:
3781 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts);
3782 break;
3783 case YANG_IF_FEATURE:
3784 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts);
3785 break;
3786 case YANG_REFERENCE:
3787 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts);
3788 break;
3789 case YANG_STATUS:
3790 ret = parse_status(ctx, data, &list->flags, &list->exts);
3791 break;
3792 case YANG_WHEN:
3793 ret = parse_when(ctx, data, &list->when);
3794 break;
3795 case YANG_KEY:
3796 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts);
3797 break;
3798 case YANG_MAX_ELEMENTS:
3799 ret = parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts);
3800 break;
3801 case YANG_MIN_ELEMENTS:
3802 ret = parse_minelements(ctx, data, &list->min, &list->flags, &list->exts);
3803 break;
3804 case YANG_ORDERED_BY:
3805 ret = parse_orderedby(ctx, data, &list->flags, &list->exts);
3806 break;
3807 case YANG_UNIQUE:
3808 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts);
3809 break;
3810
3811 case YANG_ANYDATA:
3812 case YANG_ANYXML:
3813 ret = parse_any(ctx, data, kw, &list->child);
3814 break;
3815 case YANG_CHOICE:
3816 ret = parse_choice(ctx, data, &list->child);
3817 break;
3818 case YANG_CONTAINER:
3819 ret = parse_container(ctx, data, &list->child);
3820 break;
3821 case YANG_LEAF:
3822 ret = parse_leaf(ctx, data, &list->child);
3823 break;
3824 case YANG_LEAF_LIST:
3825 ret = parse_leaflist(ctx, data, &list->child);
3826 break;
3827 case YANG_LIST:
3828 ret = parse_list(ctx, data, &list->child);
3829 break;
3830 case YANG_USES:
3831 ret = parse_uses(ctx, data, &list->child);
3832 break;
3833
3834 case YANG_TYPEDEF:
3835 ret = parse_typedef(ctx, data, &list->typedefs);
3836 break;
3837 case YANG_MUST:
3838 ret = parse_restrs(ctx, data, kw, &list->musts);
3839 break;
3840 case YANG_ACTION:
3841 ret = parse_action(ctx, data, &list->actions);
3842 break;
3843 case YANG_GROUPING:
3844 ret = parse_grouping(ctx, data, &list->groupings);
3845 break;
3846 case YANG_NOTIFICATION:
3847 ret = parse_notif(ctx, data, &list->notifs);
3848 break;
3849 case YANG_CUSTOM:
3850 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts);
3851 break;
3852 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003853 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003854 return LY_EVALID;
3855 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003856 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003858 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003859
3860 return ret;
3861}
3862
Michal Vaskoea5abea2018-09-18 13:10:54 +02003863/**
3864 * @brief Parse the yin-element statement.
3865 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003866 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003867 * @param[in,out] data Data to read from, always moved to currently handled character.
3868 * @param[in,out] flags Flags to write to.
3869 * @param[in,out] exts Extension instances to add to.
3870 *
3871 * @return LY_ERR values.
3872 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003873static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003874parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875{
3876 LY_ERR ret = 0;
3877 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003878 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003879 enum yang_keyword kw;
3880
3881 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003882 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003883 return LY_EVALID;
3884 }
3885
3886 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003887 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003888 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003889
3890 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3891 *flags |= LYS_YINELEM_TRUE;
3892 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3893 *flags |= LYS_YINELEM_FALSE;
3894 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003895 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003896 free(buf);
3897 return LY_EVALID;
3898 }
3899 free(buf);
3900
3901 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003902 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003903
3904 switch (kw) {
3905 case YANG_CUSTOM:
3906 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02003907 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908 break;
3909 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003910 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003911 return LY_EVALID;
3912 }
3913 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003914 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003915
3916 return ret;
3917}
3918
Michal Vaskoea5abea2018-09-18 13:10:54 +02003919/**
3920 * @brief Parse the yin-element statement.
3921 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003922 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003923 * @param[in,out] data Data to read from, always moved to currently handled character.
3924 * @param[in,out] argument Value to write to.
3925 * @param[in,out] flags Flags to write to.
3926 * @param[in,out] exts Extension instances to add to.
3927 *
3928 * @return LY_ERR values.
3929 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003930static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003931parse_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 +02003932{
3933 LY_ERR ret = 0;
3934 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003935 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003936 enum yang_keyword kw;
3937
3938 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003939 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003940 return LY_EVALID;
3941 }
3942
3943 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003944 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003945 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003946
Radek Krejci44ceedc2018-10-02 15:54:31 +02003947 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003948 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003949 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003950
3951 switch (kw) {
3952 case YANG_YIN_ELEMENT:
3953 ret = parse_yinelement(ctx, data, flags, exts);
3954 break;
3955 case YANG_CUSTOM:
3956 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts);
3957 break;
3958 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003959 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003960 return LY_EVALID;
3961 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003962 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003963 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003964 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003965
3966 return ret;
3967}
3968
Michal Vaskoea5abea2018-09-18 13:10:54 +02003969/**
3970 * @brief Parse the extension statement.
3971 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003972 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003973 * @param[in,out] data Data to read from, always moved to currently handled character.
3974 * @param[in,out] extensions Extensions to add to.
3975 *
3976 * @return LY_ERR values.
3977 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003978static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003979parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003980{
3981 LY_ERR ret = 0;
3982 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003983 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003984 enum yang_keyword kw;
3985 struct lysp_ext *ex;
3986
Radek Krejci2c4e7172018-10-19 15:56:26 +02003987 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003988
3989 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003990 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003991 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003992
Radek Krejci44ceedc2018-10-02 15:54:31 +02003993 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003994 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003995 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003996
3997 switch (kw) {
3998 case YANG_DESCRIPTION:
3999 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts);
4000 break;
4001 case YANG_REFERENCE:
4002 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts);
4003 break;
4004 case YANG_STATUS:
4005 ret = parse_status(ctx, data, &ex->flags, &ex->exts);
4006 break;
4007 case YANG_ARGUMENT:
4008 ret = parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts);
4009 break;
4010 case YANG_CUSTOM:
4011 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts);
4012 break;
4013 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004014 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004015 return LY_EVALID;
4016 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004017 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004018 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004019 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004020
4021 return ret;
4022}
4023
Michal Vaskoea5abea2018-09-18 13:10:54 +02004024/**
4025 * @brief Parse the deviate statement.
4026 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004027 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004028 * @param[in,out] data Data to read from, always moved to currently handled character.
4029 * @param[in,out] deviates Deviates to add to.
4030 *
4031 * @return LY_ERR values.
4032 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004033static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004034parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004035{
4036 LY_ERR ret = 0;
4037 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004038 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004039 enum yang_keyword kw;
4040 struct lysp_deviate *iter, *d;
4041 struct lysp_deviate_add *d_add = NULL;
4042 struct lysp_deviate_rpl *d_rpl = NULL;
4043 struct lysp_deviate_del *d_del = NULL;
4044 const char **d_units, ***d_uniques, ***d_dflts;
4045 struct lysp_restr **d_musts;
4046 uint16_t *d_flags;
4047 uint32_t *d_min, *d_max;
4048
4049 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004050 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004051 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004052
4053 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4054 dev_mod = LYS_DEV_NOT_SUPPORTED;
4055 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4056 dev_mod = LYS_DEV_ADD;
4057 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4058 dev_mod = LYS_DEV_REPLACE;
4059 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4060 dev_mod = LYS_DEV_DELETE;
4061 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004062 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004063 free(buf);
4064 return LY_EVALID;
4065 }
4066 free(buf);
4067
4068 /* create structure */
4069 switch (dev_mod) {
4070 case LYS_DEV_NOT_SUPPORTED:
4071 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004072 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004073 break;
4074 case LYS_DEV_ADD:
4075 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004076 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004077 d = (struct lysp_deviate *)d_add;
4078 d_units = &d_add->units;
4079 d_uniques = &d_add->uniques;
4080 d_dflts = &d_add->dflts;
4081 d_musts = &d_add->musts;
4082 d_flags = &d_add->flags;
4083 d_min = &d_add->min;
4084 d_max = &d_add->max;
4085 break;
4086 case LYS_DEV_REPLACE:
4087 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004088 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004089 d = (struct lysp_deviate *)d_rpl;
4090 d_units = &d_rpl->units;
4091 d_flags = &d_rpl->flags;
4092 d_min = &d_rpl->min;
4093 d_max = &d_rpl->max;
4094 break;
4095 case LYS_DEV_DELETE:
4096 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004097 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004098 d = (struct lysp_deviate *)d_del;
4099 d_units = &d_del->units;
4100 d_uniques = &d_del->uniques;
4101 d_dflts = &d_del->dflts;
4102 d_musts = &d_del->musts;
4103 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004104 break;
4105 default:
4106 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004107 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004108 }
4109 d->mod = dev_mod;
4110
4111 /* insert into siblings */
4112 if (!*deviates) {
4113 *deviates = d;
4114 } else {
4115 for (iter = *deviates; iter->next; iter = iter->next);
4116 iter->next = d;
4117 }
4118
4119 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004120 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004121
4122 switch (kw) {
4123 case YANG_CONFIG:
4124 switch (dev_mod) {
4125 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004126 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004127 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004128 return LY_EVALID;
4129 default:
4130 ret = parse_config(ctx, data, d_flags, &d->exts);
4131 break;
4132 }
4133 break;
4134 case YANG_DEFAULT:
4135 switch (dev_mod) {
4136 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004137 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004138 return LY_EVALID;
4139 case LYS_DEV_REPLACE:
4140 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts);
4141 break;
4142 default:
4143 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts);
4144 break;
4145 }
4146 break;
4147 case YANG_MANDATORY:
4148 switch (dev_mod) {
4149 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004150 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004151 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004152 return LY_EVALID;
4153 default:
4154 ret = parse_mandatory(ctx, data, d_flags, &d->exts);
4155 break;
4156 }
4157 break;
4158 case YANG_MAX_ELEMENTS:
4159 switch (dev_mod) {
4160 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004161 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004162 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004163 return LY_EVALID;
4164 default:
4165 ret = parse_maxelements(ctx, data, d_max, d_flags, &d->exts);
4166 break;
4167 }
4168 break;
4169 case YANG_MIN_ELEMENTS:
4170 switch (dev_mod) {
4171 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004172 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004173 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004174 return LY_EVALID;
4175 default:
4176 ret = parse_minelements(ctx, data, d_min, d_flags, &d->exts);
4177 break;
4178 }
4179 break;
4180 case YANG_MUST:
4181 switch (dev_mod) {
4182 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004183 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004184 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004185 return LY_EVALID;
4186 default:
4187 ret = parse_restrs(ctx, data, kw, d_musts);
4188 break;
4189 }
4190 break;
4191 case YANG_TYPE:
4192 switch (dev_mod) {
4193 case LYS_DEV_NOT_SUPPORTED:
4194 case LYS_DEV_ADD:
4195 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004196 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004197 return LY_EVALID;
4198 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004199 if (d_rpl->type) {
4200 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4201 return LY_EVALID;
4202 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004203 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004204 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004205 ret = parse_type(ctx, data, d_rpl->type);
4206 break;
4207 }
4208 break;
4209 case YANG_UNIQUE:
4210 switch (dev_mod) {
4211 case LYS_DEV_NOT_SUPPORTED:
4212 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004213 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004214 return LY_EVALID;
4215 default:
4216 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts);
4217 break;
4218 }
4219 break;
4220 case YANG_UNITS:
4221 switch (dev_mod) {
4222 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004223 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004224 return LY_EVALID;
4225 default:
4226 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts);
4227 break;
4228 }
4229 break;
4230 case YANG_CUSTOM:
4231 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts);
4232 break;
4233 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004234 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004235 return LY_EVALID;
4236 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004237 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004238 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004239 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004240
4241 return ret;
4242}
4243
Michal Vaskoea5abea2018-09-18 13:10:54 +02004244/**
4245 * @brief Parse the deviation statement.
4246 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004247 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004248 * @param[in,out] data Data to read from, always moved to currently handled character.
4249 * @param[in,out] deviations Deviations to add to.
4250 *
4251 * @return LY_ERR values.
4252 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004253static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004254parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004255{
4256 LY_ERR ret = 0;
4257 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004258 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004259 enum yang_keyword kw;
4260 struct lysp_deviation *dev;
4261
Radek Krejci2c4e7172018-10-19 15:56:26 +02004262 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004263
4264 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004265 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004266 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004267
Radek Krejci44ceedc2018-10-02 15:54:31 +02004268 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004269 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004270 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004271
4272 switch (kw) {
4273 case YANG_DESCRIPTION:
4274 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts);
4275 break;
4276 case YANG_DEVIATE:
4277 ret = parse_deviate(ctx, data, &dev->deviates);
4278 break;
4279 case YANG_REFERENCE:
4280 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts);
4281 break;
4282 case YANG_CUSTOM:
4283 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts);
4284 break;
4285 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004286 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004287 return LY_EVALID;
4288 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004289 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004290 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004291 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004292
4293 /* mandatory substatements */
4294 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004295 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004296 return LY_EVALID;
4297 }
4298
4299 return ret;
4300}
4301
Michal Vaskoea5abea2018-09-18 13:10:54 +02004302/**
4303 * @brief Parse the feature statement.
4304 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004305 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004306 * @param[in,out] data Data to read from, always moved to currently handled character.
4307 * @param[in,out] features Features to add to.
4308 *
4309 * @return LY_ERR values.
4310 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004311static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004312parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004313{
4314 LY_ERR ret = 0;
4315 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004316 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004317 enum yang_keyword kw;
4318 struct lysp_feature *feat;
4319
Radek Krejci2c4e7172018-10-19 15:56:26 +02004320 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004321
4322 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004323 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004324 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004325
Radek Krejci44ceedc2018-10-02 15:54:31 +02004326 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004327 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004328 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004329
4330 switch (kw) {
4331 case YANG_DESCRIPTION:
4332 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts);
4333 break;
4334 case YANG_IF_FEATURE:
4335 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts);
4336 break;
4337 case YANG_REFERENCE:
4338 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts);
4339 break;
4340 case YANG_STATUS:
4341 ret = parse_status(ctx, data, &feat->flags, &feat->exts);
4342 break;
4343 case YANG_CUSTOM:
4344 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts);
4345 break;
4346 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004347 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004348 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004349 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004350 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004351 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004352 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004353
4354 return ret;
4355}
4356
Michal Vaskoea5abea2018-09-18 13:10:54 +02004357/**
4358 * @brief Parse the identity statement.
4359 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004360 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004361 * @param[in,out] data Data to read from, always moved to currently handled character.
4362 * @param[in,out] identities Identities to add to.
4363 *
4364 * @return LY_ERR values.
4365 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004366static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004367parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004368{
4369 LY_ERR ret = 0;
4370 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004371 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004372 enum yang_keyword kw;
4373 struct lysp_ident *ident;
4374
Radek Krejci2c4e7172018-10-19 15:56:26 +02004375 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004376
4377 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004378 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004379 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004380
Radek Krejci44ceedc2018-10-02 15:54:31 +02004381 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004382 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004383 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004384
4385 switch (kw) {
4386 case YANG_DESCRIPTION:
4387 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts);
4388 break;
4389 case YANG_IF_FEATURE:
4390 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts);
4391 break;
4392 case YANG_REFERENCE:
4393 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts);
4394 break;
4395 case YANG_STATUS:
4396 ret = parse_status(ctx, data, &ident->flags, &ident->exts);
4397 break;
4398 case YANG_BASE:
4399 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts);
4400 break;
4401 case YANG_CUSTOM:
4402 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts);
4403 break;
4404 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004405 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004406 return LY_EVALID;
4407 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004408 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004409 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004410
4411 return ret;
4412}
4413
Michal Vaskoea5abea2018-09-18 13:10:54 +02004414/**
4415 * @brief Parse the module or submodule statement.
4416 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004417 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004418 * @param[in,out] data Data to read from, always moved to currently handled character.
4419 * @param[in,out] mod Module to write to.
4420 *
4421 * @return LY_ERR values.
4422 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004423static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004424parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004425{
4426 LY_ERR ret = 0;
4427 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004428 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004429 enum yang_keyword kw, prev_kw = 0;
4430 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4431
4432 /* (sub)module name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004433 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004434 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004435
Radek Krejci44ceedc2018-10-02 15:54:31 +02004436 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004437 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004438 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004439
Radek Krejcie3846472018-10-15 15:24:51 +02004440#define CHECK_ORDER(SECTION) \
4441 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4442
Michal Vasko7fbc8162018-09-17 10:35:16 +02004443 switch (kw) {
4444 /* module header */
4445 case YANG_NAMESPACE:
4446 case YANG_PREFIX:
4447 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004448 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004449 return LY_EVALID;
4450 }
Radek Krejcie3846472018-10-15 15:24:51 +02004451 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4452 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004453 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004454 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004455 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004456 return LY_EVALID;
4457 }
Radek Krejcie3846472018-10-15 15:24:51 +02004458 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4459 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004460 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004461 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004462 break;
4463 /* linkage */
4464 case YANG_INCLUDE:
4465 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004466 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004467 break;
4468 /* meta */
4469 case YANG_ORGANIZATION:
4470 case YANG_CONTACT:
4471 case YANG_DESCRIPTION:
4472 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004473 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004474 break;
4475
4476 /* revision */
4477 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004478 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004479 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004480 /* body */
4481 case YANG_ANYDATA:
4482 case YANG_ANYXML:
4483 case YANG_AUGMENT:
4484 case YANG_CHOICE:
4485 case YANG_CONTAINER:
4486 case YANG_DEVIATION:
4487 case YANG_EXTENSION:
4488 case YANG_FEATURE:
4489 case YANG_GROUPING:
4490 case YANG_IDENTITY:
4491 case YANG_LEAF:
4492 case YANG_LEAF_LIST:
4493 case YANG_LIST:
4494 case YANG_NOTIFICATION:
4495 case YANG_RPC:
4496 case YANG_TYPEDEF:
4497 case YANG_USES:
4498 case YANG_CUSTOM:
4499 mod_stmt = Y_MOD_BODY;
4500 break;
4501 default:
4502 /* error handled in the next switch */
4503 break;
4504 }
Radek Krejcie3846472018-10-15 15:24:51 +02004505#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004506
Radek Krejcie3846472018-10-15 15:24:51 +02004507 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004508 switch (kw) {
4509 /* module header */
4510 case YANG_YANG_VERSION:
4511 ret = parse_yangversion(ctx, data, mod);
4512 break;
4513 case YANG_NAMESPACE:
4514 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts);
4515 break;
4516 case YANG_PREFIX:
4517 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts);
Radek Krejci70853c52018-10-15 14:46:16 +02004518 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004519 break;
4520 case YANG_BELONGS_TO:
4521 ret = parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts);
4522 break;
4523
4524 /* linkage */
4525 case YANG_INCLUDE:
Radek Krejcid33273d2018-10-25 14:55:52 +02004526 ret = parse_include(ctx, data, mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004527 break;
4528 case YANG_IMPORT:
Radek Krejci70853c52018-10-15 14:46:16 +02004529 ret = parse_import(ctx, data, mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004530 break;
4531
4532 /* meta */
4533 case YANG_ORGANIZATION:
4534 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts);
4535 break;
4536 case YANG_CONTACT:
4537 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts);
4538 break;
4539 case YANG_DESCRIPTION:
4540 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts);
4541 break;
4542 case YANG_REFERENCE:
4543 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts);
4544 break;
4545
4546 /* revision */
4547 case YANG_REVISION:
4548 ret = parse_revision(ctx, data, &mod->revs);
4549 break;
4550
4551 /* body */
4552 case YANG_ANYDATA:
4553 case YANG_ANYXML:
4554 ret = parse_any(ctx, data, kw, &mod->data);
4555 break;
4556 case YANG_CHOICE:
4557 ret = parse_choice(ctx, data, &mod->data);
4558 break;
4559 case YANG_CONTAINER:
4560 ret = parse_container(ctx, data, &mod->data);
4561 break;
4562 case YANG_LEAF:
4563 ret = parse_leaf(ctx, data, &mod->data);
4564 break;
4565 case YANG_LEAF_LIST:
4566 ret = parse_leaflist(ctx, data, &mod->data);
4567 break;
4568 case YANG_LIST:
4569 ret = parse_list(ctx, data, &mod->data);
4570 break;
4571 case YANG_USES:
4572 ret = parse_uses(ctx, data, &mod->data);
4573 break;
4574
4575 case YANG_AUGMENT:
4576 ret = parse_augment(ctx, data, &mod->augments);
4577 break;
4578 case YANG_DEVIATION:
4579 ret = parse_deviation(ctx, data, &mod->deviations);
4580 break;
4581 case YANG_EXTENSION:
4582 ret = parse_extension(ctx, data, &mod->extensions);
4583 break;
4584 case YANG_FEATURE:
4585 ret = parse_feature(ctx, data, &mod->features);
4586 break;
4587 case YANG_GROUPING:
4588 ret = parse_grouping(ctx, data, &mod->groupings);
4589 break;
4590 case YANG_IDENTITY:
4591 ret = parse_identity(ctx, data, &mod->identities);
4592 break;
4593 case YANG_NOTIFICATION:
4594 ret = parse_notif(ctx, data, &mod->notifs);
4595 break;
4596 case YANG_RPC:
4597 ret = parse_action(ctx, data, &mod->rpcs);
4598 break;
4599 case YANG_TYPEDEF:
4600 ret = parse_typedef(ctx, data, &mod->typedefs);
4601 break;
4602 case YANG_CUSTOM:
4603 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts);
4604 break;
4605
4606 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004607 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004608 return LY_EVALID;
4609 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004610 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004611 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004612 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004613
4614 /* mandatory substatements */
4615 if (mod->submodule) {
4616 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004617 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004618 return LY_EVALID;
4619 }
4620 } else {
4621 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004622 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004623 return LY_EVALID;
4624 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004625 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004626 return LY_EVALID;
4627 }
4628 }
4629
4630 return ret;
4631}
4632
Radek Krejcid4557c62018-09-17 11:42:09 +02004633LY_ERR
Michal Vasko7fbc8162018-09-17 10:35:16 +02004634yang_parse(struct ly_ctx *ctx, const char *data, struct lysp_module **mod_p)
4635{
4636 LY_ERR ret = 0;
4637 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004638 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004639 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004640 struct lysp_module *mod = NULL;
Radek Krejci86d106e2018-10-18 09:53:19 +02004641 struct ly_parser_ctx context = {0};
Michal Vasko7fbc8162018-09-17 10:35:16 +02004642
Radek Krejci44ceedc2018-10-02 15:54:31 +02004643 context.ctx = ctx;
4644 context.line = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004645
4646 /* "module"/"submodule" */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004647 ret = get_keyword(&context, &data, &kw, &word, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004648 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004649
4650 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004651 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004652 ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004653 goto error;
4654 }
4655
4656 mod = calloc(1, sizeof *mod);
4657 LY_CHECK_ERR_GOTO(!mod, LOGMEM(ctx), error);
4658 if (kw == YANG_SUBMODULE) {
4659 mod->submodule = 1;
4660 }
Radek Krejci9fcacc12018-10-11 15:59:11 +02004661 mod->ctx = ctx;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004662
4663 /* substatements */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004664 ret = parse_sub_module(&context, &data, mod);
Radek Krejcic59bc972018-09-17 16:13:06 +02004665 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004666
4667 /* read some trailing spaces or new lines */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004668 ret = get_argument(&context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004669 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004670
4671 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004672 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004673 word_len, word);
4674 free(buf);
4675 goto error;
4676 }
4677 assert(!buf);
4678
4679 *mod_p = mod;
4680 return ret;
4681
4682error:
Radek Krejci9fcacc12018-10-11 15:59:11 +02004683 lysp_module_free(mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004684 return ret;
4685}