blob: cd11584f0ea3cea9640ae2a2491d63e7d4b58728 [file] [log] [blame]
Michal Vasko7fbc8162018-09-17 10:35:16 +02001/**
2 * @file parser_yang.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YANG parser
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <errno.h>
22#include <ctype.h>
23#include <string.h>
24#include <dirent.h>
25#include <assert.h>
26
27#include "common.h"
28#include "context.h"
29#include "libyang.h"
30
Michal Vasko7fbc8162018-09-17 10:35:16 +020031#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR) \
32 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
Radek Krejcic59bc972018-09-17 16:13:06 +020033 LY_CHECK_RET(ERR); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020034 \
35 if (KW == YANG_SEMICOLON) { \
36 return ERR; \
37 } \
38 if (KW != YANG_LEFT_BRACE) { \
Radek Krejcic59bc972018-09-17 16:13:06 +020039 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020040 return LY_EVALID; \
41 } \
42 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
43 !ERR && (KW != YANG_RIGHT_BRACE); \
44 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
45
Michal Vasko7fbc8162018-09-17 10:35:16 +020046static LY_ERR parse_container(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings);
47static LY_ERR parse_uses(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings);
48static LY_ERR parse_choice(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings);
49static LY_ERR parse_case(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings);
50static LY_ERR parse_list(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings);
51static LY_ERR parse_grouping(struct ly_ctx *ctx, const char **data, struct lysp_grp **groupings);
52
Michal Vasko7fbc8162018-09-17 10:35:16 +020053static LY_ERR
54buf_add_char(struct ly_ctx *ctx, char c, char **buf, int *buf_len, int buf_used)
55{
56 if (*buf_len == buf_used) {
57 *buf_len += 16;
58 *buf = ly_realloc(*buf, *buf_len);
59 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
60 }
61
62 (*buf)[buf_used] = c;
63 return LY_SUCCESS;
64}
65
66static LY_ERR
67buf_store_char(struct ly_ctx *ctx, const char *c, char **word_p, int *word_len, char **word_b, int *buf_len, int need_buf)
68{
69 if (word_b && *word_b) {
70 /* add another character into buffer */
71 if (buf_add_char(ctx, *c, word_b, buf_len, *word_len)) {
72 return LY_EMEM;
73 }
74
75 /* in case of realloc */
76 *word_p = *word_b;
77 } else if (need_buf) {
78 /* first time we need a buffer, copy everything read up to now */
79 if (*word_len) {
80 *word_b = malloc(*word_len);
81 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx), LY_EMEM);
82 *buf_len = *word_len;
83 memcpy(*word_b, *word_p, *word_len);
84 }
85
86 /* add this new character into buffer */
87 if (buf_add_char(ctx, *c, word_b, buf_len, *word_len)) {
88 return LY_EMEM;
89 }
90
91 /* in case of realloc */
92 *word_p = *word_b;
93 } else {
94 /* just remember the first character pointer */
95 if (!*word_p) {
96 *word_p = (char *)c;
97 }
98 }
99
100 ++(*word_len);
101 return LY_SUCCESS;
102}
103
104static LY_ERR
105check_char(struct ly_ctx *ctx, char c, enum yang_arg arg, int first, int *prefix)
106{
107 if ((arg == Y_STR_ARG) || (arg == Y_MAYBE_STR_ARG)) {
108 if ((c < ' ') && (c != '\t') && (c != '\n')) {
109 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHAR, c);
110 return LY_EVALID;
111 }
112 } else if ((arg == Y_IDENTIF_ARG) || (arg == Y_PREF_IDENTIF_ARG)) {
113 if (c < ' ') {
114 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHAR, c);
115 return LY_EVALID;
116 }
117
118 if (first || (*prefix == 2)) {
119 /* either first character of the whole identifier or of the name after prefix */
120 if (!isalpha(c) && (c != '_')) {
121 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
122 return LY_EVALID;
123 }
124 if (*prefix == 2) {
125 *prefix = 1;
126 }
127 } else {
128 /* other characters */
129 if (!isalnum(c) && (c != '_') && (c != '-') && (c != '.')) {
130 if ((arg == Y_PREF_IDENTIF_ARG) && !*prefix && (c == ':')) {
131 /* this is fine */
132 *prefix = 2;
133 } else {
134 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
135 return LY_EVALID;
136 }
137 }
138 }
139 }
140
141 return LY_SUCCESS;
142}
143
144static LY_ERR
145skip_comment(struct ly_ctx *ctx, const char **data, int comment)
146{
147 /* comment: 0 - comment ended, 1 - in line comment, 2 - in block comment, 3 - in block comment with last read character '*' */
148
149 while (**data && comment) {
150 switch (comment) {
151 case 1:
152 if (**data == '\n') {
153 comment = 0;
154 }
155 break;
156 case 2:
157 if (**data == '*') {
158 comment = 3;
159 }
160 break;
161 case 3:
162 if (**data == '/') {
163 comment = 0;
164 } else {
165 comment = 2;
166 }
167 break;
168 default:
169 LOGINT_RET(ctx);
170 }
171
172 ++(*data);
173 }
174
175 if (!**data && (comment > 1)) {
176 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
177 return LY_EVALID;
178 }
179
180 return LY_SUCCESS;
181}
182
183static LY_ERR
184read_qstring(struct ly_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, int *word_len,
185 int *buf_len, int indent)
186{
187 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
188 * 4 - string finished, now skipping whitespaces looking for +,
189 * 5 - string continues after +, skipping whitespaces */
190 int string, str_nl_indent = 0, need_buf = 0, prefix = 0;
191 const char *c;
192
193 if (**data == '\"') {
194 /* indent of the " itself */
195 ++indent;
196 string = 2;
197 } else {
198 assert(**data == '\'');
199 string = 1;
200 }
201 ++(*data);
202
203 while (**data && string) {
204 switch (string) {
205 case 1:
206 switch (**data) {
207 case '\'':
208 /* string may be finished, but check for + */
209 string = 4;
210 break;
211 default:
212 /* check and store character */
213 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
214 return LY_EVALID;
215 }
216 if (buf_store_char(ctx, *data, word_p, word_len, word_b, buf_len, need_buf)) {
217 return LY_EMEM;
218 }
219 break;
220 }
221 break;
222 case 2:
223 switch (**data) {
224 case '\"':
225 /* string may be finished, but check for + */
226 string = 4;
227 break;
228 case '\\':
229 /* special character following */
230 string = 3;
231 break;
232 case ' ':
233 if (str_nl_indent) {
234 --str_nl_indent;
235 } else {
236 /* check and store character */
237 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
238 return LY_EVALID;
239 }
240 if (buf_store_char(ctx, *data, word_p, word_len, word_b, buf_len, need_buf)) {
241 return LY_EMEM;
242 }
243 }
244 break;
245 case '\t':
246 if (str_nl_indent) {
247 if (str_nl_indent < 9) {
248 str_nl_indent = 0;
249 } else {
250 str_nl_indent -= 8;
251 }
252 } else {
253 /* check and store character */
254 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
255 return LY_EVALID;
256 }
257 if (buf_store_char(ctx, *data, word_p, word_len, word_b, buf_len, need_buf)) {
258 return LY_EMEM;
259 }
260 }
261 break;
262 case '\n':
263 str_nl_indent = indent;
264 if (indent) {
265 /* we will be removing the indents so we need our own buffer */
266 need_buf = 1;
267 }
268
269 /* check and store character */
270 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
271 return LY_EVALID;
272 }
273 if (buf_store_char(ctx, *data, word_p, word_len, word_b, buf_len, need_buf)) {
274 return LY_EMEM;
275 }
276 break;
277 default:
278 /* first non-whitespace character, clear current indent */
279 str_nl_indent = 0;
280
281 /* check and store character */
282 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
283 return LY_EVALID;
284 }
285 if (buf_store_char(ctx, *data, word_p, word_len, word_b, buf_len, need_buf)) {
286 return LY_EMEM;
287 }
288 break;
289 }
290 break;
291 case 3:
292 /* string encoded characters */
293 switch (**data) {
294 case 'n':
295 c = "\n";
296 break;
297 case 't':
298 c = "\t";
299 break;
300 case '\"':
301 c = *data;
302 break;
303 case '\\':
304 c = *data;
305 break;
306 default:
307 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX_YANG,
308 "Double-quoted string unknown special character '\\%c'.\n", **data);
309 return LY_EVALID;
310 }
311
312 /* check and store character */
313 if (check_char(ctx, *c, arg, !*word_len, &prefix)) {
314 return LY_EVALID;
315 }
316 if (buf_store_char(ctx, c, word_p, word_len, word_b, buf_len, need_buf)) {
317 return LY_EMEM;
318 }
319
320 string = 2;
321 break;
322 case 4:
323 switch (**data) {
324 case '+':
325 /* string continues */
326 string = 5;
327 break;
328 case ' ':
329 case '\t':
330 case '\n':
331 /* just skip */
332 break;
333 default:
334 /* string is finished */
335 goto string_end;
336 }
337 break;
338 case 5:
339 switch (**data) {
340 case ' ':
341 case '\t':
342 case '\n':
343 /* skip */
344 break;
345 case '\'':
346 string = 1;
347 break;
348 case '\"':
349 string = 2;
350 break;
351 default:
352 /* it must be quoted again */
353 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX_YANG,
354 "Both string parts divided by '+' must be quoted.\n");
355 return LY_EVALID;
356 }
357 break;
358 default:
359 return LY_EINT;
360 }
361
362 ++(*data);
363 }
364
365string_end:
366 return LY_SUCCESS;
367}
368
369/* read another word - character sequence without whitespaces (logs directly)
370 * - there can be whitespaces if they are a part of string
371 * - strings are always returned separately even if not separated by whitespaces
372 * - strings are returned without ' or "
373 * - strings divided by + are returned concatenated
374 * - comments are skipped
375 */
376static LY_ERR
377get_string(struct ly_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, int *word_len)
378{
379 int buf_len = 0, slash = 0, indent = 0, prefix = 0;
380 LY_ERR ret;
381
382 /* word buffer - dynamically allocated */
383 *word_b = NULL;
384
385 /* word pointer - just a pointer to data */
386 *word_p = NULL;
387
388 *word_len = 0;
389 while (**data) {
390 if (slash) {
391 if (**data == '/') {
392 /* one-line comment */
393 ret = skip_comment(ctx, data, 1);
394 if (ret) {
395 return ret;
396 }
397 } else if (**data == '*') {
398 /* block comment */
399 ret = skip_comment(ctx, data, 2);
400 if (ret) {
401 return ret;
402 }
403 } else {
404 /* not a comment after all */
405 ret = buf_store_char(ctx, (*data) - 1, word_p, word_len, word_b, &buf_len, 0);
406 if (ret) {
407 return ret;
408 }
409 }
410 slash = 0;
411 }
412
413 switch (**data) {
414 case '\'':
415 case '\"':
416 if (*word_len) {
417 /* we want strings always in a separate word, leave it */
418 goto str_end;
419 }
420 ret = read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len, indent);
421 if (ret) {
422 return ret;
423 }
424 goto str_end;
425 case '/':
426 slash = 1;
427 break;
428 case ' ':
429 if (*word_len) {
430 /* word is finished */
431 goto str_end;
432 }
433 /* increase indent */
434 ++indent;
435 break;
436 case '\t':
437 if (*word_len) {
438 /* word is finished */
439 goto str_end;
440 }
441 /* tabs count for 8 spaces */
442 indent += 8;
443 break;
444 case '\n':
445 if (*word_len) {
446 /* word is finished */
447 goto str_end;
448 }
449 /* reset indent */
450 indent = 0;
451 break;
452 case ';':
453 case '{':
454 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
455 /* word is finished */
456 goto str_end;
457 }
458
459 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INSTREXP, 1, *data, "an argument");
460 return LY_EVALID;
461 default:
462 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
463 return LY_EVALID;
464 }
465
466 if (buf_store_char(ctx, *data, word_p, word_len, word_b, &buf_len, 0)) {
467 return LY_EMEM;
468 }
469 break;
470 }
471
472 ++(*data);
473 }
474
475str_end:
476 /* ending '\0' for buf */
477 if (*word_b) {
478 if (buf_add_char(ctx, '\0', word_b, &buf_len, *word_len)) {
479 return LY_EMEM;
480 }
481 *word_p = *word_b;
482 }
483
484 return LY_SUCCESS;
485}
486
487static LY_ERR
488get_keyword(struct ly_ctx *ctx, const char **data, enum yang_keyword *kw, char **word_p, int *word_len)
489{
490 LY_ERR ret;
491 int prefix;
492 const char *word_start;
493 /* slash: 0 - nothing, 1 - last character was '/' */
494 int slash = 0;
495
496 if (word_p) {
497 *word_p = NULL;
498 *word_len = 0;
499 }
500
501 /* first skip "optsep", comments */
502 while (**data) {
503 if (slash) {
504 if (**data == '/') {
505 /* one-line comment */
506 ret = skip_comment(ctx, data, 1);
507 if (ret) {
508 return ret;
509 }
510 } else if (**data == '*') {
511 /* block comment */
512 ret = skip_comment(ctx, data, 2);
513 if (ret) {
514 return ret;
515 }
516 } else {
517 /* not a comment after all */
518 goto keyword_start;
519 }
520 slash = 0;
521 }
522
523 switch (**data) {
524 case '/':
525 slash = 1;
526 break;
527 case ' ':
528 case '\t':
529 case '\n':
530 /* skip whitespaces (optsep) */
531 break;
532 default:
533 /* either a keyword start or an invalid character */
534 goto keyword_start;
535 }
536
537 ++(*data);
538 }
539
540keyword_start:
541 word_start = *data;
542 *kw = YANG_NONE;
543
544 /* read the keyword itself */
545 switch (**data) {
546 case 'a':
547 ++(*data);
548 if (!strncmp(*data, "rgument", 7)) {
549 *data += 7;
550 *kw = YANG_ARGUMENT;
551 } else if (!strncmp(*data, "ugment", 6)) {
552 *data += 6;
553 *kw = YANG_AUGMENT;
554 } else if (!strncmp(*data, "ction", 5)) {
555 *data += 5;
556 *kw = YANG_ACTION;
557 } else if (!strncmp(*data, "ny", 2)) {
558 *data += 2;
559 if (!strncmp(*data, "data", 4)) {
560 *data += 4;
561 *kw = YANG_ANYDATA;
562 } else if (!strncmp(*data, "xml", 3)) {
563 *data += 3;
564 *kw = YANG_ANYXML;
565 }
566 }
567 break;
568 case 'b':
569 ++(*data);
570 if (!strncmp(*data, "ase", 3)) {
571 *data += 3;
572 *kw = YANG_BASE;
573 } else if (!strncmp(*data, "elongs-to", 9)) {
574 *data += 9;
575 *kw = YANG_BELONGS_TO;
576 } else if (!strncmp(*data, "it", 2)) {
577 *data += 2;
578 *kw = YANG_BIT;
579 }
580 break;
581 case 'c':
582 ++(*data);
583 if (!strncmp(*data, "ase", 3)) {
584 *data += 3;
585 *kw = YANG_CASE;
586 } else if (!strncmp(*data, "hoice", 5)) {
587 *data += 5;
588 *kw = YANG_CHOICE;
589 } else if (!strncmp(*data, "on", 2)) {
590 *data += 2;
591 if (!strncmp(*data, "fig", 3)) {
592 *data += 3;
593 *kw = YANG_CONFIG;
594 } else if (!strncmp(*data, "ta", 2)) {
595 *data += 2;
596 if (!strncmp(*data, "ct", 2)) {
597 *data += 2;
598 *kw = YANG_CONTACT;
599 } else if (!strncmp(*data, "iner", 4)) {
600 *data += 4;
601 *kw = YANG_CONTAINER;
602 }
603 }
604 }
605 break;
606 case 'd':
607 ++(*data);
608 if (**data == 'e') {
609 ++(*data);
610 if (!strncmp(*data, "fault", 5)) {
611 *data += 5;
612 *kw = YANG_DEFAULT;
613 } else if (!strncmp(*data, "scription", 9)) {
614 *data += 9;
615 *kw = YANG_DESCRIPTION;
616 } else if (!strncmp(*data, "viat", 4)) {
617 *data += 4;
618 if (**data == 'e') {
619 ++(*data);
620 *kw = YANG_DEVIATE;
621 } else if (!strncmp(*data, "ion", 3)) {
622 *data += 3;
623 *kw = YANG_DEVIATION;
624 }
625 }
626 }
627 break;
628 case 'e':
629 ++(*data);
630 if (!strncmp(*data, "num", 3)) {
631 *data += 3;
632 *kw = YANG_ENUM;
633 } else if (!strncmp(*data, "rror-", 5)) {
634 *data += 5;
635 if (!strncmp(*data, "app-tag", 7)) {
636 *data += 7;
637 *kw = YANG_ERROR_APP_TAG;
638 } else if (!strncmp(*data, "message", 7)) {
639 *data += 7;
640 *kw = YANG_ERROR_MESSAGE;
641 }
642 } else if (!strncmp(*data, "xtension", 8)) {
643 *data += 8;
644 *kw = YANG_EXTENSION;
645 }
646 break;
647 case 'f':
648 ++(*data);
649 if (!strncmp(*data, "eature", 6)) {
650 *data += 6;
651 *kw = YANG_FEATURE;
652 } else if (!strncmp(*data, "raction-digits", 14)) {
653 *data += 14;
654 *kw = YANG_FRACTION_DIGITS;
655 }
656 break;
657 case 'g':
658 ++(*data);
659 if (!strncmp(*data, "rouping", 7)) {
660 *data += 7;
661 *kw = YANG_GROUPING;
662 }
663 break;
664 case 'i':
665 ++(*data);
666 if (!strncmp(*data, "dentity", 7)) {
667 *data += 7;
668 *kw = YANG_IDENTITY;
669 } else if (!strncmp(*data, "f-feature", 9)) {
670 *data += 9;
671 *kw = YANG_IF_FEATURE;
672 } else if (!strncmp(*data, "mport", 5)) {
673 *data += 5;
674 *kw = YANG_IMPORT;
675 } else if (**data == 'n') {
676 ++(*data);
677 if (!strncmp(*data, "clude", 5)) {
678 *data += 5;
679 *kw = YANG_INCLUDE;
680 } else if (!strncmp(*data, "put", 3)) {
681 *data += 3;
682 *kw = YANG_INPUT;
683 }
684 }
685 break;
686 case 'k':
687 ++(*data);
688 if (!strncmp(*data, "ey", 2)) {
689 *data += 2;
690 *kw = YANG_KEY;
691 }
692 break;
693 case 'l':
694 ++(*data);
695 if (**data == 'e') {
696 ++(*data);
697 if (!strncmp(*data, "af", 2)) {
698 *data += 2;
699 if (**data != '-') {
700 *kw = YANG_LEAF;
701 } else if (!strncmp(*data, "-list", 5)) {
702 *data += 5;
703 *kw = YANG_LEAF_LIST;
704 }
705 } else if (!strncmp(*data, "ngth", 4)) {
706 *data += 4;
707 *kw = YANG_LENGTH;
708 }
709 } else if (!strncmp(*data, "ist", 3)) {
710 *data += 3;
711 *kw = YANG_LIST;
712 }
713 break;
714 case 'm':
715 ++(*data);
716 if (**data == 'a') {
717 ++(*data);
718 if (!strncmp(*data, "ndatory", 7)) {
719 *data += 7;
720 *kw = YANG_MANDATORY;
721 } else if (!strncmp(*data, "x-elements", 10)) {
722 *data += 10;
723 *kw = YANG_MAX_ELEMENTS;
724 }
725 } else if (!strncmp(*data, "in-elements", 11)) {
726 *data += 11;
727 *kw = YANG_MIN_ELEMENTS;
728 } else if (!strncmp(*data, "ust", 3)) {
729 *data += 3;
730 *kw = YANG_MUST;
731 } else if (!strncmp(*data, "od", 2)) {
732 *data += 2;
733 if (!strncmp(*data, "ule", 3)) {
734 *data += 3;
735 *kw = YANG_MODULE;
736 } else if (!strncmp(*data, "ifier", 5)) {
737 *data += 3;
738 *kw = YANG_MODIFIER;
739 }
740 }
741 break;
742 case 'n':
743 ++(*data);
744 if (!strncmp(*data, "amespace", 8)) {
745 *data += 8;
746 *kw = YANG_NAMESPACE;
747 } else if (!strncmp(*data, "otification", 11)) {
748 *data += 11;
749 *kw = YANG_NOTIFICATION;
750 }
751 break;
752 case 'o':
753 ++(*data);
754 if (**data == 'r') {
755 ++(*data);
756 if (!strncmp(*data, "dered-by", 8)) {
757 *data += 8;
758 *kw = YANG_ORDERED_BY;
759 } else if (!strncmp(*data, "ganization", 10)) {
760 *data += 10;
761 *kw = YANG_ORGANIZATION;
762 }
763 } else if (!strncmp(*data, "utput", 5)) {
764 *data += 5;
765 *kw = YANG_OUTPUT;
766 }
767 break;
768 case 'p':
769 ++(*data);
770 if (!strncmp(*data, "at", 2)) {
771 *data += 2;
772 if (**data == 'h') {
773 ++(*data);
774 *kw = YANG_PATH;
775 } else if (!strncmp(*data, "tern", 4)) {
776 *data += 4;
777 *kw = YANG_PATTERN;
778 }
779 } else if (!strncmp(*data, "osition", 7)) {
780 *data += 7;
781 *kw = YANG_POSITION;
782 } else if (!strncmp(*data, "re", 2)) {
783 *data += 2;
784 if (!strncmp(*data, "fix", 3)) {
785 *data += 3;
786 *kw = YANG_PREFIX;
787 } else if (!strncmp(*data, "sence", 5)) {
788 *data += 5;
789 *kw = YANG_PRESENCE;
790 }
791 }
792 break;
793 case 'r':
794 ++(*data);
795 if (!strncmp(*data, "ange", 4)) {
796 *data += 4;
797 *kw = YANG_RANGE;
798 } else if (**data == 'e') {
799 ++(*data);
800 if (**data == 'f') {
801 ++(*data);
802 if (!strncmp(*data, "erence", 6)) {
803 *data += 6;
804 *kw = YANG_REFERENCE;
805 } else if (!strncmp(*data, "ine", 3)) {
806 *data += 3;
807 *kw = YANG_REFINE;
808 }
809 } else if (!strncmp(*data, "quire-instance", 14)) {
810 *data += 14;
811 *kw = YANG_REQUIRE_INSTANCE;
812 } else if (!strncmp(*data, "vision", 6)) {
813 *data += 6;
814 if (**data != '-') {
815 *kw = YANG_REVISION;
816 } else if (!strncmp(*data, "-date", 5)) {
817 *data += 5;
818 *kw = YANG_REVISION_DATE;
819 }
820 }
821 } else if (!strncmp(*data, "pc", 2)) {
822 *data += 2;
823 *kw = YANG_RPC;
824 }
825 break;
826 case 's':
827 ++(*data);
828 if (!strncmp(*data, "tatus", 5)) {
829 *data += 5;
830 *kw = YANG_STATUS;
831 } else if (!strncmp(*data, "ubmodule", 8)) {
832 *data += 8;
833 *kw = YANG_SUBMODULE;
834 }
835 break;
836 case 't':
837 ++(*data);
838 if (!strncmp(*data, "ype", 3)) {
839 *data += 3;
840 if (**data != 'd') {
841 *kw = YANG_TYPE;
842 } else if (!strncmp(*data, "def", 3)) {
843 *data += 3;
844 *kw = YANG_TYPEDEF;
845 }
846 }
847 break;
848 case 'u':
849 ++(*data);
850 if (!strncmp(*data, "ni", 2)) {
851 *data += 2;
852 if (!strncmp(*data, "que", 3)) {
853 *data += 3;
854 *kw = YANG_UNIQUE;
855 } else if (!strncmp(*data, "ts", 2)) {
856 *data += 2;
857 *kw = YANG_UNITS;
858 }
859 } else if (!strncmp(*data, "ses", 3)) {
860 *data += 3;
861 *kw = YANG_USES;
862 }
863 break;
864 case 'v':
865 ++(*data);
866 if (!strncmp(*data, "alue", 4)) {
867 *data += 4;
868 *kw = YANG_VALUE;
869 }
870 break;
871 case 'w':
872 ++(*data);
873 if (!strncmp(*data, "hen", 3)) {
874 *data += 3;
875 *kw = YANG_WHEN;
876 }
877 break;
878 case 'y':
879 ++(*data);
880 if (!strncmp(*data, "ang-version", 11)) {
881 *data += 11;
882 *kw = YANG_YANG_VERSION;
883 } else if (!strncmp(*data, "in-element", 10)) {
884 *data += 10;
885 *kw = YANG_YIN_ELEMENT;
886 }
887 break;
888 case ';':
889 ++(*data);
890 *kw = YANG_SEMICOLON;
891 break;
892 case '{':
893 ++(*data);
894 *kw = YANG_LEFT_BRACE;
895 break;
896 case '}':
897 ++(*data);
898 *kw = YANG_RIGHT_BRACE;
899 break;
900 default:
901 break;
902 }
903
904 if (*kw != YANG_NONE) {
905 /* make sure we have the whole keyword */
906 switch (**data) {
907 case ' ':
908 case '\t':
909 case '\n':
910 /* mandatory "sep" */
911 break;
912 default:
913 ++(*data);
914 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
915 "a keyword followed by a separator");
916 return LY_EVALID;
917 }
918 } else {
919 /* still can be an extension */
920 prefix = 0;
921 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
922 if (check_char(ctx, **data, Y_PREF_IDENTIF_ARG, *data == word_start ? 1 : 0, &prefix)) {
923 return LY_EVALID;
924 }
925 ++(*data);
926 }
927 if (!**data) {
Radek Krejcic07921a2018-09-17 11:40:15 +0200928 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200929 return LY_EVALID;
930 }
931
932 /* prefix is mandatory for extension instances */
933 if (prefix != 1) {
934 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
935 return LY_EVALID;
936 }
937
938 *kw = YANG_CUSTOM;
939 }
940
941 if (word_p) {
942 *word_p = (char *)word_start;
943 *word_len = *data - word_start;
944 }
945
946 return LY_SUCCESS;
947}
948
949static LY_ERR
950parse_ext_substmt(struct ly_ctx *ctx, const char **data, char *word, int word_len,
951 struct lysp_stmt **child)
952{
953 char *buf;
954 LY_ERR ret = 0;
955 enum yang_keyword kw;
956 struct lysp_stmt *stmt, *par_child;
957
958 stmt = calloc(1, sizeof *stmt);
959 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
960
961 stmt->stmt = lydict_insert(ctx, word, word_len);
962
963 /* get optional argument */
964 ret = get_string(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +0200965 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200966
967 if (buf) {
968 stmt->arg = lydict_insert_zc(ctx, word);
969 } else {
970 stmt->arg = lydict_insert(ctx, word, word_len);
971 }
972
973 /* insert into parent statements */
974 if (!*child) {
975 *child = stmt;
976 } else {
977 for (par_child = *child; par_child->next; par_child = par_child->next);
978 par_child->next = stmt;
979 }
980
981 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +0200982 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200983
984 ret = parse_ext_substmt(ctx, data, word, word_len, &stmt->child);
Radek Krejcic59bc972018-09-17 16:13:06 +0200985 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200986 }
Radek Krejcic59bc972018-09-17 16:13:06 +0200987 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200988
989 return ret;
990}
991
992static LY_ERR
993parse_ext(struct ly_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
994 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
995{
996 LY_ERR ret = 0;
997 char *buf, *word;
998 int word_len;
999 struct lysp_ext_instance *e;
1000 enum yang_keyword kw;
1001
1002 LYSP_ARRAY_NEW_RET(ctx, exts, e, LY_EMEM);
1003
1004 /* store name and insubstmt info */
1005 e->name = lydict_insert(ctx, ext_name, ext_name_len);
1006 e->insubstmt = insubstmt;
1007 e->insubstmt_index = insubstmt_index;
1008
1009 /* get optional argument */
1010 ret = get_string(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001011 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001012
1013 if (buf) {
1014 e->argument = lydict_insert_zc(ctx, word);
1015 } else {
1016 e->argument = lydict_insert(ctx, word, word_len);
1017 }
1018
1019 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001020 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001021
1022 ret = parse_ext_substmt(ctx, data, word, word_len, &e->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001023 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001024 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001025 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001026
1027 return ret;
1028}
1029
1030static LY_ERR
1031parse_text_field(struct ly_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
1032 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1033{
1034 LY_ERR ret = 0;
1035 char *buf, *word;
1036 int word_len;
1037 enum yang_keyword kw;
1038
1039 if (*value) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001040 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001041 return LY_EVALID;
1042 }
1043
1044 /* get value */
1045 ret = get_string(ctx, data, 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
1048 /* store value and spend buf if allocated */
1049 if (buf) {
1050 *value = lydict_insert_zc(ctx, word);
1051 } else {
1052 *value = lydict_insert(ctx, word, word_len);
1053 }
1054
1055 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001056 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001057
1058 switch (kw) {
1059 case YANG_CUSTOM:
1060 ret = parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001061 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001062 break;
1063 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001064 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001065 return LY_EVALID;
1066 }
1067 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001068 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001069
1070 return ret;
1071}
1072
1073static LY_ERR
1074parse_yangversion(struct ly_ctx *ctx, const char **data, struct lysp_module *mod)
1075{
1076 LY_ERR ret = 0;
1077 char *buf, *word;
1078 int word_len;
1079 enum yang_keyword kw;
1080
1081 if (mod->version) {
1082 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "yang-version");
1083 return LY_EVALID;
1084 }
1085
1086 /* get value */
1087 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001088 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001089
1090 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1091 mod->version = LYS_VERSION_1_0;
1092 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1093 mod->version = LYS_VERSION_1_1;
1094 } else {
1095 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "yang-version");
1096 free(buf);
1097 return LY_EVALID;
1098 }
1099 free(buf);
1100
1101 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001102 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001103
1104 switch (kw) {
1105 case YANG_CUSTOM:
1106 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001107 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001108 break;
1109 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001110 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001111 return LY_EVALID;
1112 }
1113 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001114 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001115
1116 return ret;
1117}
1118
1119static LY_ERR
1120parse_belongsto(struct ly_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
1121{
1122 LY_ERR ret = 0;
1123 char *buf, *word;
1124 int word_len;
1125 enum yang_keyword kw;
1126
1127 if (*belongsto) {
1128 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "belongs-to");
1129 return LY_EVALID;
1130 }
1131
1132 /* get value */
1133 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001134 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001135
1136 if (buf) {
1137 *belongsto = lydict_insert_zc(ctx, word);
1138 } else {
1139 *belongsto = lydict_insert(ctx, word, word_len);
1140 }
1141
1142 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001143 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001144
1145 switch (kw) {
1146 case YANG_PREFIX:
1147 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts);
1148 break;
1149 case YANG_CUSTOM:
1150 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts);
1151 break;
1152 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001153 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001154 return LY_EVALID;
1155 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001156 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001157 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001158 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001159
1160 /* mandatory substatements */
1161 if (!*prefix) {
1162 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "prefix", "belongs-to");
1163 return LY_EVALID;
1164 }
1165
1166 return ret;
1167}
1168
1169static LY_ERR
1170parse_revisiondate(struct ly_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
1171{
1172 LY_ERR ret = 0;
1173 char *buf, *word;
1174 int word_len;
1175 enum yang_keyword kw;
1176
1177 if (rev[0]) {
1178 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "revision-date");
1179 return LY_EVALID;
1180 }
1181
1182 /* get value */
1183 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001184 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001185
1186 /* check value */
1187 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
1188 free(buf);
1189 return LY_EVALID;
1190 }
1191
1192 /* store value and spend buf if allocated */
1193 strncpy(rev, word, word_len);
1194 free(buf);
1195
1196 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001197 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001198
1199 switch (kw) {
1200 case YANG_CUSTOM:
1201 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001202 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001203 break;
1204 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001205 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001206 return LY_EVALID;
1207 }
1208 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001209 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001210
1211 return ret;
1212}
1213
1214static LY_ERR
1215parse_include(struct ly_ctx *ctx, const char **data, struct lysp_include **includes)
1216{
1217 LY_ERR ret = 0;
1218 char *buf, *word;
1219 int word_len;
1220 enum yang_keyword kw;
1221 struct lysp_include *inc;
1222
1223 LYSP_ARRAY_NEW_RET(ctx, includes, inc, LY_EMEM);
1224
1225 /* get value */
1226 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001227 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001228
1229 if (buf) {
1230 inc->name = lydict_insert_zc(ctx, word);
1231 } else {
1232 inc->name = lydict_insert(ctx, word, word_len);
1233 }
1234
1235 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001236 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001237
1238 switch (kw) {
1239 case YANG_DESCRIPTION:
1240 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts);
1241 break;
1242 case YANG_REFERENCE:
1243 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts);
1244 break;
1245 case YANG_REVISION_DATE:
1246 ret = parse_revisiondate(ctx, data, inc->rev, &inc->exts);
1247 break;
1248 case YANG_CUSTOM:
1249 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts);
1250 break;
1251 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001252 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001253 return LY_EVALID;
1254 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001255 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001256 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001257 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001258
1259 return ret;
1260}
1261
1262static LY_ERR
1263parse_import(struct ly_ctx *ctx, const char **data, struct lysp_import **imports)
1264{
1265 LY_ERR ret = 0;
1266 char *buf, *word;
1267 int word_len;
1268 enum yang_keyword kw;
1269 struct lysp_import *imp;
1270
1271 LYSP_ARRAY_NEW_RET(ctx, imports, imp, LY_EVALID);
1272
1273 /* get value */
1274 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001275 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001276
1277 if (buf) {
1278 imp->name = lydict_insert_zc(ctx, word);
1279 } else {
1280 imp->name = lydict_insert(ctx, word, word_len);
1281 }
1282
1283 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001284 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001285
1286 switch (kw) {
1287 case YANG_PREFIX:
1288 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts);
1289 break;
1290 case YANG_DESCRIPTION:
1291 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts);
1292 break;
1293 case YANG_REFERENCE:
1294 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts);
1295 break;
1296 case YANG_REVISION_DATE:
1297 ret = parse_revisiondate(ctx, data, imp->rev, &imp->exts);
1298 break;
1299 case YANG_CUSTOM:
1300 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts);
1301 break;
1302 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001303 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001304 return LY_EVALID;
1305 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001306 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001307 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001308 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001309
1310 /* mandatory substatements */
1311 if (!imp->prefix) {
1312 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "prefix", "import");
1313 return LY_EVALID;
1314 }
1315
1316 return ret;
1317}
1318
1319static LY_ERR
1320parse_revision(struct ly_ctx *ctx, const char **data, struct lysp_revision **revs)
1321{
1322 LY_ERR ret = 0;
1323 char *buf, *word;
1324 int word_len;
1325 enum yang_keyword kw;
1326 struct lysp_revision *rev;
1327
1328 LYSP_ARRAY_NEW_RET(ctx, revs, rev, LY_EMEM);
1329
1330 /* get value */
1331 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001332 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001333
1334 /* check value */
1335 if (lysp_check_date(ctx, word, word_len, "revision")) {
1336 return LY_EVALID;
1337 }
1338
1339 strncpy(rev->rev, word, word_len);
1340 free(buf);
1341
1342 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001343 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001344
1345 switch (kw) {
1346 case YANG_DESCRIPTION:
1347 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts);
1348 break;
1349 case YANG_REFERENCE:
1350 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts);
1351 break;
1352 case YANG_CUSTOM:
1353 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts);
1354 break;
1355 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001356 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001357 return LY_EVALID;
1358 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001359 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001360 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001361 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001362
1363 return ret;
1364}
1365
1366static LY_ERR
1367parse_text_fields(struct ly_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
1368 struct lysp_ext_instance **exts)
1369{
1370 LY_ERR ret = 0;
1371 char *buf, *word;
1372 int count, word_len;
1373 enum yang_keyword kw;
1374
1375 /* allocate new pointer */
1376 for (count = 1; (*texts) && (*texts)[count - 1]; ++count);
1377 *texts = realloc(*texts, count * sizeof **texts);
1378 LY_CHECK_ERR_RET(!*texts, LOGMEM(ctx), LY_EMEM);
1379
1380 /* get value */
1381 ret = get_string(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001382 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001383
1384 if (buf) {
1385 (*texts)[count - 1] = lydict_insert_zc(ctx, word);
1386 } else {
1387 (*texts)[count - 1] = lydict_insert(ctx, word, word_len);
1388 }
1389
1390 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001391 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001392
1393 switch (kw) {
1394 case YANG_CUSTOM:
1395 ret = parse_ext(ctx, data, word, word_len, substmt, count - 1, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001396 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001397 break;
1398 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001399 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001400 return LY_EVALID;
1401 }
1402 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001403 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001404
1405 return ret;
1406}
1407
1408static LY_ERR
1409parse_config(struct ly_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
1410{
1411 LY_ERR ret = 0;
1412 char *buf, *word;
1413 int word_len;
1414 enum yang_keyword kw;
1415
1416 if (*flags & LYS_CONFIG_MASK) {
1417 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "config");
1418 return LY_EVALID;
1419 }
1420
1421 /* get value */
1422 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001423 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001424
1425 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1426 *flags |= LYS_CONFIG_W;
1427 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1428 *flags |= LYS_CONFIG_R;
1429 } else {
1430 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "config");
1431 free(buf);
1432 return LY_EVALID;
1433 }
1434 free(buf);
1435
1436 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001437 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438
1439 switch (kw) {
1440 case YANG_CUSTOM:
1441 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001442 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001443 break;
1444 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001445 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001446 return LY_EVALID;
1447 }
1448 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001449 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001450
1451 return ret;
1452}
1453
1454static LY_ERR
1455parse_mandatory(struct ly_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
1456{
1457 LY_ERR ret = 0;
1458 char *buf, *word;
1459 int word_len;
1460 enum yang_keyword kw;
1461
1462 if (*flags & LYS_MAND_MASK) {
1463 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "mandatory");
1464 return LY_EVALID;
1465 }
1466
1467 /* get value */
1468 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001469 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001470
1471 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1472 *flags |= LYS_MAND_TRUE;
1473 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1474 *flags |= LYS_MAND_FALSE;
1475 } else {
1476 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "mandatory");
1477 free(buf);
1478 return LY_EVALID;
1479 }
1480 free(buf);
1481
1482 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001483 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001484
1485 switch (kw) {
1486 case YANG_CUSTOM:
1487 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001488 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001489 break;
1490 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001491 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001492 return LY_EVALID;
1493 }
1494 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001495 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001496
1497 return ret;
1498}
1499
1500static LY_ERR
1501parse_restr(struct ly_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr *restr)
1502{
1503 LY_ERR ret = 0;
1504 char *buf, *word;
1505 int word_len;
1506 enum yang_keyword kw;
1507
1508 /* get value */
1509 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001510 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001511
1512 if (buf) {
1513 restr->arg = lydict_insert_zc(ctx, word);
1514 } else {
1515 restr->arg = lydict_insert(ctx, word, word_len);
1516 }
1517
1518 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001519 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001520
1521 switch (kw) {
1522 case YANG_DESCRIPTION:
1523 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
1524 break;
1525 case YANG_REFERENCE:
1526 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
1527 break;
1528 case YANG_ERROR_APP_TAG:
1529 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
1530 break;
1531 case YANG_ERROR_MESSAGE:
1532 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
1533 break;
1534 case YANG_CUSTOM:
1535 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
1536 break;
1537 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001538 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001539 return LY_EVALID;
1540 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001541 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001542 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001543 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001544
1545 return ret;
1546}
1547
1548static LY_ERR
1549parse_restrs(struct ly_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr **restrs)
1550{
1551 struct lysp_restr *restr;
1552
1553 LYSP_ARRAY_NEW_RET(ctx, restrs, restr, LY_EMEM);
1554
1555 return parse_restr(ctx, data, restr_kw, restr);
1556}
1557
1558static LY_ERR
1559parse_status(struct ly_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
1560{
1561 LY_ERR ret = 0;
1562 char *buf, *word;
1563 int word_len;
1564 enum yang_keyword kw;
1565
1566 if (*flags & LYS_STATUS_MASK) {
1567 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "status");
1568 return LY_EVALID;
1569 }
1570
1571 /* get value */
1572 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001573 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001574
1575 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1576 *flags |= LYS_STATUS_CURR;
1577 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1578 *flags |= LYS_STATUS_DEPRC;
1579 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1580 *flags |= LYS_STATUS_OBSLT;
1581 } else {
1582 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "status");
1583 free(buf);
1584 return LY_EVALID;
1585 }
1586 free(buf);
1587
1588 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001589 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001590
1591 switch (kw) {
1592 case YANG_CUSTOM:
1593 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001594 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001595 break;
1596 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001597 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001598 return LY_EVALID;
1599 }
1600 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001601 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001602
1603 return ret;
1604}
1605
1606static LY_ERR
1607parse_when(struct ly_ctx *ctx, const char **data, struct lysp_when **when_p)
1608{
1609 LY_ERR ret = 0;
1610 char *buf, *word;
1611 int word_len;
1612 enum yang_keyword kw;
1613 struct lysp_when *when;
1614
1615 if (*when_p) {
1616 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "when");
1617 return LY_EVALID;
1618 }
1619
1620 when = calloc(1, sizeof *when);
1621 LY_CHECK_ERR_RET(!when, LOGMEM(ctx), LY_EMEM);
1622 *when_p = when;
1623
1624 /* get value */
1625 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001626 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001627
1628 if (buf) {
1629 when->cond = lydict_insert_zc(ctx, word);
1630 } else {
1631 when->cond = lydict_insert(ctx, word, word_len);
1632 }
1633
1634 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001635 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001636
1637 switch (kw) {
1638 case YANG_DESCRIPTION:
1639 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts);
1640 break;
1641 case YANG_REFERENCE:
1642 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts);
1643 break;
1644 case YANG_CUSTOM:
1645 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts);
1646 break;
1647 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001648 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001649 return LY_EVALID;
1650 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001651 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001652 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001653 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001654
1655 return ret;
1656}
1657
1658static LY_ERR
1659parse_any(struct ly_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node **siblings)
1660{
1661 LY_ERR ret = 0;
1662 char *buf, *word;
1663 int word_len;
1664 struct lysp_node *iter;
1665 struct lysp_node_anydata *any;
1666
1667 /* create structure */
1668 any = calloc(1, sizeof *any);
1669 LY_CHECK_ERR_RET(!any, LOGMEM(ctx), LY_EMEM);
1670 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
1671
1672 /* insert into siblings */
1673 if (!*siblings) {
1674 *siblings = (struct lysp_node *)any;
1675 } else {
1676 for (iter = *siblings; iter->next; iter = iter->next);
1677 iter->next = (struct lysp_node *)any;
1678 }
1679
1680 /* get name */
1681 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001682 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001683
1684 if (buf) {
1685 any->name = lydict_insert_zc(ctx, word);
1686 } else {
1687 any->name = lydict_insert(ctx, word, word_len);
1688 }
1689
1690 /* parse substatements */
1691 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001692 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001693
1694 switch (kw) {
1695 case YANG_CONFIG:
1696 ret = parse_config(ctx, data, &any->flags, &any->exts);
1697 break;
1698 case YANG_DESCRIPTION:
1699 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts);
1700 break;
1701 case YANG_IF_FEATURE:
1702 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts);
1703 break;
1704 case YANG_MANDATORY:
1705 ret = parse_mandatory(ctx, data, &any->flags, &any->exts);
1706 break;
1707 case YANG_MUST:
1708 ret = parse_restrs(ctx, data, kw, &any->musts);
1709 break;
1710 case YANG_REFERENCE:
1711 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts);
1712 break;
1713 case YANG_STATUS:
1714 ret = parse_status(ctx, data, &any->flags, &any->exts);
1715 break;
1716 case YANG_WHEN:
1717 ret = parse_when(ctx, data, &any->when);
1718 break;
1719 case YANG_CUSTOM:
1720 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts);
1721 break;
1722 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001723 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
1724 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001725 return LY_EVALID;
1726 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001727 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001728 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001729 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001730
1731 return ret;
1732}
1733
1734static LY_ERR
1735parse_type_enum_value_pos(struct ly_ctx *ctx, const char **data, enum yang_keyword val_kw, int64_t *value, uint16_t *flags,
1736 struct lysp_ext_instance **exts)
1737{
1738 LY_ERR ret = 0;
1739 char *buf, *word, *ptr;
1740 int word_len;
1741 long int num;
1742 unsigned long int unum;
1743 enum yang_keyword kw;
1744
1745 if (*flags & LYS_SET_VALUE) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001746 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001747 return LY_EVALID;
1748 }
1749 *flags |= LYS_SET_VALUE;
1750
1751 /* get value */
1752 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001753 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001754
1755 if (!word_len || (word[0] == '+') || ((word[0] == '0') && (word_len > 1)) || ((val_kw == YANG_VALUE) && !strncmp(word, "-0", 2))) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001756 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001757 free(buf);
1758 return LY_EVALID;
1759 }
1760
1761 errno = 0;
1762 if (val_kw == YANG_VALUE) {
1763 num = strtol(word, &ptr, 10);
1764 } else {
1765 unum = strtoul(word, &ptr, 10);
1766 }
1767 /* we have not parsed the whole argument */
1768 if (ptr - word != word_len) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001769 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001770 free(buf);
1771 return LY_EVALID;
1772 }
1773 if (errno == ERANGE) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001774 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001775 free(buf);
1776 return LY_EVALID;
1777 }
1778 if (val_kw == YANG_VALUE) {
1779 *value = num;
1780 } else {
1781 *value = unum;
1782 }
1783 free(buf);
1784
1785 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001786 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001787
1788 switch (kw) {
1789 case YANG_CUSTOM:
1790 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 +02001791 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001792 break;
1793 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001794 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001795 return LY_EVALID;
1796 }
1797 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001798 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001799
1800 return ret;
1801}
1802
1803static LY_ERR
1804parse_type_enum(struct ly_ctx *ctx, const char **data, enum yang_keyword enum_kw, struct lysp_type_enum **enums)
1805{
1806 LY_ERR ret = 0;
1807 char *buf, *word;
1808 int word_len;
1809 enum yang_keyword kw;
1810 struct lysp_type_enum *enm;
1811
1812 LYSP_ARRAY_NEW_RET(ctx, enums, enm, LY_EMEM);
1813
1814 /* get value */
1815 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001816 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001817
1818 if (buf) {
1819 enm->name = lydict_insert_zc(ctx, word);
1820 } else {
1821 enm->name = lydict_insert(ctx, word, word_len);
1822 }
1823
1824 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001825 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001826
1827 switch (kw) {
1828 case YANG_DESCRIPTION:
1829 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts);
1830 break;
1831 case YANG_IF_FEATURE:
1832 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts);
1833 break;
1834 case YANG_REFERENCE:
1835 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts);
1836 break;
1837 case YANG_STATUS:
1838 ret = parse_status(ctx, data, &enm->flags, &enm->exts);
1839 break;
1840 case YANG_VALUE:
1841 case YANG_POSITION:
1842 ret = parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts);
1843 break;
1844 case YANG_CUSTOM:
1845 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts);
1846 break;
1847 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001848 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001849 return LY_EVALID;
1850 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001851 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001852 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001853 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001854
1855 return ret;
1856}
1857
1858static LY_ERR
1859parse_type_fracdigits(struct ly_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
1860{
1861 LY_ERR ret = 0;
1862 char *buf, *word, *ptr;
1863 int word_len;
1864 unsigned long int num;
1865 enum yang_keyword kw;
1866
1867 if (*fracdig) {
1868 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "fraction-digits");
1869 return LY_EVALID;
1870 }
1871
1872 /* get value */
1873 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001874 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001875
1876 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
1877 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "fraction-digits");
1878 free(buf);
1879 return LY_EVALID;
1880 }
1881
1882 errno = 0;
1883 num = strtoul(word, &ptr, 10);
1884 /* we have not parsed the whole argument */
1885 if (ptr - word != word_len) {
1886 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "fraction-digits");
1887 free(buf);
1888 return LY_EVALID;
1889 }
1890 if ((errno == ERANGE) || (num > 18)) {
1891 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_OOB, word_len, word, "fraction-digits");
1892 free(buf);
1893 return LY_EVALID;
1894 }
1895 *fracdig = num;
1896 free(buf);
1897
1898 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001899 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001900
1901 switch (kw) {
1902 case YANG_CUSTOM:
1903 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001904 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001905 break;
1906 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001907 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001908 return LY_EVALID;
1909 }
1910 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001911 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001912
1913 return ret;
1914}
1915
1916static LY_ERR
1917parse_type_reqinstance(struct ly_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
1918 struct lysp_ext_instance **exts)
1919{
1920 LY_ERR ret = 0;
1921 char *buf, *word;
1922 int word_len;
1923 enum yang_keyword kw;
1924
1925 if (*flags & LYS_SET_REQINST) {
1926 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "require-instance");
1927 return LY_EVALID;
1928 }
1929 *flags |= LYS_SET_REQINST;
1930
1931 /* get value */
1932 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001933 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001934
1935 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1936 *reqinst = 1;
1937 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
1938 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "require-instance");
1939 free(buf);
1940 return LY_EVALID;
1941 }
1942 free(buf);
1943
1944 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001945 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001946
1947 switch (kw) {
1948 case YANG_CUSTOM:
1949 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001950 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001951 break;
1952 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02001953 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001954 return LY_EVALID;
1955 }
1956 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001957 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001958
1959 return ret;
1960}
1961
1962static LY_ERR
1963parse_type_pattern_modifier(struct ly_ctx *ctx, const char **data, const char **pat, struct lysp_ext_instance **exts)
1964{
1965 LY_ERR ret = 0;
1966 char *buf, *word;
1967 int word_len;
1968 enum yang_keyword kw;
1969
1970 if ((*pat)[0] == 0x15) {
1971 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "modifier");
1972 return LY_EVALID;
1973 }
1974
1975 /* get value */
1976 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001977 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001978
1979 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
1980 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "modifier");
1981 free(buf);
1982 return LY_EVALID;
1983 }
1984 free(buf);
1985
1986 /* replace the value in the dictionary */
1987 buf = malloc(strlen(*pat) + 1);
1988 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx), LY_EMEM);
1989 strcpy(buf, *pat);
1990 lydict_remove(ctx, *pat);
1991
1992 assert(buf[0] == 0x06);
1993 buf[0] = 0x15;
1994 *pat = lydict_insert_zc(ctx, buf);
1995
1996 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001997 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001998
1999 switch (kw) {
2000 case YANG_CUSTOM:
2001 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002002 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002003 break;
2004 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002005 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002006 return LY_EVALID;
2007 }
2008 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002009 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002010
2011 return ret;
2012}
2013
2014static LY_ERR
2015parse_type_pattern(struct ly_ctx *ctx, const char **data, struct lysp_restr **patterns)
2016{
2017 LY_ERR ret = 0;
2018 char *buf, *word;
2019 int word_len;
2020 enum yang_keyword kw;
2021 struct lysp_restr *restr;
2022
2023 LYSP_ARRAY_NEW_RET(ctx, patterns, restr, LY_EMEM);
2024
2025 /* get value */
2026 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002027 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002028
2029 /* add special meaning first byte */
2030 if (buf) {
2031 buf = realloc(buf, word_len + 2);
2032 word = buf;
2033 } else {
2034 buf = malloc(word_len + 2);
2035 }
2036 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx), LY_EMEM);
2037 memmove(buf + 1, word, word_len + 1);
2038 word[0] = 0x06;
2039 restr->arg = lydict_insert_zc(ctx, word);
2040
2041 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002042 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002043
2044 switch (kw) {
2045 case YANG_DESCRIPTION:
2046 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
2047 break;
2048 case YANG_REFERENCE:
2049 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
2050 break;
2051 case YANG_ERROR_APP_TAG:
2052 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
2053 break;
2054 case YANG_ERROR_MESSAGE:
2055 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
2056 break;
2057 case YANG_MODIFIER:
2058 ret = parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts);
2059 break;
2060 case YANG_CUSTOM:
2061 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
2062 break;
2063 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002064 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002065 return LY_EVALID;
2066 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002067 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002068 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002069 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002070
2071 return ret;
2072}
2073
2074static LY_ERR
2075parse_type(struct ly_ctx *ctx, const char **data, struct lysp_type *type)
2076{
2077 LY_ERR ret = 0;
2078 char *buf, *word;
2079 int word_len;
2080 enum yang_keyword kw;
2081 struct lysp_type *nest_type;
2082
2083 if (type->name) {
2084 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "type");
2085 return LY_EVALID;
2086 }
2087
2088 /* get value */
2089 ret = get_string(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002090 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002091
2092 if (buf) {
2093 type->name = lydict_insert_zc(ctx, word);
2094 } else {
2095 type->name = lydict_insert(ctx, word, word_len);
2096 }
2097
2098 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002099 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002100
2101 switch (kw) {
2102 case YANG_BASE:
2103 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts);
2104 break;
2105 case YANG_BIT:
2106 ret = parse_type_enum(ctx, data, kw, &type->bits);
2107 break;
2108 case YANG_ENUM:
2109 ret = parse_type_enum(ctx, data, kw, &type->enums);
2110 break;
2111 case YANG_FRACTION_DIGITS:
2112 ret = parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts);
2113 break;
2114 case YANG_LENGTH:
2115 if (type->length) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002116 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002117 return LY_EVALID;
2118 }
2119 type->length = calloc(1, sizeof *type->length);
2120 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx), LY_EMEM);
2121
2122 ret = parse_restr(ctx, data, kw, type->length);
2123 break;
2124 case YANG_PATH:
2125 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts);
2126 break;
2127 case YANG_PATTERN:
2128 ret = parse_type_pattern(ctx, data, &type->patterns);
2129 break;
2130 case YANG_RANGE:
2131 if (type->range) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002132 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002133 return LY_EVALID;
2134 }
2135 type->range = calloc(1, sizeof *type->range);
2136 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx), LY_EVALID);
2137
2138 ret = parse_restr(ctx, data, kw, type->range);
2139 break;
2140 case YANG_REQUIRE_INSTANCE:
2141 ret = parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts);
2142 break;
2143 case YANG_TYPE:
2144 {
2145 LYSP_ARRAY_NEW_RET(ctx, &type->types, nest_type, LY_EMEM);
2146 }
2147 ret = parse_type(ctx, data, nest_type);
2148 break;
2149 case YANG_CUSTOM:
2150 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts);
2151 break;
2152 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002153 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002154 return LY_EVALID;
2155 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002156 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002157 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002158 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002159
2160 return ret;
2161}
2162
2163static LY_ERR
2164parse_leaf(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
2165{
2166 LY_ERR ret = 0;
2167 char *buf, *word;
2168 int word_len;
2169 enum yang_keyword kw;
2170 struct lysp_node *iter;
2171 struct lysp_node_leaf *leaf;
2172
2173 /* create structure */
2174 leaf = calloc(1, sizeof *leaf);
2175 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx), LY_EMEM);
2176 leaf->nodetype = LYS_LEAF;
2177
2178 /* insert into siblings */
2179 if (!*siblings) {
2180 *siblings = (struct lysp_node *)leaf;
2181 } else {
2182 for (iter = *siblings; iter->next; iter = iter->next);
2183 iter->next = (struct lysp_node *)leaf;
2184 }
2185
2186 /* get name */
2187 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002188 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189
2190 if (buf) {
2191 leaf->name = lydict_insert_zc(ctx, word);
2192 } else {
2193 leaf->name = lydict_insert(ctx, word, word_len);
2194 }
2195
2196 /* parse substatements */
2197 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002198 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002199
2200 switch (kw) {
2201 case YANG_CONFIG:
2202 ret = parse_config(ctx, data, &leaf->flags, &leaf->exts);
2203 break;
2204 case YANG_DEFAULT:
2205 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts);
2206 break;
2207 case YANG_DESCRIPTION:
2208 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts);
2209 break;
2210 case YANG_IF_FEATURE:
2211 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts);
2212 break;
2213 case YANG_MANDATORY:
2214 ret = parse_mandatory(ctx, data, &leaf->flags, &leaf->exts);
2215 break;
2216 case YANG_MUST:
2217 ret = parse_restrs(ctx, data, kw, &leaf->musts);
2218 break;
2219 case YANG_REFERENCE:
2220 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts);
2221 break;
2222 case YANG_STATUS:
2223 ret = parse_status(ctx, data, &leaf->flags, &leaf->exts);
2224 break;
2225 case YANG_TYPE:
2226 ret = parse_type(ctx, data, &leaf->type);
2227 break;
2228 case YANG_UNITS:
2229 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts);
2230 break;
2231 case YANG_WHEN:
2232 ret = parse_when(ctx, data, &leaf->when);
2233 break;
2234 case YANG_CUSTOM:
2235 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts);
2236 break;
2237 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002238 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002239 return LY_EVALID;
2240 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002241 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002242 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002243 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002244
2245 /* mandatory substatements */
2246 if (!leaf->type.name) {
2247 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "type", "leaf");
2248 return LY_EVALID;
2249 }
2250
2251 return ret;
2252}
2253
2254static LY_ERR
2255parse_maxelements(struct ly_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
2256{
2257 LY_ERR ret = 0;
2258 char *buf, *word, *ptr;
2259 int word_len;
2260 unsigned long int num;
2261 enum yang_keyword kw;
2262
2263 if (*flags & LYS_SET_MAX) {
2264 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "max-elements");
2265 return LY_EVALID;
2266 }
2267 *flags |= LYS_SET_MAX;
2268
2269 /* get value */
2270 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002271 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002272
2273 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
2274 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "max-elements");
2275 free(buf);
2276 return LY_EVALID;
2277 }
2278
2279 if (strncmp(word, "unbounded", word_len)) {
2280 errno = 0;
2281 num = strtoul(word, &ptr, 10);
2282 /* we have not parsed the whole argument */
2283 if (ptr - word != word_len) {
2284 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "max-elements");
2285 free(buf);
2286 return LY_EVALID;
2287 }
2288 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2289 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_OOB, word_len, word, "max-elements");
2290 free(buf);
2291 return LY_EVALID;
2292 }
2293
2294 *max = num;
2295 }
2296 free(buf);
2297
2298 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002299 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002300
2301 switch (kw) {
2302 case YANG_CUSTOM:
2303 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002304 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002305 break;
2306 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002307 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002308 return LY_EVALID;
2309 }
2310 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002311 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002312
2313 return ret;
2314}
2315
2316static LY_ERR
2317parse_minelements(struct ly_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
2318{
2319 LY_ERR ret = 0;
2320 char *buf, *word, *ptr;
2321 int word_len;
2322 unsigned long int num;
2323 enum yang_keyword kw;
2324
2325 if (*flags & LYS_SET_MIN) {
2326 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "min-elements");
2327 return LY_EVALID;
2328 }
2329 *flags |= LYS_SET_MIN;
2330
2331 /* get value */
2332 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002333 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002334
2335 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
2336 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "min-elements");
2337 free(buf);
2338 return LY_EVALID;
2339 }
2340
2341 errno = 0;
2342 num = strtoul(word, &ptr, 10);
2343 /* we have not parsed the whole argument */
2344 if (ptr - word != word_len) {
2345 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "min-elements");
2346 free(buf);
2347 return LY_EVALID;
2348 }
2349 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2350 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_OOB, word_len, word, "min-elements");
2351 free(buf);
2352 return LY_EVALID;
2353 }
2354 *min = num;
2355 free(buf);
2356
2357 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002358 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002359
2360 switch (kw) {
2361 case YANG_CUSTOM:
2362 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002363 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002364 break;
2365 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002366 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002367 return LY_EVALID;
2368 }
2369 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002370 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002371
2372 return ret;
2373}
2374
2375static LY_ERR
2376parse_orderedby(struct ly_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
2377{
2378 LY_ERR ret = 0;
2379 char *buf, *word;
2380 int word_len;
2381 enum yang_keyword kw;
2382
2383 if (*flags & LYS_ORDBY_MASK) {
2384 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "ordered-by");
2385 return LY_EVALID;
2386 }
2387
2388 /* get value */
2389 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002390 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002391
2392 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2393 *flags |= LYS_ORDBY_SYSTEM;
2394 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2395 *flags |= LYS_ORDBY_USER;
2396 } else {
2397 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "ordered-by");
2398 free(buf);
2399 return LY_EVALID;
2400 }
2401 free(buf);
2402
2403 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002404 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002405
2406 switch (kw) {
2407 case YANG_CUSTOM:
2408 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002409 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002410 break;
2411 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002412 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002413 return LY_EVALID;
2414 }
2415 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002416 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002417
2418 return ret;
2419}
2420
2421static LY_ERR
2422parse_leaflist(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
2423{
2424 LY_ERR ret = 0;
2425 char *buf, *word;
2426 int word_len;
2427 enum yang_keyword kw;
2428 struct lysp_node *iter;
2429 struct lysp_node_leaflist *llist;
2430
2431 /* create structure */
2432 llist = calloc(1, sizeof *llist);
2433 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx), LY_EMEM);
2434 llist->nodetype = LYS_LEAFLIST;
2435
2436 /* insert into siblings */
2437 if (!*siblings) {
2438 *siblings = (struct lysp_node *)llist;
2439 } else {
2440 for (iter = *siblings; iter->next; iter = iter->next);
2441 iter->next = (struct lysp_node *)llist;
2442 }
2443
2444 /* get name */
2445 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002446 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002447
2448 if (buf) {
2449 llist->name = lydict_insert_zc(ctx, word);
2450 } else {
2451 llist->name = lydict_insert(ctx, word, word_len);
2452 }
2453
2454 /* parse substatements */
2455 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002456 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002457
2458 switch (kw) {
2459 case YANG_CONFIG:
2460 ret = parse_config(ctx, data, &llist->flags, &llist->exts);
2461 break;
2462 case YANG_DEFAULT:
2463 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts);
2464 break;
2465 case YANG_DESCRIPTION:
2466 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts);
2467 break;
2468 case YANG_IF_FEATURE:
2469 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts);
2470 break;
2471 case YANG_MAX_ELEMENTS:
2472 ret = parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts);
2473 break;
2474 case YANG_MIN_ELEMENTS:
2475 ret = parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts);
2476 break;
2477 case YANG_MUST:
2478 ret = parse_restrs(ctx, data, kw, &llist->musts);
2479 break;
2480 case YANG_ORDERED_BY:
2481 ret = parse_orderedby(ctx, data, &llist->flags, &llist->exts);
2482 break;
2483 case YANG_REFERENCE:
2484 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts);
2485 break;
2486 case YANG_STATUS:
2487 ret = parse_status(ctx, data, &llist->flags, &llist->exts);
2488 break;
2489 case YANG_TYPE:
2490 ret = parse_type(ctx, data, &llist->type);
2491 break;
2492 case YANG_UNITS:
2493 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts);
2494 break;
2495 case YANG_WHEN:
2496 ret = parse_when(ctx, data, &llist->when);
2497 break;
2498 case YANG_CUSTOM:
2499 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts);
2500 break;
2501 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002502 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002503 return LY_EVALID;
2504 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002505 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002506 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002507 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002508
2509 /* mandatory substatements */
2510 if (!llist->type.name) {
2511 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "type", "leaf-list");
2512 return LY_EVALID;
2513 }
2514
2515 return ret;
2516}
2517
2518static LY_ERR
2519parse_refine(struct ly_ctx *ctx, const char **data, struct lysp_refine **refines)
2520{
2521 LY_ERR ret = 0;
2522 char *buf, *word;
2523 int word_len;
2524 enum yang_keyword kw;
2525 struct lysp_refine *rf;
2526
2527 LYSP_ARRAY_NEW_RET(ctx, refines, rf, LY_EMEM);
2528
2529 /* get value */
2530 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002531 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002532
2533 if (buf) {
2534 rf->nodeid = lydict_insert_zc(ctx, word);
2535 } else {
2536 rf->nodeid = lydict_insert(ctx, word, word_len);
2537 }
2538
2539 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002540 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002541
2542 switch (kw) {
2543 case YANG_CONFIG:
2544 ret = parse_config(ctx, data, &rf->flags, &rf->exts);
2545 break;
2546 case YANG_DEFAULT:
2547 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts);
2548 break;
2549 case YANG_DESCRIPTION:
2550 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts);
2551 break;
2552 case YANG_IF_FEATURE:
2553 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts);
2554 break;
2555 case YANG_MAX_ELEMENTS:
2556 ret = parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts);
2557 break;
2558 case YANG_MIN_ELEMENTS:
2559 ret = parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts);
2560 break;
2561 case YANG_MUST:
2562 ret = parse_restrs(ctx, data, kw, &rf->musts);
2563 break;
2564 case YANG_MANDATORY:
2565 ret = parse_mandatory(ctx, data, &rf->flags, &rf->exts);
2566 break;
2567 case YANG_REFERENCE:
2568 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts);
2569 break;
2570 case YANG_PRESENCE:
2571 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts);
2572 break;
2573 case YANG_CUSTOM:
2574 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts);
2575 break;
2576 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002577 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002578 return LY_EVALID;
2579 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002580 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002581 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002582 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002583
2584 return ret;
2585}
2586
2587static LY_ERR
2588parse_typedef(struct ly_ctx *ctx, const char **data, struct lysp_tpdf **typedefs)
2589{
2590 LY_ERR ret = 0;
2591 char *buf, *word;
2592 int word_len;
2593 enum yang_keyword kw;
2594 struct lysp_tpdf *tpdf;
2595
2596 LYSP_ARRAY_NEW_RET(ctx, typedefs, tpdf, LY_EMEM);
2597
2598 /* get value */
2599 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002600 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002601
2602 if (buf) {
2603 tpdf->name = lydict_insert_zc(ctx, word);
2604 } else {
2605 tpdf->name = lydict_insert(ctx, word, word_len);
2606 }
2607
2608 /* parse substatements */
2609 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002610 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002611
2612 switch (kw) {
2613 case YANG_DEFAULT:
2614 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts);
2615 break;
2616 case YANG_DESCRIPTION:
2617 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts);
2618 break;
2619 case YANG_REFERENCE:
2620 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts);
2621 break;
2622 case YANG_STATUS:
2623 ret = parse_status(ctx, data, &tpdf->flags, &tpdf->exts);
2624 break;
2625 case YANG_TYPE:
2626 ret = parse_type(ctx, data, &tpdf->type);
2627 break;
2628 case YANG_UNITS:
2629 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts);
2630 break;
2631 case YANG_CUSTOM:
2632 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts);
2633 break;
2634 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002635 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636 return LY_EVALID;
2637 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002638 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002639 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002640 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002641
2642 /* mandatory substatements */
2643 if (!tpdf->type.name) {
2644 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "type", "typedef");
2645 return LY_EVALID;
2646 }
2647
2648 return ret;
2649}
2650
2651static LY_ERR
2652parse_inout(struct ly_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_action_inout **inout_p)
2653{
2654 LY_ERR ret = 0;
2655 char *word;
2656 int word_len;
2657 struct lysp_action_inout *inout;
2658
2659 if (*inout_p) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002660 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002661 return LY_EVALID;
2662 }
2663
2664 /* create structure */
2665 inout = calloc(1, sizeof *inout);
2666 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx), LY_EMEM);
2667 *inout_p = inout;
2668
2669 /* parse substatements */
2670 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002671 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002672
2673 switch (kw) {
2674 case YANG_ANYDATA:
2675 case YANG_ANYXML:
2676 ret = parse_any(ctx, data, kw, &inout->data);
2677 break;
2678 case YANG_CHOICE:
2679 ret = parse_choice(ctx, data, &inout->data);
2680 break;
2681 case YANG_CONTAINER:
2682 ret = parse_container(ctx, data, &inout->data);
2683 break;
2684 case YANG_LEAF:
2685 ret = parse_leaf(ctx, data, &inout->data);
2686 break;
2687 case YANG_LEAF_LIST:
2688 ret = parse_leaflist(ctx, data, &inout->data);
2689 break;
2690 case YANG_LIST:
2691 ret = parse_list(ctx, data, &inout->data);
2692 break;
2693 case YANG_USES:
2694 ret = parse_uses(ctx, data, &inout->data);
2695 break;
2696
2697 case YANG_TYPEDEF:
2698 ret = parse_typedef(ctx, data, &inout->typedefs);
2699 break;
2700 case YANG_MUST:
2701 ret = parse_restrs(ctx, data, kw, &inout->musts);
2702 break;
2703 case YANG_GROUPING:
2704 ret = parse_grouping(ctx, data, &inout->groupings);
2705 break;
2706 case YANG_CUSTOM:
2707 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts);
2708 break;
2709 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002710 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002711 return LY_EVALID;
2712 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002713 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002714 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002715 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002716
2717 return ret;
2718}
2719
2720static LY_ERR
2721parse_action(struct ly_ctx *ctx, const char **data, struct lysp_action **actions)
2722{
2723 LY_ERR ret = 0;
2724 char *buf, *word;
2725 int word_len;
2726 enum yang_keyword kw;
2727 struct lysp_action *act;
2728
2729 LYSP_ARRAY_NEW_RET(ctx, actions, act, LY_EMEM);
2730
2731 /* get value */
2732 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002733 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002734
2735 if (buf) {
2736 act->name = lydict_insert_zc(ctx, word);
2737 } else {
2738 act->name = lydict_insert(ctx, word, word_len);
2739 }
2740
2741 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002742 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002743
2744 switch (kw) {
2745 case YANG_DESCRIPTION:
2746 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts);
2747 break;
2748 case YANG_IF_FEATURE:
2749 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts);
2750 break;
2751 case YANG_REFERENCE:
2752 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts);
2753 break;
2754 case YANG_STATUS:
2755 ret = parse_status(ctx, data, &act->flags, &act->exts);
2756 break;
2757
2758 case YANG_INPUT:
2759 ret = parse_inout(ctx, data, kw, &act->input);
2760 break;
2761 case YANG_OUTPUT:
2762 ret = parse_inout(ctx, data, kw, &act->output);
2763 break;
2764
2765 case YANG_TYPEDEF:
2766 ret = parse_typedef(ctx, data, &act->typedefs);
2767 break;
2768 case YANG_GROUPING:
2769 ret = parse_grouping(ctx, data, &act->groupings);
2770 break;
2771 case YANG_CUSTOM:
2772 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts);
2773 break;
2774 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002775 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002776 return LY_EVALID;
2777 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002778 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002779 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002780 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002781
2782 return ret;
2783}
2784
2785static LY_ERR
2786parse_notif(struct ly_ctx *ctx, const char **data, struct lysp_notif **notifs)
2787{
2788 LY_ERR ret = 0;
2789 char *buf, *word;
2790 int word_len;
2791 enum yang_keyword kw;
2792 struct lysp_notif *notif;
2793
2794 LYSP_ARRAY_NEW_RET(ctx, notifs, notif, LY_EMEM);
2795
2796 /* get value */
2797 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002798 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002799
2800 if (buf) {
2801 notif->name = lydict_insert_zc(ctx, word);
2802 } else {
2803 notif->name = lydict_insert(ctx, word, word_len);
2804 }
2805
2806 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002807 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002808
2809 switch (kw) {
2810 case YANG_DESCRIPTION:
2811 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts);
2812 break;
2813 case YANG_IF_FEATURE:
2814 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts);
2815 break;
2816 case YANG_REFERENCE:
2817 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts);
2818 break;
2819 case YANG_STATUS:
2820 ret = parse_status(ctx, data, &notif->flags, &notif->exts);
2821 break;
2822
2823 case YANG_ANYDATA:
2824 case YANG_ANYXML:
2825 ret = parse_any(ctx, data, kw, &notif->data);
2826 break;
2827 case YANG_CHOICE:
2828 ret = parse_case(ctx, data, &notif->data);
2829 break;
2830 case YANG_CONTAINER:
2831 ret = parse_container(ctx, data, &notif->data);
2832 break;
2833 case YANG_LEAF:
2834 ret = parse_leaf(ctx, data, &notif->data);
2835 break;
2836 case YANG_LEAF_LIST:
2837 ret = parse_leaflist(ctx, data, &notif->data);
2838 break;
2839 case YANG_LIST:
2840 ret = parse_list(ctx, data, &notif->data);
2841 break;
2842 case YANG_USES:
2843 ret = parse_uses(ctx, data, &notif->data);
2844 break;
2845
2846 case YANG_MUST:
2847 ret = parse_restrs(ctx, data, kw, &notif->musts);
2848 break;
2849 case YANG_TYPEDEF:
2850 ret = parse_typedef(ctx, data, &notif->typedefs);
2851 break;
2852 case YANG_GROUPING:
2853 ret = parse_grouping(ctx, data, &notif->groupings);
2854 break;
2855 case YANG_CUSTOM:
2856 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts);
2857 break;
2858 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002859 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 return LY_EVALID;
2861 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002862 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002864 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002865
2866 return ret;
2867}
2868
2869static LY_ERR
2870parse_grouping(struct ly_ctx *ctx, const char **data, struct lysp_grp **groupings)
2871{
2872 LY_ERR ret = 0;
2873 char *buf, *word;
2874 int word_len;
2875 enum yang_keyword kw;
2876 struct lysp_grp *grp;
2877
2878 LYSP_ARRAY_NEW_RET(ctx, groupings, grp, LY_EMEM);
2879
2880 /* get value */
2881 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002882 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002883
2884 if (buf) {
2885 grp->name = lydict_insert_zc(ctx, word);
2886 } else {
2887 grp->name = lydict_insert(ctx, word, word_len);
2888 }
2889
2890 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002891 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002892
2893 switch (kw) {
2894 case YANG_DESCRIPTION:
2895 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts);
2896 break;
2897 case YANG_REFERENCE:
2898 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts);
2899 break;
2900 case YANG_STATUS:
2901 ret = parse_status(ctx, data, &grp->flags, &grp->exts);
2902 break;
2903
2904 case YANG_ANYDATA:
2905 case YANG_ANYXML:
2906 ret = parse_any(ctx, data, kw, &grp->data);
2907 break;
2908 case YANG_CHOICE:
2909 ret = parse_choice(ctx, data, &grp->data);
2910 break;
2911 case YANG_CONTAINER:
2912 ret = parse_container(ctx, data, &grp->data);
2913 break;
2914 case YANG_LEAF:
2915 ret = parse_leaf(ctx, data, &grp->data);
2916 break;
2917 case YANG_LEAF_LIST:
2918 ret = parse_leaflist(ctx, data, &grp->data);
2919 break;
2920 case YANG_LIST:
2921 ret = parse_list(ctx, data, &grp->data);
2922 break;
2923 case YANG_USES:
2924 ret = parse_uses(ctx, data, &grp->data);
2925 break;
2926
2927 case YANG_TYPEDEF:
2928 ret = parse_typedef(ctx, data, &grp->typedefs);
2929 break;
2930 case YANG_ACTION:
2931 ret = parse_action(ctx, data, &grp->actions);
2932 break;
2933 case YANG_GROUPING:
2934 ret = parse_grouping(ctx, data, &grp->groupings);
2935 break;
2936 case YANG_NOTIFICATION:
2937 ret = parse_notif(ctx, data, &grp->notifs);
2938 break;
2939 case YANG_CUSTOM:
2940 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts);
2941 break;
2942 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02002943 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002944 return LY_EVALID;
2945 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002946 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002947 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002948 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002949
2950 return ret;
2951}
2952
2953static LY_ERR
2954parse_augment(struct ly_ctx *ctx, const char **data, struct lysp_augment **augments)
2955{
2956 LY_ERR ret = 0;
2957 char *buf, *word;
2958 int word_len;
2959 enum yang_keyword kw;
2960 struct lysp_augment *aug;
2961
2962 LYSP_ARRAY_NEW_RET(ctx, augments, aug, LY_EMEM);
2963
2964 /* get value */
2965 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002966 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002967
2968 if (buf) {
2969 aug->nodeid = lydict_insert_zc(ctx, word);
2970 } else {
2971 aug->nodeid = lydict_insert(ctx, word, word_len);
2972 }
2973
2974 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002975 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002976
2977 switch (kw) {
2978 case YANG_DESCRIPTION:
2979 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts);
2980 break;
2981 case YANG_IF_FEATURE:
2982 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts);
2983 break;
2984 case YANG_REFERENCE:
2985 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts);
2986 break;
2987 case YANG_STATUS:
2988 ret = parse_status(ctx, data, &aug->flags, &aug->exts);
2989 break;
2990 case YANG_WHEN:
2991 ret = parse_when(ctx, data, &aug->when);
2992 break;
2993
2994 case YANG_ANYDATA:
2995 case YANG_ANYXML:
2996 ret = parse_any(ctx, data, kw, &aug->child);
2997 break;
2998 case YANG_CASE:
2999 ret = parse_case(ctx, data, &aug->child);
3000 break;
3001 case YANG_CHOICE:
3002 ret = parse_choice(ctx, data, &aug->child);
3003 break;
3004 case YANG_CONTAINER:
3005 ret = parse_container(ctx, data, &aug->child);
3006 break;
3007 case YANG_LEAF:
3008 ret = parse_leaf(ctx, data, &aug->child);
3009 break;
3010 case YANG_LEAF_LIST:
3011 ret = parse_leaflist(ctx, data, &aug->child);
3012 break;
3013 case YANG_LIST:
3014 ret = parse_list(ctx, data, &aug->child);
3015 break;
3016 case YANG_USES:
3017 ret = parse_uses(ctx, data, &aug->child);
3018 break;
3019
3020 case YANG_ACTION:
3021 ret = parse_action(ctx, data, &aug->actions);
3022 break;
3023 case YANG_NOTIFICATION:
3024 ret = parse_notif(ctx, data, &aug->notifs);
3025 break;
3026 case YANG_CUSTOM:
3027 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts);
3028 break;
3029 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003030 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003031 return LY_EVALID;
3032 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003033 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003034 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003035 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003036
3037 return ret;
3038}
3039
3040static LY_ERR
3041parse_uses(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
3042{
3043 LY_ERR ret = 0;
3044 char *buf, *word;
3045 int word_len;
3046 enum yang_keyword kw;
3047 struct lysp_node *iter;
3048 struct lysp_node_uses *uses;
3049
3050 /* create structure */
3051 uses = calloc(1, sizeof *uses);
3052 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx), LY_EMEM);
3053 uses->nodetype = LYS_USES;
3054
3055 /* insert into siblings */
3056 if (!*siblings) {
3057 *siblings = (struct lysp_node *)uses;
3058 } else {
3059 for (iter = *siblings; iter->next; iter = iter->next);
3060 iter->next = (struct lysp_node *)uses;
3061 }
3062
3063 /* get name */
3064 ret = get_string(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003065 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003066
3067 if (buf) {
3068 uses->name = lydict_insert_zc(ctx, word);
3069 } else {
3070 uses->name = lydict_insert(ctx, word, word_len);
3071 }
3072
3073 /* parse substatements */
3074 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003075 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076
3077 switch (kw) {
3078 case YANG_DESCRIPTION:
3079 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts);
3080 break;
3081 case YANG_IF_FEATURE:
3082 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts);
3083 break;
3084 case YANG_REFERENCE:
3085 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts);
3086 break;
3087 case YANG_STATUS:
3088 ret = parse_status(ctx, data, &uses->flags, &uses->exts);
3089 break;
3090 case YANG_WHEN:
3091 ret = parse_when(ctx, data, &uses->when);
3092 break;
3093
3094 case YANG_REFINE:
3095 ret = parse_refine(ctx, data, &uses->refines);
3096 break;
3097 case YANG_AUGMENT:
3098 ret = parse_augment(ctx, data, &uses->augments);
3099 break;
3100 case YANG_CUSTOM:
3101 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts);
3102 break;
3103 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003104 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003105 return LY_EVALID;
3106 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003107 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003108 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003109 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003110
3111 return ret;
3112}
3113
3114static LY_ERR
3115parse_case(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
3116{
3117 LY_ERR ret = 0;
3118 char *buf, *word;
3119 int word_len;
3120 enum yang_keyword kw;
3121 struct lysp_node *iter;
3122 struct lysp_node_case *cas;
3123
3124 /* create structure */
3125 cas = calloc(1, sizeof *cas);
3126 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx), LY_EMEM);
3127 cas->nodetype = LYS_CASE;
3128
3129 /* insert into siblings */
3130 if (!*siblings) {
3131 *siblings = (struct lysp_node *)cas;
3132 } else {
3133 for (iter = *siblings; iter->next; iter = iter->next);
3134 iter->next = (struct lysp_node *)cas;
3135 }
3136
3137 /* get name */
3138 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003139 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003140
3141 if (buf) {
3142 cas->name = lydict_insert_zc(ctx, word);
3143 } else {
3144 cas->name = lydict_insert(ctx, word, word_len);
3145 }
3146
3147 /* parse substatements */
3148 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003149 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003150
3151 switch (kw) {
3152 case YANG_DESCRIPTION:
3153 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts);
3154 break;
3155 case YANG_IF_FEATURE:
3156 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts);
3157 break;
3158 case YANG_REFERENCE:
3159 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts);
3160 break;
3161 case YANG_STATUS:
3162 ret = parse_status(ctx, data, &cas->flags, &cas->exts);
3163 break;
3164 case YANG_WHEN:
3165 ret = parse_when(ctx, data, &cas->when);
3166 break;
3167
3168 case YANG_ANYDATA:
3169 case YANG_ANYXML:
3170 ret = parse_any(ctx, data, kw, &cas->child);
3171 break;
3172 case YANG_CHOICE:
3173 ret = parse_case(ctx, data, &cas->child);
3174 break;
3175 case YANG_CONTAINER:
3176 ret = parse_container(ctx, data, &cas->child);
3177 break;
3178 case YANG_LEAF:
3179 ret = parse_leaf(ctx, data, &cas->child);
3180 break;
3181 case YANG_LEAF_LIST:
3182 ret = parse_leaflist(ctx, data, &cas->child);
3183 break;
3184 case YANG_LIST:
3185 ret = parse_list(ctx, data, &cas->child);
3186 break;
3187 case YANG_USES:
3188 ret = parse_uses(ctx, data, &cas->child);
3189 break;
3190 case YANG_CUSTOM:
3191 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts);
3192 break;
3193 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003194 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003195 return LY_EVALID;
3196 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003197 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003198 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003199 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003200
3201 return ret;
3202}
3203
3204static LY_ERR
3205parse_choice(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
3206{
3207 LY_ERR ret = 0;
3208 char *buf, *word;
3209 int word_len;
3210 enum yang_keyword kw;
3211 struct lysp_node *iter;
3212 struct lysp_node_choice *choic;
3213
3214 /* create structure */
3215 choic = calloc(1, sizeof *choic);
3216 LY_CHECK_ERR_RET(!choic, LOGMEM(ctx), LY_EMEM);
3217 choic->nodetype = LYS_CHOICE;
3218
3219 /* insert into siblings */
3220 if (!*siblings) {
3221 *siblings = (struct lysp_node *)choic;
3222 } else {
3223 for (iter = *siblings; iter->next; iter = iter->next);
3224 iter->next = (struct lysp_node *)choic;
3225 }
3226
3227 /* get name */
3228 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003229 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003230
3231 if (buf) {
3232 choic->name = lydict_insert_zc(ctx, word);
3233 } else {
3234 choic->name = lydict_insert(ctx, word, word_len);
3235 }
3236
3237 /* parse substatements */
3238 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003239 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003240
3241 switch (kw) {
3242 case YANG_CONFIG:
3243 ret = parse_config(ctx, data, &choic->flags, &choic->exts);
3244 break;
3245 case YANG_DESCRIPTION:
3246 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choic->dsc, Y_STR_ARG, &choic->exts);
3247 break;
3248 case YANG_IF_FEATURE:
3249 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choic->iffeatures, Y_STR_ARG, &choic->exts);
3250 break;
3251 case YANG_MANDATORY:
3252 ret = parse_mandatory(ctx, data, &choic->flags, &choic->exts);
3253 break;
3254 case YANG_REFERENCE:
3255 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choic->ref, Y_STR_ARG, &choic->exts);
3256 break;
3257 case YANG_STATUS:
3258 ret = parse_status(ctx, data, &choic->flags, &choic->exts);
3259 break;
3260 case YANG_WHEN:
3261 ret = parse_when(ctx, data, &choic->when);
3262 break;
3263 case YANG_DEFAULT:
3264 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choic->dflt, Y_IDENTIF_ARG, &choic->exts);
3265 break;
3266
3267 case YANG_ANYDATA:
3268 case YANG_ANYXML:
3269 ret = parse_any(ctx, data, kw, &choic->child);
3270 break;
3271 case YANG_CASE:
3272 ret = parse_case(ctx, data, &choic->child);
3273 break;
3274 case YANG_CHOICE:
3275 ret = parse_choice(ctx, data, &choic->child);
3276 break;
3277 case YANG_CONTAINER:
3278 ret = parse_container(ctx, data, &choic->child);
3279 break;
3280 case YANG_LEAF:
3281 ret = parse_leaf(ctx, data, &choic->child);
3282 break;
3283 case YANG_LEAF_LIST:
3284 ret = parse_leaflist(ctx, data, &choic->child);
3285 break;
3286 case YANG_LIST:
3287 ret = parse_list(ctx, data, &choic->child);
3288 break;
3289 case YANG_CUSTOM:
3290 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choic->exts);
3291 break;
3292 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003293 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003294 return LY_EVALID;
3295 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003296 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003298 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003299
3300 return ret;
3301}
3302
3303static LY_ERR
3304parse_container(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
3305{
3306 LY_ERR ret = 0;
3307 char *buf, *word;
3308 int word_len;
3309 enum yang_keyword kw;
3310 struct lysp_node *iter;
3311 struct lysp_node_container *cont;
3312
3313 /* create structure */
3314 cont = calloc(1, sizeof *cont);
3315 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx), LY_EMEM);
3316 cont->nodetype = LYS_CONTAINER;
3317
3318 /* insert into siblings */
3319 if (!*siblings) {
3320 *siblings = (struct lysp_node *)cont;
3321 } else {
3322 for (iter = *siblings; iter->next; iter = iter->next);
3323 iter->next = (struct lysp_node *)cont;
3324 }
3325
3326 /* get name */
3327 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003328 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003329
3330 if (buf) {
3331 cont->name = lydict_insert_zc(ctx, word);
3332 } else {
3333 cont->name = lydict_insert(ctx, word, word_len);
3334 }
3335
3336 /* parse substatements */
3337 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003338 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003339
3340 switch (kw) {
3341 case YANG_CONFIG:
3342 ret = parse_config(ctx, data, &cont->flags, &cont->exts);
3343 break;
3344 case YANG_DESCRIPTION:
3345 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts);
3346 break;
3347 case YANG_IF_FEATURE:
3348 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts);
3349 break;
3350 case YANG_REFERENCE:
3351 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts);
3352 break;
3353 case YANG_STATUS:
3354 ret = parse_status(ctx, data, &cont->flags, &cont->exts);
3355 break;
3356 case YANG_WHEN:
3357 ret = parse_when(ctx, data, &cont->when);
3358 break;
3359 case YANG_PRESENCE:
3360 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts);
3361 break;
3362
3363 case YANG_ANYDATA:
3364 case YANG_ANYXML:
3365 ret = parse_any(ctx, data, kw, &cont->child);
3366 break;
3367 case YANG_CHOICE:
3368 ret = parse_choice(ctx, data, &cont->child);
3369 break;
3370 case YANG_CONTAINER:
3371 ret = parse_container(ctx, data, &cont->child);
3372 break;
3373 case YANG_LEAF:
3374 ret = parse_leaf(ctx, data, &cont->child);
3375 break;
3376 case YANG_LEAF_LIST:
3377 ret = parse_leaflist(ctx, data, &cont->child);
3378 break;
3379 case YANG_LIST:
3380 ret = parse_list(ctx, data, &cont->child);
3381 break;
3382 case YANG_USES:
3383 ret = parse_uses(ctx, data, &cont->child);
3384 break;
3385
3386 case YANG_TYPEDEF:
3387 ret = parse_typedef(ctx, data, &cont->typedefs);
3388 break;
3389 case YANG_MUST:
3390 ret = parse_restrs(ctx, data, kw, &cont->musts);
3391 break;
3392 case YANG_ACTION:
3393 ret = parse_action(ctx, data, &cont->actions);
3394 break;
3395 case YANG_GROUPING:
3396 ret = parse_grouping(ctx, data, &cont->groupings);
3397 break;
3398 case YANG_NOTIFICATION:
3399 ret = parse_notif(ctx, data, &cont->notifs);
3400 break;
3401 case YANG_CUSTOM:
3402 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts);
3403 break;
3404 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003405 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003406 return LY_EVALID;
3407 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003408 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003409 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003410 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003411
3412 return ret;
3413}
3414
3415static LY_ERR
3416parse_list(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
3417{
3418 LY_ERR ret = 0;
3419 char *buf, *word;
3420 int word_len;
3421 enum yang_keyword kw;
3422 struct lysp_node *iter;
3423 struct lysp_node_list *list;
3424
3425 /* create structure */
3426 list = calloc(1, sizeof *list);
3427 LY_CHECK_ERR_RET(!list, LOGMEM(ctx), LY_EMEM);
3428 list->nodetype = LYS_LIST;
3429
3430 /* insert into siblings */
3431 if (!*siblings) {
3432 *siblings = (struct lysp_node *)list;
3433 } else {
3434 for (iter = *siblings; iter->next; iter = iter->next);
3435 iter->next = (struct lysp_node *)list;
3436 }
3437
3438 /* get name */
3439 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003440 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003441
3442 if (buf) {
3443 list->name = lydict_insert_zc(ctx, word);
3444 } else {
3445 list->name = lydict_insert(ctx, word, word_len);
3446 }
3447
3448 /* parse substatements */
3449 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003450 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003451
3452 switch (kw) {
3453 case YANG_CONFIG:
3454 ret = parse_config(ctx, data, &list->flags, &list->exts);
3455 break;
3456 case YANG_DESCRIPTION:
3457 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts);
3458 break;
3459 case YANG_IF_FEATURE:
3460 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts);
3461 break;
3462 case YANG_REFERENCE:
3463 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts);
3464 break;
3465 case YANG_STATUS:
3466 ret = parse_status(ctx, data, &list->flags, &list->exts);
3467 break;
3468 case YANG_WHEN:
3469 ret = parse_when(ctx, data, &list->when);
3470 break;
3471 case YANG_KEY:
3472 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts);
3473 break;
3474 case YANG_MAX_ELEMENTS:
3475 ret = parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts);
3476 break;
3477 case YANG_MIN_ELEMENTS:
3478 ret = parse_minelements(ctx, data, &list->min, &list->flags, &list->exts);
3479 break;
3480 case YANG_ORDERED_BY:
3481 ret = parse_orderedby(ctx, data, &list->flags, &list->exts);
3482 break;
3483 case YANG_UNIQUE:
3484 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts);
3485 break;
3486
3487 case YANG_ANYDATA:
3488 case YANG_ANYXML:
3489 ret = parse_any(ctx, data, kw, &list->child);
3490 break;
3491 case YANG_CHOICE:
3492 ret = parse_choice(ctx, data, &list->child);
3493 break;
3494 case YANG_CONTAINER:
3495 ret = parse_container(ctx, data, &list->child);
3496 break;
3497 case YANG_LEAF:
3498 ret = parse_leaf(ctx, data, &list->child);
3499 break;
3500 case YANG_LEAF_LIST:
3501 ret = parse_leaflist(ctx, data, &list->child);
3502 break;
3503 case YANG_LIST:
3504 ret = parse_list(ctx, data, &list->child);
3505 break;
3506 case YANG_USES:
3507 ret = parse_uses(ctx, data, &list->child);
3508 break;
3509
3510 case YANG_TYPEDEF:
3511 ret = parse_typedef(ctx, data, &list->typedefs);
3512 break;
3513 case YANG_MUST:
3514 ret = parse_restrs(ctx, data, kw, &list->musts);
3515 break;
3516 case YANG_ACTION:
3517 ret = parse_action(ctx, data, &list->actions);
3518 break;
3519 case YANG_GROUPING:
3520 ret = parse_grouping(ctx, data, &list->groupings);
3521 break;
3522 case YANG_NOTIFICATION:
3523 ret = parse_notif(ctx, data, &list->notifs);
3524 break;
3525 case YANG_CUSTOM:
3526 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts);
3527 break;
3528 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003529 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530 return LY_EVALID;
3531 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003532 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003533 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003534 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003535
3536 return ret;
3537}
3538
3539static LY_ERR
3540parse_yinelement(struct ly_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
3541{
3542 LY_ERR ret = 0;
3543 char *buf, *word;
3544 int word_len;
3545 enum yang_keyword kw;
3546
3547 if (*flags & LYS_YINELEM_MASK) {
3548 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "yin-element");
3549 return LY_EVALID;
3550 }
3551
3552 /* get value */
3553 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003554 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003555
3556 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3557 *flags |= LYS_YINELEM_TRUE;
3558 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3559 *flags |= LYS_YINELEM_FALSE;
3560 } else {
3561 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "yin-element");
3562 free(buf);
3563 return LY_EVALID;
3564 }
3565 free(buf);
3566
3567 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003568 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569
3570 switch (kw) {
3571 case YANG_CUSTOM:
3572 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02003573 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003574 break;
3575 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003576 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003577 return LY_EVALID;
3578 }
3579 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003580 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003581
3582 return ret;
3583}
3584
3585static LY_ERR
3586parse_argument(struct ly_ctx *ctx, const char **data, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
3587{
3588 LY_ERR ret = 0;
3589 char *buf, *word;
3590 int word_len;
3591 enum yang_keyword kw;
3592
3593 if (*argument) {
3594 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "argument");
3595 return LY_EVALID;
3596 }
3597
3598 /* get value */
3599 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003600 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003601
3602 if (buf) {
3603 *argument = lydict_insert_zc(ctx, word);
3604 } else {
3605 *argument = lydict_insert(ctx, word, word_len);
3606 }
3607
3608 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003609 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610
3611 switch (kw) {
3612 case YANG_YIN_ELEMENT:
3613 ret = parse_yinelement(ctx, data, flags, exts);
3614 break;
3615 case YANG_CUSTOM:
3616 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts);
3617 break;
3618 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003619 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003620 return LY_EVALID;
3621 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003622 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003623 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003624 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003625
3626 return ret;
3627}
3628
3629static LY_ERR
3630parse_extension(struct ly_ctx *ctx, const char **data, struct lysp_ext **extensions)
3631{
3632 LY_ERR ret = 0;
3633 char *buf, *word;
3634 int word_len;
3635 enum yang_keyword kw;
3636 struct lysp_ext *ex;
3637
3638 LYSP_ARRAY_NEW_RET(ctx, extensions, ex, LY_EMEM);
3639
3640 /* get value */
3641 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003642 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643
3644 if (buf) {
3645 ex->name = lydict_insert_zc(ctx, word);
3646 } else {
3647 ex->name = lydict_insert(ctx, word, word_len);
3648 }
3649
3650 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003651 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003652
3653 switch (kw) {
3654 case YANG_DESCRIPTION:
3655 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts);
3656 break;
3657 case YANG_REFERENCE:
3658 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts);
3659 break;
3660 case YANG_STATUS:
3661 ret = parse_status(ctx, data, &ex->flags, &ex->exts);
3662 break;
3663 case YANG_ARGUMENT:
3664 ret = parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts);
3665 break;
3666 case YANG_CUSTOM:
3667 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts);
3668 break;
3669 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003670 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003671 return LY_EVALID;
3672 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003673 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003674 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003675 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003676
3677 return ret;
3678}
3679
3680static LY_ERR
3681parse_deviate(struct ly_ctx *ctx, const char **data, struct lysp_deviate **deviates)
3682{
3683 LY_ERR ret = 0;
3684 char *buf, *word;
3685 int word_len, dev_mod;
3686 enum yang_keyword kw;
3687 struct lysp_deviate *iter, *d;
3688 struct lysp_deviate_add *d_add = NULL;
3689 struct lysp_deviate_rpl *d_rpl = NULL;
3690 struct lysp_deviate_del *d_del = NULL;
3691 const char **d_units, ***d_uniques, ***d_dflts;
3692 struct lysp_restr **d_musts;
3693 uint16_t *d_flags;
3694 uint32_t *d_min, *d_max;
3695
3696 /* get value */
3697 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003698 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003699
3700 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3701 dev_mod = LYS_DEV_NOT_SUPPORTED;
3702 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3703 dev_mod = LYS_DEV_ADD;
3704 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3705 dev_mod = LYS_DEV_REPLACE;
3706 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3707 dev_mod = LYS_DEV_DELETE;
3708 } else {
3709 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "deviate");
3710 free(buf);
3711 return LY_EVALID;
3712 }
3713 free(buf);
3714
3715 /* create structure */
3716 switch (dev_mod) {
3717 case LYS_DEV_NOT_SUPPORTED:
3718 d = calloc(1, sizeof *d);
3719 LY_CHECK_ERR_RET(!d, LOGMEM(ctx), LY_EMEM);
3720 break;
3721 case LYS_DEV_ADD:
3722 d_add = calloc(1, sizeof *d_add);
3723 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx), LY_EMEM);
3724 d = (struct lysp_deviate *)d_add;
3725 d_units = &d_add->units;
3726 d_uniques = &d_add->uniques;
3727 d_dflts = &d_add->dflts;
3728 d_musts = &d_add->musts;
3729 d_flags = &d_add->flags;
3730 d_min = &d_add->min;
3731 d_max = &d_add->max;
3732 break;
3733 case LYS_DEV_REPLACE:
3734 d_rpl = calloc(1, sizeof *d_rpl);
3735 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx), LY_EMEM);
3736 d = (struct lysp_deviate *)d_rpl;
3737 d_units = &d_rpl->units;
3738 d_flags = &d_rpl->flags;
3739 d_min = &d_rpl->min;
3740 d_max = &d_rpl->max;
3741 break;
3742 case LYS_DEV_DELETE:
3743 d_del = calloc(1, sizeof *d_del);
3744 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx), LY_EMEM);
3745 d = (struct lysp_deviate *)d_del;
3746 d_units = &d_del->units;
3747 d_uniques = &d_del->uniques;
3748 d_dflts = &d_del->dflts;
3749 d_musts = &d_del->musts;
3750 d_flags = &d_del->flags;
3751 d_min = &d_del->min;
3752 d_max = &d_del->max;
3753 break;
3754 default:
3755 assert(0);
3756 LOGINT_RET(ctx);
3757 }
3758 d->mod = dev_mod;
3759
3760 /* insert into siblings */
3761 if (!*deviates) {
3762 *deviates = d;
3763 } else {
3764 for (iter = *deviates; iter->next; iter = iter->next);
3765 iter->next = d;
3766 }
3767
3768 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003769 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003770
3771 switch (kw) {
3772 case YANG_CONFIG:
3773 switch (dev_mod) {
3774 case LYS_DEV_NOT_SUPPORTED:
Radek Krejcic59bc972018-09-17 16:13:06 +02003775 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003776 return LY_EVALID;
3777 default:
3778 ret = parse_config(ctx, data, d_flags, &d->exts);
3779 break;
3780 }
3781 break;
3782 case YANG_DEFAULT:
3783 switch (dev_mod) {
3784 case LYS_DEV_NOT_SUPPORTED:
Radek Krejcic59bc972018-09-17 16:13:06 +02003785 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003786 return LY_EVALID;
3787 case LYS_DEV_REPLACE:
3788 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts);
3789 break;
3790 default:
3791 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts);
3792 break;
3793 }
3794 break;
3795 case YANG_MANDATORY:
3796 switch (dev_mod) {
3797 case LYS_DEV_NOT_SUPPORTED:
Radek Krejcic59bc972018-09-17 16:13:06 +02003798 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003799 return LY_EVALID;
3800 default:
3801 ret = parse_mandatory(ctx, data, d_flags, &d->exts);
3802 break;
3803 }
3804 break;
3805 case YANG_MAX_ELEMENTS:
3806 switch (dev_mod) {
3807 case LYS_DEV_NOT_SUPPORTED:
Radek Krejcic59bc972018-09-17 16:13:06 +02003808 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003809 return LY_EVALID;
3810 default:
3811 ret = parse_maxelements(ctx, data, d_max, d_flags, &d->exts);
3812 break;
3813 }
3814 break;
3815 case YANG_MIN_ELEMENTS:
3816 switch (dev_mod) {
3817 case LYS_DEV_NOT_SUPPORTED:
Radek Krejcic59bc972018-09-17 16:13:06 +02003818 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003819 return LY_EVALID;
3820 default:
3821 ret = parse_minelements(ctx, data, d_min, d_flags, &d->exts);
3822 break;
3823 }
3824 break;
3825 case YANG_MUST:
3826 switch (dev_mod) {
3827 case LYS_DEV_NOT_SUPPORTED:
Radek Krejcic59bc972018-09-17 16:13:06 +02003828 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003829 return LY_EVALID;
3830 default:
3831 ret = parse_restrs(ctx, data, kw, d_musts);
3832 break;
3833 }
3834 break;
3835 case YANG_TYPE:
3836 switch (dev_mod) {
3837 case LYS_DEV_NOT_SUPPORTED:
3838 case LYS_DEV_ADD:
3839 case LYS_DEV_DELETE:
Radek Krejcic59bc972018-09-17 16:13:06 +02003840 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003841 return LY_EVALID;
3842 default:
3843 d_rpl->type = calloc(1, sizeof *d_rpl->type);
3844 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx), LY_EMEM);
3845 ret = parse_type(ctx, data, d_rpl->type);
3846 break;
3847 }
3848 break;
3849 case YANG_UNIQUE:
3850 switch (dev_mod) {
3851 case LYS_DEV_NOT_SUPPORTED:
3852 case LYS_DEV_REPLACE:
Radek Krejcic59bc972018-09-17 16:13:06 +02003853 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003854 return LY_EVALID;
3855 default:
3856 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts);
3857 break;
3858 }
3859 break;
3860 case YANG_UNITS:
3861 switch (dev_mod) {
3862 case LYS_DEV_NOT_SUPPORTED:
Radek Krejcic59bc972018-09-17 16:13:06 +02003863 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003864 return LY_EVALID;
3865 default:
3866 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts);
3867 break;
3868 }
3869 break;
3870 case YANG_CUSTOM:
3871 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts);
3872 break;
3873 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003874 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875 return LY_EVALID;
3876 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003877 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003878 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003879 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003880
3881 return ret;
3882}
3883
3884static LY_ERR
3885parse_deviation(struct ly_ctx *ctx, const char **data, struct lysp_deviation **deviations)
3886{
3887 LY_ERR ret = 0;
3888 char *buf, *word;
3889 int word_len;
3890 enum yang_keyword kw;
3891 struct lysp_deviation *dev;
3892
3893 LYSP_ARRAY_NEW_RET(ctx, deviations, dev, LY_EMEM);
3894
3895 /* get value */
3896 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003897 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003898
3899 if (buf) {
3900 dev->nodeid = lydict_insert_zc(ctx, word);
3901 } else {
3902 dev->nodeid = lydict_insert(ctx, word, word_len);
3903 }
3904
3905 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003906 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003907
3908 switch (kw) {
3909 case YANG_DESCRIPTION:
3910 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts);
3911 break;
3912 case YANG_DEVIATE:
3913 ret = parse_deviate(ctx, data, &dev->deviates);
3914 break;
3915 case YANG_REFERENCE:
3916 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts);
3917 break;
3918 case YANG_CUSTOM:
3919 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts);
3920 break;
3921 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003922 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003923 return LY_EVALID;
3924 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003925 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003926 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003927 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003928
3929 /* mandatory substatements */
3930 if (!dev->deviates) {
3931 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "deviate", "deviation");
3932 return LY_EVALID;
3933 }
3934
3935 return ret;
3936}
3937
3938static LY_ERR
3939parse_feature(struct ly_ctx *ctx, const char **data, struct lysp_feature **features)
3940{
3941 LY_ERR ret = 0;
3942 char *buf, *word;
3943 int word_len;
3944 enum yang_keyword kw;
3945 struct lysp_feature *feat;
3946
3947 LYSP_ARRAY_NEW_RET(ctx, features, feat, LY_EMEM);
3948
3949 /* get value */
3950 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003951 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003952
3953 if (buf) {
3954 feat->name = lydict_insert_zc(ctx, word);
3955 } else {
3956 feat->name = lydict_insert(ctx, word, word_len);
3957 }
3958
3959 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003960 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003961
3962 switch (kw) {
3963 case YANG_DESCRIPTION:
3964 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts);
3965 break;
3966 case YANG_IF_FEATURE:
3967 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts);
3968 break;
3969 case YANG_REFERENCE:
3970 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts);
3971 break;
3972 case YANG_STATUS:
3973 ret = parse_status(ctx, data, &feat->flags, &feat->exts);
3974 break;
3975 case YANG_CUSTOM:
3976 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts);
3977 break;
3978 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02003979 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003980 return LY_EMEM;
3981 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003982 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003983 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003984 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003985
3986 return ret;
3987}
3988
3989static LY_ERR
3990parse_identity(struct ly_ctx *ctx, const char **data, struct lysp_ident **identities)
3991{
3992 LY_ERR ret = 0;
3993 char *buf, *word;
3994 int word_len;
3995 enum yang_keyword kw;
3996 struct lysp_ident *ident;
3997
3998 LYSP_ARRAY_NEW_RET(ctx, identities, ident, LY_EMEM);
3999
4000 /* get value */
4001 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004002 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004003
4004 if (buf) {
4005 ident->name = lydict_insert_zc(ctx, word);
4006 } else {
4007 ident->name = lydict_insert(ctx, word, word_len);
4008 }
4009
4010 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004011 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004012
4013 switch (kw) {
4014 case YANG_DESCRIPTION:
4015 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts);
4016 break;
4017 case YANG_IF_FEATURE:
4018 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts);
4019 break;
4020 case YANG_REFERENCE:
4021 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts);
4022 break;
4023 case YANG_STATUS:
4024 ret = parse_status(ctx, data, &ident->flags, &ident->exts);
4025 break;
4026 case YANG_BASE:
4027 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts);
4028 break;
4029 case YANG_CUSTOM:
4030 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts);
4031 break;
4032 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02004033 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004034 return LY_EVALID;
4035 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004036 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004037 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004038 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004039
4040 return ret;
4041}
4042
4043static LY_ERR
4044parse_sub_module(struct ly_ctx *ctx, const char **data, struct lysp_module *mod)
4045{
4046 LY_ERR ret = 0;
4047 char *buf, *word;
4048 int word_len;
4049 enum yang_keyword kw, prev_kw = 0;
4050 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4051
4052 /* (sub)module name */
4053 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004054 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004055
4056 if (buf) {
4057 mod->name = lydict_insert_zc(ctx, word);
4058 } else {
4059 mod->name = lydict_insert(ctx, word, word_len);
4060 }
4061
4062 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004063 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004064
4065 switch (kw) {
4066 /* module header */
4067 case YANG_NAMESPACE:
4068 case YANG_PREFIX:
4069 if (mod->submodule) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004070 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004071 return LY_EVALID;
4072 }
4073 /* fallthrough */
4074 case YANG_BELONGS_TO:
4075 if ((kw == YANG_BELONGS_TO) && !mod->submodule) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004076 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004077 return LY_EVALID;
4078 }
4079 /* fallthrough */
4080 case YANG_YANG_VERSION:
4081 if (mod_stmt > Y_MOD_MODULE_HEADER) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004082 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004083 return LY_EVALID;
4084 }
4085 break;
4086 /* linkage */
4087 case YANG_INCLUDE:
4088 case YANG_IMPORT:
4089 if (mod_stmt > Y_MOD_LINKAGE) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004090 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004091 return LY_EVALID;
4092 }
4093 mod_stmt = Y_MOD_LINKAGE;
4094 break;
4095 /* meta */
4096 case YANG_ORGANIZATION:
4097 case YANG_CONTACT:
4098 case YANG_DESCRIPTION:
4099 case YANG_REFERENCE:
4100 if (mod_stmt > Y_MOD_META) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004101 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004102 return LY_EVALID;
4103 }
4104 mod_stmt = Y_MOD_META;
4105 break;
4106
4107 /* revision */
4108 case YANG_REVISION:
4109 if (mod_stmt > Y_MOD_REVISION) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004110 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004111 return LY_EVALID;
4112 }
4113 mod_stmt = Y_MOD_REVISION;
4114 break;
4115
4116 /* body */
4117 case YANG_ANYDATA:
4118 case YANG_ANYXML:
4119 case YANG_AUGMENT:
4120 case YANG_CHOICE:
4121 case YANG_CONTAINER:
4122 case YANG_DEVIATION:
4123 case YANG_EXTENSION:
4124 case YANG_FEATURE:
4125 case YANG_GROUPING:
4126 case YANG_IDENTITY:
4127 case YANG_LEAF:
4128 case YANG_LEAF_LIST:
4129 case YANG_LIST:
4130 case YANG_NOTIFICATION:
4131 case YANG_RPC:
4132 case YANG_TYPEDEF:
4133 case YANG_USES:
4134 case YANG_CUSTOM:
4135 mod_stmt = Y_MOD_BODY;
4136 break;
4137 default:
4138 /* error handled in the next switch */
4139 break;
4140 }
4141 prev_kw = kw;
4142
4143 switch (kw) {
4144 /* module header */
4145 case YANG_YANG_VERSION:
4146 ret = parse_yangversion(ctx, data, mod);
4147 break;
4148 case YANG_NAMESPACE:
4149 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts);
4150 break;
4151 case YANG_PREFIX:
4152 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts);
4153 break;
4154 case YANG_BELONGS_TO:
4155 ret = parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts);
4156 break;
4157
4158 /* linkage */
4159 case YANG_INCLUDE:
4160 ret = parse_include(ctx, data, &mod->includes);
4161 break;
4162 case YANG_IMPORT:
4163 ret = parse_import(ctx, data, &mod->imports);
4164 break;
4165
4166 /* meta */
4167 case YANG_ORGANIZATION:
4168 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts);
4169 break;
4170 case YANG_CONTACT:
4171 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts);
4172 break;
4173 case YANG_DESCRIPTION:
4174 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts);
4175 break;
4176 case YANG_REFERENCE:
4177 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts);
4178 break;
4179
4180 /* revision */
4181 case YANG_REVISION:
4182 ret = parse_revision(ctx, data, &mod->revs);
4183 break;
4184
4185 /* body */
4186 case YANG_ANYDATA:
4187 case YANG_ANYXML:
4188 ret = parse_any(ctx, data, kw, &mod->data);
4189 break;
4190 case YANG_CHOICE:
4191 ret = parse_choice(ctx, data, &mod->data);
4192 break;
4193 case YANG_CONTAINER:
4194 ret = parse_container(ctx, data, &mod->data);
4195 break;
4196 case YANG_LEAF:
4197 ret = parse_leaf(ctx, data, &mod->data);
4198 break;
4199 case YANG_LEAF_LIST:
4200 ret = parse_leaflist(ctx, data, &mod->data);
4201 break;
4202 case YANG_LIST:
4203 ret = parse_list(ctx, data, &mod->data);
4204 break;
4205 case YANG_USES:
4206 ret = parse_uses(ctx, data, &mod->data);
4207 break;
4208
4209 case YANG_AUGMENT:
4210 ret = parse_augment(ctx, data, &mod->augments);
4211 break;
4212 case YANG_DEVIATION:
4213 ret = parse_deviation(ctx, data, &mod->deviations);
4214 break;
4215 case YANG_EXTENSION:
4216 ret = parse_extension(ctx, data, &mod->extensions);
4217 break;
4218 case YANG_FEATURE:
4219 ret = parse_feature(ctx, data, &mod->features);
4220 break;
4221 case YANG_GROUPING:
4222 ret = parse_grouping(ctx, data, &mod->groupings);
4223 break;
4224 case YANG_IDENTITY:
4225 ret = parse_identity(ctx, data, &mod->identities);
4226 break;
4227 case YANG_NOTIFICATION:
4228 ret = parse_notif(ctx, data, &mod->notifs);
4229 break;
4230 case YANG_RPC:
4231 ret = parse_action(ctx, data, &mod->rpcs);
4232 break;
4233 case YANG_TYPEDEF:
4234 ret = parse_typedef(ctx, data, &mod->typedefs);
4235 break;
4236 case YANG_CUSTOM:
4237 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts);
4238 break;
4239
4240 default:
Radek Krejcic59bc972018-09-17 16:13:06 +02004241 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004242 return LY_EVALID;
4243 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004244 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004245 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004246 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004247
4248 /* mandatory substatements */
4249 if (mod->submodule) {
4250 if (!mod->belongsto) {
4251 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "belongs-to", "submodule");
4252 return LY_EVALID;
4253 }
4254 } else {
4255 if (!mod->ns) {
4256 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "namespace", "module");
4257 return LY_EVALID;
4258 } else if (!mod->prefix) {
4259 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "prefix", "module");
4260 return LY_EVALID;
4261 }
4262 }
4263
4264 return ret;
4265}
4266
Radek Krejcid4557c62018-09-17 11:42:09 +02004267LY_ERR
Michal Vasko7fbc8162018-09-17 10:35:16 +02004268yang_parse(struct ly_ctx *ctx, const char *data, struct lysp_module **mod_p)
4269{
4270 LY_ERR ret = 0;
4271 char *word, *buf;
4272 int word_len;
4273 const char *data_start;
4274 enum yang_keyword kw;
4275 struct lysp_module *mod;
4276
4277 data_start = data;
4278
4279 /* "module"/"submodule" */
4280 ret = get_keyword(ctx, &data, &kw, &word, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004281 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004282
4283 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
4284 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".\n",
Radek Krejcic59bc972018-09-17 16:13:06 +02004285 ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004286 goto error;
4287 }
4288
4289 mod = calloc(1, sizeof *mod);
4290 LY_CHECK_ERR_GOTO(!mod, LOGMEM(ctx), error);
4291 if (kw == YANG_SUBMODULE) {
4292 mod->submodule = 1;
4293 }
4294
4295 /* substatements */
4296 ret = parse_sub_module(ctx, &data, mod);
Radek Krejcic59bc972018-09-17 16:13:06 +02004297 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004298
4299 /* read some trailing spaces or new lines */
4300 ret = get_string(ctx, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004301 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004302
4303 if (word) {
4304 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
4305 word_len, word);
4306 free(buf);
4307 goto error;
4308 }
4309 assert(!buf);
4310
4311 *mod_p = mod;
4312 return ret;
4313
4314error:
4315 LOGERR(ctx, LY_EINVAL, "Module parsing failed on line %d.", lysp_get_data_line(data_start, data - data_start));
4316 /* TODO free module */
4317 return ret;
4318}