blob: d8311598d5e22b7680ffa42615884a1322b03d2b [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
31#define YANG_ERR_GOTO(ERR, GO) if (ERR) goto GO;
32
33#define YANG_ERR_RET(ERR) if (ERR) return ERR;
34
35#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR) \
36 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
37 YANG_ERR_RET(ERR); \
38 \
39 if (KW == YANG_SEMICOLON) { \
40 return ERR; \
41 } \
42 if (KW != YANG_LEFT_BRACE) { \
43 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", kw2str(KW)); \
44 return LY_EVALID; \
45 } \
46 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
47 !ERR && (KW != YANG_RIGHT_BRACE); \
48 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
49
50enum yang_module_stmt {
51 Y_MOD_MODULE_HEADER,
52 Y_MOD_LINKAGE,
53 Y_MOD_META,
54 Y_MOD_REVISION,
55 Y_MOD_BODY
56};
57
58enum yang_arg {
59 Y_IDENTIF_ARG,
60 Y_PREF_IDENTIF_ARG,
61 Y_STR_ARG,
62 Y_MAYBE_STR_ARG
63};
64
65enum yang_keyword {
66 YANG_NONE = 0,
67 YANG_ACTION,
68 YANG_ANYDATA,
69 YANG_ANYXML,
70 YANG_ARGUMENT,
71 YANG_AUGMENT,
72 YANG_BASE,
73 YANG_BELONGS_TO,
74 YANG_BIT,
75 YANG_CASE,
76 YANG_CHOICE,
77 YANG_CONFIG,
78 YANG_CONTACT,
79 YANG_CONTAINER,
80 YANG_DEFAULT,
81 YANG_DESCRIPTION,
82 YANG_DEVIATE,
83 YANG_DEVIATION,
84 YANG_ENUM,
85 YANG_ERROR_APP_TAG,
86 YANG_ERROR_MESSAGE,
87 YANG_EXTENSION,
88 YANG_FEATURE,
89 YANG_FRACTION_DIGITS,
90 YANG_GROUPING,
91 YANG_IDENTITY,
92 YANG_IF_FEATURE,
93 YANG_IMPORT,
94 YANG_INCLUDE,
95 YANG_INPUT,
96 YANG_KEY,
97 YANG_LEAF,
98 YANG_LEAF_LIST,
99 YANG_LENGTH,
100 YANG_LIST,
101 YANG_MANDATORY,
102 YANG_MAX_ELEMENTS,
103 YANG_MIN_ELEMENTS,
104 YANG_MODIFIER,
105 YANG_MODULE,
106 YANG_MUST,
107 YANG_NAMESPACE,
108 YANG_NOTIFICATION,
109 YANG_ORDERED_BY,
110 YANG_ORGANIZATION,
111 YANG_OUTPUT,
112 YANG_PATH,
113 YANG_PATTERN,
114 YANG_POSITION,
115 YANG_PREFIX,
116 YANG_PRESENCE,
117 YANG_RANGE,
118 YANG_REFERENCE,
119 YANG_REFINE,
120 YANG_REQUIRE_INSTANCE,
121 YANG_REVISION,
122 YANG_REVISION_DATE,
123 YANG_RPC,
124 YANG_STATUS,
125 YANG_SUBMODULE,
126 YANG_TYPE,
127 YANG_TYPEDEF,
128 YANG_UNIQUE,
129 YANG_UNITS,
130 YANG_USES,
131 YANG_VALUE,
132 YANG_WHEN,
133 YANG_YANG_VERSION,
134 YANG_YIN_ELEMENT,
135
136 YANG_SEMICOLON,
137 YANG_LEFT_BRACE,
138 YANG_RIGHT_BRACE,
139 YANG_CUSTOM
140};
141
142static LY_ERR parse_container(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings);
143static LY_ERR parse_uses(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings);
144static LY_ERR parse_choice(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings);
145static LY_ERR parse_case(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings);
146static LY_ERR parse_list(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings);
147static LY_ERR parse_grouping(struct ly_ctx *ctx, const char **data, struct lysp_grp **groupings);
148
149static const char *
150kw2str(enum yang_keyword kw)
151{
152 switch (kw) {
153 case YANG_ACTION:
154 return "action";
155 case YANG_ANYDATA:
156 return "anydata";
157 case YANG_ANYXML:
158 return "anyxml";
159 case YANG_ARGUMENT:
160 return "argument";
161 case YANG_AUGMENT:
162 return "augment";
163 case YANG_BASE:
164 return "base";
165 case YANG_BELONGS_TO:
166 return "belongs-to";
167 case YANG_BIT:
168 return "bit";
169 case YANG_CASE:
170 return "case";
171 case YANG_CHOICE:
172 return "choice";
173 case YANG_CONFIG:
174 return "config";
175 case YANG_CONTACT:
176 return "contact";
177 case YANG_CONTAINER:
178 return "container";
179 case YANG_CUSTOM:
180 return "<extension-instance>";
181 case YANG_DEFAULT:
182 return "default";
183 case YANG_DESCRIPTION:
184 return "description";
185 case YANG_DEVIATE:
186 return "deviate";
187 case YANG_DEVIATION:
188 return "deviation";
189 case YANG_ENUM:
190 return "enum";
191 case YANG_ERROR_APP_TAG:
192 return "error-app-tag";
193 case YANG_ERROR_MESSAGE:
194 return "error-message";
195 case YANG_EXTENSION:
196 return "extension";
197 case YANG_FEATURE:
198 return "feature";
199 case YANG_FRACTION_DIGITS:
200 return "fraction-digits";
201 case YANG_GROUPING:
202 return "grouping";
203 case YANG_IDENTITY:
204 return "identitiy";
205 case YANG_IF_FEATURE:
206 return "if-feature";
207 case YANG_IMPORT:
208 return "import";
209 case YANG_INCLUDE:
210 return "include";
211 case YANG_INPUT:
212 return "input";
213 case YANG_KEY:
214 return "key";
215 case YANG_LEAF:
216 return "leaf";
217 case YANG_LEAF_LIST:
218 return "leaf-list";
219 case YANG_LENGTH:
220 return "length";
221 case YANG_LIST:
222 return "list";
223 case YANG_MANDATORY:
224 return "mandatory";
225 case YANG_MAX_ELEMENTS:
226 return "max-elements";
227 case YANG_MIN_ELEMENTS:
228 return "min-elements";
229 case YANG_MODIFIER:
230 return "modifier";
231 case YANG_MODULE:
232 return "module";
233 case YANG_MUST:
234 return "must";
235 case YANG_NAMESPACE:
236 return "namespace";
237 case YANG_NOTIFICATION:
238 return "notification";
239 case YANG_ORDERED_BY:
240 return "ordered-by";
241 case YANG_ORGANIZATION:
242 return "organization";
243 case YANG_OUTPUT:
244 return "output";
245 case YANG_PATH:
246 return "path";
247 case YANG_PATTERN:
248 return "pattern";
249 case YANG_POSITION:
250 return "position";
251 case YANG_PREFIX:
252 return "prefix";
253 case YANG_PRESENCE:
254 return "presence";
255 case YANG_RANGE:
256 return "range";
257 case YANG_REFERENCE:
258 return "reference";
259 case YANG_REFINE:
260 return "refine";
261 case YANG_REQUIRE_INSTANCE:
262 return "require-instance";
263 case YANG_REVISION:
264 return "revision";
265 case YANG_REVISION_DATE:
266 return "revision-date";
267 case YANG_RPC:
268 return "rpc";
269 case YANG_STATUS:
270 return "status";
271 case YANG_SUBMODULE:
272 return "submodule";
273 case YANG_TYPE:
274 return "type";
275 case YANG_TYPEDEF:
276 return "typedef";
277 case YANG_UNIQUE:
278 return "unique";
279 case YANG_UNITS:
280 return "units";
281 case YANG_USES:
282 return "uses";
283 case YANG_VALUE:
284 return "value";
285 case YANG_WHEN:
286 return "when";
287 case YANG_YANG_VERSION:
288 return "yang-version";
289 case YANG_YIN_ELEMENT:
290 return "yin-element";
291 case YANG_SEMICOLON:
292 return ";";
293 case YANG_LEFT_BRACE:
294 return "{";
295 case YANG_RIGHT_BRACE:
296 return "}";
297 default:
298 return "";
299 }
300}
301
302static const char *
303substmt2str(LYEXT_SUBSTMT substmt)
304{
305 switch (substmt) {
306 case LYEXT_SUBSTMT_ARGUMENT:
307 return "argument";
308 case LYEXT_SUBSTMT_BASE:
309 return "base";
310 case LYEXT_SUBSTMT_BELONGSTO:
311 return "belongs-to";
312 case LYEXT_SUBSTMT_CONTACT:
313 return "contact";
314 case LYEXT_SUBSTMT_DEFAULT:
315 return "default";
316 case LYEXT_SUBSTMT_DESCRIPTION:
317 return "description";
318 case LYEXT_SUBSTMT_ERRTAG:
319 return "error-app-tag";
320 case LYEXT_SUBSTMT_ERRMSG:
321 return "error-message";
322 case LYEXT_SUBSTMT_KEY:
323 return "key";
324 case LYEXT_SUBSTMT_NAMESPACE:
325 return "namespace";
326 case LYEXT_SUBSTMT_ORGANIZATION:
327 return "organization";
328 case LYEXT_SUBSTMT_PATH:
329 return "path";
330 case LYEXT_SUBSTMT_PREFIX:
331 return "prefix";
332 case LYEXT_SUBSTMT_PRESENCE:
333 return "presence";
334 case LYEXT_SUBSTMT_REFERENCE:
335 return "reference";
336 case LYEXT_SUBSTMT_REVISIONDATE:
337 return "revision-date";
338 case LYEXT_SUBSTMT_UNITS:
339 return "units";
340 case LYEXT_SUBSTMT_VALUE:
341 return "value";
342 case LYEXT_SUBSTMT_VERSION:
343 return "yang-version";
344 case LYEXT_SUBSTMT_MODIFIER:
345 return "modifier";
346 case LYEXT_SUBSTMT_REQINSTANCE:
347 return "require-instance";
348 case LYEXT_SUBSTMT_YINELEM:
349 return "yin-element";
350 case LYEXT_SUBSTMT_CONFIG:
351 return "config";
352 case LYEXT_SUBSTMT_MANDATORY:
353 return "mandatory";
354 case LYEXT_SUBSTMT_ORDEREDBY:
355 return "ordered-by";
356 case LYEXT_SUBSTMT_STATUS:
357 return "status";
358 case LYEXT_SUBSTMT_FRACDIGITS:
359 return "fraction-digits";
360 case LYEXT_SUBSTMT_MAX:
361 return "max-elements";
362 case LYEXT_SUBSTMT_MIN:
363 return "min-elements";
364 case LYEXT_SUBSTMT_POSITION:
365 return "position";
366 case LYEXT_SUBSTMT_UNIQUE:
367 return "unique";
368 case LYEXT_SUBSTMT_IFFEATURE:
369 return "if-feature";
370 default:
371 return "";
372 }
373}
374
375static const char *
376nodetype2str(uint16_t nodetype)
377{
378 switch (nodetype) {
379 case LYS_CONTAINER:
380 return "container";
381 case LYS_CHOICE:
382 return "choice";
383 case LYS_LEAF:
384 return "leaf";
385 case LYS_LEAFLIST:
386 return "leaf-list";
387 case LYS_LIST:
388 return "list";
389 case LYS_ANYXML:
390 return "anyxml";
391 case LYS_CASE:
392 return "case";
393 case LYS_USES:
394 return "uses";
395 case LYS_ANYDATA:
396 return "anydata";
397 default:
398 return "";
399 }
400}
401
402static const char *
403devmod2str(uint8_t devmod)
404{
405 switch (devmod) {
406 case LYS_DEV_NOT_SUPPORTED:
407 return "not-supported";
408 case LYS_DEV_ADD:
409 return "add";
410 case LYS_DEV_DELETE:
411 return "delete";
412 case LYS_DEV_REPLACE:
413 return "replace";
414 default:
415 return "";
416 }
417}
418
419static LY_ERR
420buf_add_char(struct ly_ctx *ctx, char c, char **buf, int *buf_len, int buf_used)
421{
422 if (*buf_len == buf_used) {
423 *buf_len += 16;
424 *buf = ly_realloc(*buf, *buf_len);
425 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
426 }
427
428 (*buf)[buf_used] = c;
429 return LY_SUCCESS;
430}
431
432static LY_ERR
433buf_store_char(struct ly_ctx *ctx, const char *c, char **word_p, int *word_len, char **word_b, int *buf_len, int need_buf)
434{
435 if (word_b && *word_b) {
436 /* add another character into buffer */
437 if (buf_add_char(ctx, *c, word_b, buf_len, *word_len)) {
438 return LY_EMEM;
439 }
440
441 /* in case of realloc */
442 *word_p = *word_b;
443 } else if (need_buf) {
444 /* first time we need a buffer, copy everything read up to now */
445 if (*word_len) {
446 *word_b = malloc(*word_len);
447 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx), LY_EMEM);
448 *buf_len = *word_len;
449 memcpy(*word_b, *word_p, *word_len);
450 }
451
452 /* add this new character into buffer */
453 if (buf_add_char(ctx, *c, word_b, buf_len, *word_len)) {
454 return LY_EMEM;
455 }
456
457 /* in case of realloc */
458 *word_p = *word_b;
459 } else {
460 /* just remember the first character pointer */
461 if (!*word_p) {
462 *word_p = (char *)c;
463 }
464 }
465
466 ++(*word_len);
467 return LY_SUCCESS;
468}
469
470static LY_ERR
471check_char(struct ly_ctx *ctx, char c, enum yang_arg arg, int first, int *prefix)
472{
473 if ((arg == Y_STR_ARG) || (arg == Y_MAYBE_STR_ARG)) {
474 if ((c < ' ') && (c != '\t') && (c != '\n')) {
475 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHAR, c);
476 return LY_EVALID;
477 }
478 } else if ((arg == Y_IDENTIF_ARG) || (arg == Y_PREF_IDENTIF_ARG)) {
479 if (c < ' ') {
480 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHAR, c);
481 return LY_EVALID;
482 }
483
484 if (first || (*prefix == 2)) {
485 /* either first character of the whole identifier or of the name after prefix */
486 if (!isalpha(c) && (c != '_')) {
487 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
488 return LY_EVALID;
489 }
490 if (*prefix == 2) {
491 *prefix = 1;
492 }
493 } else {
494 /* other characters */
495 if (!isalnum(c) && (c != '_') && (c != '-') && (c != '.')) {
496 if ((arg == Y_PREF_IDENTIF_ARG) && !*prefix && (c == ':')) {
497 /* this is fine */
498 *prefix = 2;
499 } else {
500 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
501 return LY_EVALID;
502 }
503 }
504 }
505 }
506
507 return LY_SUCCESS;
508}
509
510static LY_ERR
511skip_comment(struct ly_ctx *ctx, const char **data, int comment)
512{
513 /* comment: 0 - comment ended, 1 - in line comment, 2 - in block comment, 3 - in block comment with last read character '*' */
514
515 while (**data && comment) {
516 switch (comment) {
517 case 1:
518 if (**data == '\n') {
519 comment = 0;
520 }
521 break;
522 case 2:
523 if (**data == '*') {
524 comment = 3;
525 }
526 break;
527 case 3:
528 if (**data == '/') {
529 comment = 0;
530 } else {
531 comment = 2;
532 }
533 break;
534 default:
535 LOGINT_RET(ctx);
536 }
537
538 ++(*data);
539 }
540
541 if (!**data && (comment > 1)) {
542 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
543 return LY_EVALID;
544 }
545
546 return LY_SUCCESS;
547}
548
549static LY_ERR
550read_qstring(struct ly_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, int *word_len,
551 int *buf_len, int indent)
552{
553 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
554 * 4 - string finished, now skipping whitespaces looking for +,
555 * 5 - string continues after +, skipping whitespaces */
556 int string, str_nl_indent = 0, need_buf = 0, prefix = 0;
557 const char *c;
558
559 if (**data == '\"') {
560 /* indent of the " itself */
561 ++indent;
562 string = 2;
563 } else {
564 assert(**data == '\'');
565 string = 1;
566 }
567 ++(*data);
568
569 while (**data && string) {
570 switch (string) {
571 case 1:
572 switch (**data) {
573 case '\'':
574 /* string may be finished, but check for + */
575 string = 4;
576 break;
577 default:
578 /* check and store character */
579 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
580 return LY_EVALID;
581 }
582 if (buf_store_char(ctx, *data, word_p, word_len, word_b, buf_len, need_buf)) {
583 return LY_EMEM;
584 }
585 break;
586 }
587 break;
588 case 2:
589 switch (**data) {
590 case '\"':
591 /* string may be finished, but check for + */
592 string = 4;
593 break;
594 case '\\':
595 /* special character following */
596 string = 3;
597 break;
598 case ' ':
599 if (str_nl_indent) {
600 --str_nl_indent;
601 } else {
602 /* check and store character */
603 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
604 return LY_EVALID;
605 }
606 if (buf_store_char(ctx, *data, word_p, word_len, word_b, buf_len, need_buf)) {
607 return LY_EMEM;
608 }
609 }
610 break;
611 case '\t':
612 if (str_nl_indent) {
613 if (str_nl_indent < 9) {
614 str_nl_indent = 0;
615 } else {
616 str_nl_indent -= 8;
617 }
618 } else {
619 /* check and store character */
620 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
621 return LY_EVALID;
622 }
623 if (buf_store_char(ctx, *data, word_p, word_len, word_b, buf_len, need_buf)) {
624 return LY_EMEM;
625 }
626 }
627 break;
628 case '\n':
629 str_nl_indent = indent;
630 if (indent) {
631 /* we will be removing the indents so we need our own buffer */
632 need_buf = 1;
633 }
634
635 /* check and store character */
636 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
637 return LY_EVALID;
638 }
639 if (buf_store_char(ctx, *data, word_p, word_len, word_b, buf_len, need_buf)) {
640 return LY_EMEM;
641 }
642 break;
643 default:
644 /* first non-whitespace character, clear current indent */
645 str_nl_indent = 0;
646
647 /* check and store character */
648 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
649 return LY_EVALID;
650 }
651 if (buf_store_char(ctx, *data, word_p, word_len, word_b, buf_len, need_buf)) {
652 return LY_EMEM;
653 }
654 break;
655 }
656 break;
657 case 3:
658 /* string encoded characters */
659 switch (**data) {
660 case 'n':
661 c = "\n";
662 break;
663 case 't':
664 c = "\t";
665 break;
666 case '\"':
667 c = *data;
668 break;
669 case '\\':
670 c = *data;
671 break;
672 default:
673 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX_YANG,
674 "Double-quoted string unknown special character '\\%c'.\n", **data);
675 return LY_EVALID;
676 }
677
678 /* check and store character */
679 if (check_char(ctx, *c, arg, !*word_len, &prefix)) {
680 return LY_EVALID;
681 }
682 if (buf_store_char(ctx, c, word_p, word_len, word_b, buf_len, need_buf)) {
683 return LY_EMEM;
684 }
685
686 string = 2;
687 break;
688 case 4:
689 switch (**data) {
690 case '+':
691 /* string continues */
692 string = 5;
693 break;
694 case ' ':
695 case '\t':
696 case '\n':
697 /* just skip */
698 break;
699 default:
700 /* string is finished */
701 goto string_end;
702 }
703 break;
704 case 5:
705 switch (**data) {
706 case ' ':
707 case '\t':
708 case '\n':
709 /* skip */
710 break;
711 case '\'':
712 string = 1;
713 break;
714 case '\"':
715 string = 2;
716 break;
717 default:
718 /* it must be quoted again */
719 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX_YANG,
720 "Both string parts divided by '+' must be quoted.\n");
721 return LY_EVALID;
722 }
723 break;
724 default:
725 return LY_EINT;
726 }
727
728 ++(*data);
729 }
730
731string_end:
732 return LY_SUCCESS;
733}
734
735/* read another word - character sequence without whitespaces (logs directly)
736 * - there can be whitespaces if they are a part of string
737 * - strings are always returned separately even if not separated by whitespaces
738 * - strings are returned without ' or "
739 * - strings divided by + are returned concatenated
740 * - comments are skipped
741 */
742static LY_ERR
743get_string(struct ly_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, int *word_len)
744{
745 int buf_len = 0, slash = 0, indent = 0, prefix = 0;
746 LY_ERR ret;
747
748 /* word buffer - dynamically allocated */
749 *word_b = NULL;
750
751 /* word pointer - just a pointer to data */
752 *word_p = NULL;
753
754 *word_len = 0;
755 while (**data) {
756 if (slash) {
757 if (**data == '/') {
758 /* one-line comment */
759 ret = skip_comment(ctx, data, 1);
760 if (ret) {
761 return ret;
762 }
763 } else if (**data == '*') {
764 /* block comment */
765 ret = skip_comment(ctx, data, 2);
766 if (ret) {
767 return ret;
768 }
769 } else {
770 /* not a comment after all */
771 ret = buf_store_char(ctx, (*data) - 1, word_p, word_len, word_b, &buf_len, 0);
772 if (ret) {
773 return ret;
774 }
775 }
776 slash = 0;
777 }
778
779 switch (**data) {
780 case '\'':
781 case '\"':
782 if (*word_len) {
783 /* we want strings always in a separate word, leave it */
784 goto str_end;
785 }
786 ret = read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len, indent);
787 if (ret) {
788 return ret;
789 }
790 goto str_end;
791 case '/':
792 slash = 1;
793 break;
794 case ' ':
795 if (*word_len) {
796 /* word is finished */
797 goto str_end;
798 }
799 /* increase indent */
800 ++indent;
801 break;
802 case '\t':
803 if (*word_len) {
804 /* word is finished */
805 goto str_end;
806 }
807 /* tabs count for 8 spaces */
808 indent += 8;
809 break;
810 case '\n':
811 if (*word_len) {
812 /* word is finished */
813 goto str_end;
814 }
815 /* reset indent */
816 indent = 0;
817 break;
818 case ';':
819 case '{':
820 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
821 /* word is finished */
822 goto str_end;
823 }
824
825 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INSTREXP, 1, *data, "an argument");
826 return LY_EVALID;
827 default:
828 if (check_char(ctx, **data, arg, !*word_len, &prefix)) {
829 return LY_EVALID;
830 }
831
832 if (buf_store_char(ctx, *data, word_p, word_len, word_b, &buf_len, 0)) {
833 return LY_EMEM;
834 }
835 break;
836 }
837
838 ++(*data);
839 }
840
841str_end:
842 /* ending '\0' for buf */
843 if (*word_b) {
844 if (buf_add_char(ctx, '\0', word_b, &buf_len, *word_len)) {
845 return LY_EMEM;
846 }
847 *word_p = *word_b;
848 }
849
850 return LY_SUCCESS;
851}
852
853static LY_ERR
854get_keyword(struct ly_ctx *ctx, const char **data, enum yang_keyword *kw, char **word_p, int *word_len)
855{
856 LY_ERR ret;
857 int prefix;
858 const char *word_start;
859 /* slash: 0 - nothing, 1 - last character was '/' */
860 int slash = 0;
861
862 if (word_p) {
863 *word_p = NULL;
864 *word_len = 0;
865 }
866
867 /* first skip "optsep", comments */
868 while (**data) {
869 if (slash) {
870 if (**data == '/') {
871 /* one-line comment */
872 ret = skip_comment(ctx, data, 1);
873 if (ret) {
874 return ret;
875 }
876 } else if (**data == '*') {
877 /* block comment */
878 ret = skip_comment(ctx, data, 2);
879 if (ret) {
880 return ret;
881 }
882 } else {
883 /* not a comment after all */
884 goto keyword_start;
885 }
886 slash = 0;
887 }
888
889 switch (**data) {
890 case '/':
891 slash = 1;
892 break;
893 case ' ':
894 case '\t':
895 case '\n':
896 /* skip whitespaces (optsep) */
897 break;
898 default:
899 /* either a keyword start or an invalid character */
900 goto keyword_start;
901 }
902
903 ++(*data);
904 }
905
906keyword_start:
907 word_start = *data;
908 *kw = YANG_NONE;
909
910 /* read the keyword itself */
911 switch (**data) {
912 case 'a':
913 ++(*data);
914 if (!strncmp(*data, "rgument", 7)) {
915 *data += 7;
916 *kw = YANG_ARGUMENT;
917 } else if (!strncmp(*data, "ugment", 6)) {
918 *data += 6;
919 *kw = YANG_AUGMENT;
920 } else if (!strncmp(*data, "ction", 5)) {
921 *data += 5;
922 *kw = YANG_ACTION;
923 } else if (!strncmp(*data, "ny", 2)) {
924 *data += 2;
925 if (!strncmp(*data, "data", 4)) {
926 *data += 4;
927 *kw = YANG_ANYDATA;
928 } else if (!strncmp(*data, "xml", 3)) {
929 *data += 3;
930 *kw = YANG_ANYXML;
931 }
932 }
933 break;
934 case 'b':
935 ++(*data);
936 if (!strncmp(*data, "ase", 3)) {
937 *data += 3;
938 *kw = YANG_BASE;
939 } else if (!strncmp(*data, "elongs-to", 9)) {
940 *data += 9;
941 *kw = YANG_BELONGS_TO;
942 } else if (!strncmp(*data, "it", 2)) {
943 *data += 2;
944 *kw = YANG_BIT;
945 }
946 break;
947 case 'c':
948 ++(*data);
949 if (!strncmp(*data, "ase", 3)) {
950 *data += 3;
951 *kw = YANG_CASE;
952 } else if (!strncmp(*data, "hoice", 5)) {
953 *data += 5;
954 *kw = YANG_CHOICE;
955 } else if (!strncmp(*data, "on", 2)) {
956 *data += 2;
957 if (!strncmp(*data, "fig", 3)) {
958 *data += 3;
959 *kw = YANG_CONFIG;
960 } else if (!strncmp(*data, "ta", 2)) {
961 *data += 2;
962 if (!strncmp(*data, "ct", 2)) {
963 *data += 2;
964 *kw = YANG_CONTACT;
965 } else if (!strncmp(*data, "iner", 4)) {
966 *data += 4;
967 *kw = YANG_CONTAINER;
968 }
969 }
970 }
971 break;
972 case 'd':
973 ++(*data);
974 if (**data == 'e') {
975 ++(*data);
976 if (!strncmp(*data, "fault", 5)) {
977 *data += 5;
978 *kw = YANG_DEFAULT;
979 } else if (!strncmp(*data, "scription", 9)) {
980 *data += 9;
981 *kw = YANG_DESCRIPTION;
982 } else if (!strncmp(*data, "viat", 4)) {
983 *data += 4;
984 if (**data == 'e') {
985 ++(*data);
986 *kw = YANG_DEVIATE;
987 } else if (!strncmp(*data, "ion", 3)) {
988 *data += 3;
989 *kw = YANG_DEVIATION;
990 }
991 }
992 }
993 break;
994 case 'e':
995 ++(*data);
996 if (!strncmp(*data, "num", 3)) {
997 *data += 3;
998 *kw = YANG_ENUM;
999 } else if (!strncmp(*data, "rror-", 5)) {
1000 *data += 5;
1001 if (!strncmp(*data, "app-tag", 7)) {
1002 *data += 7;
1003 *kw = YANG_ERROR_APP_TAG;
1004 } else if (!strncmp(*data, "message", 7)) {
1005 *data += 7;
1006 *kw = YANG_ERROR_MESSAGE;
1007 }
1008 } else if (!strncmp(*data, "xtension", 8)) {
1009 *data += 8;
1010 *kw = YANG_EXTENSION;
1011 }
1012 break;
1013 case 'f':
1014 ++(*data);
1015 if (!strncmp(*data, "eature", 6)) {
1016 *data += 6;
1017 *kw = YANG_FEATURE;
1018 } else if (!strncmp(*data, "raction-digits", 14)) {
1019 *data += 14;
1020 *kw = YANG_FRACTION_DIGITS;
1021 }
1022 break;
1023 case 'g':
1024 ++(*data);
1025 if (!strncmp(*data, "rouping", 7)) {
1026 *data += 7;
1027 *kw = YANG_GROUPING;
1028 }
1029 break;
1030 case 'i':
1031 ++(*data);
1032 if (!strncmp(*data, "dentity", 7)) {
1033 *data += 7;
1034 *kw = YANG_IDENTITY;
1035 } else if (!strncmp(*data, "f-feature", 9)) {
1036 *data += 9;
1037 *kw = YANG_IF_FEATURE;
1038 } else if (!strncmp(*data, "mport", 5)) {
1039 *data += 5;
1040 *kw = YANG_IMPORT;
1041 } else if (**data == 'n') {
1042 ++(*data);
1043 if (!strncmp(*data, "clude", 5)) {
1044 *data += 5;
1045 *kw = YANG_INCLUDE;
1046 } else if (!strncmp(*data, "put", 3)) {
1047 *data += 3;
1048 *kw = YANG_INPUT;
1049 }
1050 }
1051 break;
1052 case 'k':
1053 ++(*data);
1054 if (!strncmp(*data, "ey", 2)) {
1055 *data += 2;
1056 *kw = YANG_KEY;
1057 }
1058 break;
1059 case 'l':
1060 ++(*data);
1061 if (**data == 'e') {
1062 ++(*data);
1063 if (!strncmp(*data, "af", 2)) {
1064 *data += 2;
1065 if (**data != '-') {
1066 *kw = YANG_LEAF;
1067 } else if (!strncmp(*data, "-list", 5)) {
1068 *data += 5;
1069 *kw = YANG_LEAF_LIST;
1070 }
1071 } else if (!strncmp(*data, "ngth", 4)) {
1072 *data += 4;
1073 *kw = YANG_LENGTH;
1074 }
1075 } else if (!strncmp(*data, "ist", 3)) {
1076 *data += 3;
1077 *kw = YANG_LIST;
1078 }
1079 break;
1080 case 'm':
1081 ++(*data);
1082 if (**data == 'a') {
1083 ++(*data);
1084 if (!strncmp(*data, "ndatory", 7)) {
1085 *data += 7;
1086 *kw = YANG_MANDATORY;
1087 } else if (!strncmp(*data, "x-elements", 10)) {
1088 *data += 10;
1089 *kw = YANG_MAX_ELEMENTS;
1090 }
1091 } else if (!strncmp(*data, "in-elements", 11)) {
1092 *data += 11;
1093 *kw = YANG_MIN_ELEMENTS;
1094 } else if (!strncmp(*data, "ust", 3)) {
1095 *data += 3;
1096 *kw = YANG_MUST;
1097 } else if (!strncmp(*data, "od", 2)) {
1098 *data += 2;
1099 if (!strncmp(*data, "ule", 3)) {
1100 *data += 3;
1101 *kw = YANG_MODULE;
1102 } else if (!strncmp(*data, "ifier", 5)) {
1103 *data += 3;
1104 *kw = YANG_MODIFIER;
1105 }
1106 }
1107 break;
1108 case 'n':
1109 ++(*data);
1110 if (!strncmp(*data, "amespace", 8)) {
1111 *data += 8;
1112 *kw = YANG_NAMESPACE;
1113 } else if (!strncmp(*data, "otification", 11)) {
1114 *data += 11;
1115 *kw = YANG_NOTIFICATION;
1116 }
1117 break;
1118 case 'o':
1119 ++(*data);
1120 if (**data == 'r') {
1121 ++(*data);
1122 if (!strncmp(*data, "dered-by", 8)) {
1123 *data += 8;
1124 *kw = YANG_ORDERED_BY;
1125 } else if (!strncmp(*data, "ganization", 10)) {
1126 *data += 10;
1127 *kw = YANG_ORGANIZATION;
1128 }
1129 } else if (!strncmp(*data, "utput", 5)) {
1130 *data += 5;
1131 *kw = YANG_OUTPUT;
1132 }
1133 break;
1134 case 'p':
1135 ++(*data);
1136 if (!strncmp(*data, "at", 2)) {
1137 *data += 2;
1138 if (**data == 'h') {
1139 ++(*data);
1140 *kw = YANG_PATH;
1141 } else if (!strncmp(*data, "tern", 4)) {
1142 *data += 4;
1143 *kw = YANG_PATTERN;
1144 }
1145 } else if (!strncmp(*data, "osition", 7)) {
1146 *data += 7;
1147 *kw = YANG_POSITION;
1148 } else if (!strncmp(*data, "re", 2)) {
1149 *data += 2;
1150 if (!strncmp(*data, "fix", 3)) {
1151 *data += 3;
1152 *kw = YANG_PREFIX;
1153 } else if (!strncmp(*data, "sence", 5)) {
1154 *data += 5;
1155 *kw = YANG_PRESENCE;
1156 }
1157 }
1158 break;
1159 case 'r':
1160 ++(*data);
1161 if (!strncmp(*data, "ange", 4)) {
1162 *data += 4;
1163 *kw = YANG_RANGE;
1164 } else if (**data == 'e') {
1165 ++(*data);
1166 if (**data == 'f') {
1167 ++(*data);
1168 if (!strncmp(*data, "erence", 6)) {
1169 *data += 6;
1170 *kw = YANG_REFERENCE;
1171 } else if (!strncmp(*data, "ine", 3)) {
1172 *data += 3;
1173 *kw = YANG_REFINE;
1174 }
1175 } else if (!strncmp(*data, "quire-instance", 14)) {
1176 *data += 14;
1177 *kw = YANG_REQUIRE_INSTANCE;
1178 } else if (!strncmp(*data, "vision", 6)) {
1179 *data += 6;
1180 if (**data != '-') {
1181 *kw = YANG_REVISION;
1182 } else if (!strncmp(*data, "-date", 5)) {
1183 *data += 5;
1184 *kw = YANG_REVISION_DATE;
1185 }
1186 }
1187 } else if (!strncmp(*data, "pc", 2)) {
1188 *data += 2;
1189 *kw = YANG_RPC;
1190 }
1191 break;
1192 case 's':
1193 ++(*data);
1194 if (!strncmp(*data, "tatus", 5)) {
1195 *data += 5;
1196 *kw = YANG_STATUS;
1197 } else if (!strncmp(*data, "ubmodule", 8)) {
1198 *data += 8;
1199 *kw = YANG_SUBMODULE;
1200 }
1201 break;
1202 case 't':
1203 ++(*data);
1204 if (!strncmp(*data, "ype", 3)) {
1205 *data += 3;
1206 if (**data != 'd') {
1207 *kw = YANG_TYPE;
1208 } else if (!strncmp(*data, "def", 3)) {
1209 *data += 3;
1210 *kw = YANG_TYPEDEF;
1211 }
1212 }
1213 break;
1214 case 'u':
1215 ++(*data);
1216 if (!strncmp(*data, "ni", 2)) {
1217 *data += 2;
1218 if (!strncmp(*data, "que", 3)) {
1219 *data += 3;
1220 *kw = YANG_UNIQUE;
1221 } else if (!strncmp(*data, "ts", 2)) {
1222 *data += 2;
1223 *kw = YANG_UNITS;
1224 }
1225 } else if (!strncmp(*data, "ses", 3)) {
1226 *data += 3;
1227 *kw = YANG_USES;
1228 }
1229 break;
1230 case 'v':
1231 ++(*data);
1232 if (!strncmp(*data, "alue", 4)) {
1233 *data += 4;
1234 *kw = YANG_VALUE;
1235 }
1236 break;
1237 case 'w':
1238 ++(*data);
1239 if (!strncmp(*data, "hen", 3)) {
1240 *data += 3;
1241 *kw = YANG_WHEN;
1242 }
1243 break;
1244 case 'y':
1245 ++(*data);
1246 if (!strncmp(*data, "ang-version", 11)) {
1247 *data += 11;
1248 *kw = YANG_YANG_VERSION;
1249 } else if (!strncmp(*data, "in-element", 10)) {
1250 *data += 10;
1251 *kw = YANG_YIN_ELEMENT;
1252 }
1253 break;
1254 case ';':
1255 ++(*data);
1256 *kw = YANG_SEMICOLON;
1257 break;
1258 case '{':
1259 ++(*data);
1260 *kw = YANG_LEFT_BRACE;
1261 break;
1262 case '}':
1263 ++(*data);
1264 *kw = YANG_RIGHT_BRACE;
1265 break;
1266 default:
1267 break;
1268 }
1269
1270 if (*kw != YANG_NONE) {
1271 /* make sure we have the whole keyword */
1272 switch (**data) {
1273 case ' ':
1274 case '\t':
1275 case '\n':
1276 /* mandatory "sep" */
1277 break;
1278 default:
1279 ++(*data);
1280 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
1281 "a keyword followed by a separator");
1282 return LY_EVALID;
1283 }
1284 } else {
1285 /* still can be an extension */
1286 prefix = 0;
1287 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
1288 if (check_char(ctx, **data, Y_PREF_IDENTIF_ARG, *data == word_start ? 1 : 0, &prefix)) {
1289 return LY_EVALID;
1290 }
1291 ++(*data);
1292 }
1293 if (!**data) {
Radek Krejcic07921a2018-09-17 11:40:15 +02001294 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001295 return LY_EVALID;
1296 }
1297
1298 /* prefix is mandatory for extension instances */
1299 if (prefix != 1) {
1300 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
1301 return LY_EVALID;
1302 }
1303
1304 *kw = YANG_CUSTOM;
1305 }
1306
1307 if (word_p) {
1308 *word_p = (char *)word_start;
1309 *word_len = *data - word_start;
1310 }
1311
1312 return LY_SUCCESS;
1313}
1314
1315static LY_ERR
1316parse_ext_substmt(struct ly_ctx *ctx, const char **data, char *word, int word_len,
1317 struct lysp_stmt **child)
1318{
1319 char *buf;
1320 LY_ERR ret = 0;
1321 enum yang_keyword kw;
1322 struct lysp_stmt *stmt, *par_child;
1323
1324 stmt = calloc(1, sizeof *stmt);
1325 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
1326
1327 stmt->stmt = lydict_insert(ctx, word, word_len);
1328
1329 /* get optional argument */
1330 ret = get_string(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
1331 YANG_ERR_RET(ret);
1332
1333 if (buf) {
1334 stmt->arg = lydict_insert_zc(ctx, word);
1335 } else {
1336 stmt->arg = lydict_insert(ctx, word, word_len);
1337 }
1338
1339 /* insert into parent statements */
1340 if (!*child) {
1341 *child = stmt;
1342 } else {
1343 for (par_child = *child; par_child->next; par_child = par_child->next);
1344 par_child->next = stmt;
1345 }
1346
1347 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1348 YANG_ERR_RET(ret);
1349
1350 ret = parse_ext_substmt(ctx, data, word, word_len, &stmt->child);
1351 YANG_ERR_RET(ret);
1352 }
1353 YANG_ERR_RET(ret);
1354
1355 return ret;
1356}
1357
1358static LY_ERR
1359parse_ext(struct ly_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
1360 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1361{
1362 LY_ERR ret = 0;
1363 char *buf, *word;
1364 int word_len;
1365 struct lysp_ext_instance *e;
1366 enum yang_keyword kw;
1367
1368 LYSP_ARRAY_NEW_RET(ctx, exts, e, LY_EMEM);
1369
1370 /* store name and insubstmt info */
1371 e->name = lydict_insert(ctx, ext_name, ext_name_len);
1372 e->insubstmt = insubstmt;
1373 e->insubstmt_index = insubstmt_index;
1374
1375 /* get optional argument */
1376 ret = get_string(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
1377 YANG_ERR_RET(ret);
1378
1379 if (buf) {
1380 e->argument = lydict_insert_zc(ctx, word);
1381 } else {
1382 e->argument = lydict_insert(ctx, word, word_len);
1383 }
1384
1385 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1386 YANG_ERR_RET(ret);
1387
1388 ret = parse_ext_substmt(ctx, data, word, word_len, &e->child);
1389 YANG_ERR_RET(ret);
1390 }
1391 YANG_ERR_RET(ret);
1392
1393 return ret;
1394}
1395
1396static LY_ERR
1397parse_text_field(struct ly_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
1398 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1399{
1400 LY_ERR ret = 0;
1401 char *buf, *word;
1402 int word_len;
1403 enum yang_keyword kw;
1404
1405 if (*value) {
1406 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, substmt2str(substmt));
1407 return LY_EVALID;
1408 }
1409
1410 /* get value */
1411 ret = get_string(ctx, data, arg, &word, &buf, &word_len);
1412 YANG_ERR_RET(ret);
1413
1414 /* store value and spend buf if allocated */
1415 if (buf) {
1416 *value = lydict_insert_zc(ctx, word);
1417 } else {
1418 *value = lydict_insert(ctx, word, word_len);
1419 }
1420
1421 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1422 YANG_ERR_RET(ret);
1423
1424 switch (kw) {
1425 case YANG_CUSTOM:
1426 ret = parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts);
1427 YANG_ERR_RET(ret);
1428 break;
1429 default:
1430 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), substmt2str(substmt));
1431 return LY_EVALID;
1432 }
1433 }
1434 YANG_ERR_RET(ret);
1435
1436 return ret;
1437}
1438
1439static LY_ERR
1440parse_yangversion(struct ly_ctx *ctx, const char **data, struct lysp_module *mod)
1441{
1442 LY_ERR ret = 0;
1443 char *buf, *word;
1444 int word_len;
1445 enum yang_keyword kw;
1446
1447 if (mod->version) {
1448 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "yang-version");
1449 return LY_EVALID;
1450 }
1451
1452 /* get value */
1453 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
1454 YANG_ERR_RET(ret);
1455
1456 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1457 mod->version = LYS_VERSION_1_0;
1458 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1459 mod->version = LYS_VERSION_1_1;
1460 } else {
1461 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "yang-version");
1462 free(buf);
1463 return LY_EVALID;
1464 }
1465 free(buf);
1466
1467 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1468 YANG_ERR_RET(ret);
1469
1470 switch (kw) {
1471 case YANG_CUSTOM:
1472 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts);
1473 YANG_ERR_RET(ret);
1474 break;
1475 default:
1476 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "yang-version");
1477 return LY_EVALID;
1478 }
1479 }
1480 YANG_ERR_RET(ret);
1481
1482 return ret;
1483}
1484
1485static LY_ERR
1486parse_belongsto(struct ly_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
1487{
1488 LY_ERR ret = 0;
1489 char *buf, *word;
1490 int word_len;
1491 enum yang_keyword kw;
1492
1493 if (*belongsto) {
1494 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "belongs-to");
1495 return LY_EVALID;
1496 }
1497
1498 /* get value */
1499 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
1500 YANG_ERR_RET(ret);
1501
1502 if (buf) {
1503 *belongsto = lydict_insert_zc(ctx, word);
1504 } else {
1505 *belongsto = lydict_insert(ctx, word, word_len);
1506 }
1507
1508 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1509 YANG_ERR_RET(ret);
1510
1511 switch (kw) {
1512 case YANG_PREFIX:
1513 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts);
1514 break;
1515 case YANG_CUSTOM:
1516 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts);
1517 break;
1518 default:
1519 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "belongs-to");
1520 return LY_EVALID;
1521 }
1522 YANG_ERR_RET(ret);
1523 }
1524 YANG_ERR_RET(ret);
1525
1526 /* mandatory substatements */
1527 if (!*prefix) {
1528 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "prefix", "belongs-to");
1529 return LY_EVALID;
1530 }
1531
1532 return ret;
1533}
1534
1535static LY_ERR
1536parse_revisiondate(struct ly_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
1537{
1538 LY_ERR ret = 0;
1539 char *buf, *word;
1540 int word_len;
1541 enum yang_keyword kw;
1542
1543 if (rev[0]) {
1544 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "revision-date");
1545 return LY_EVALID;
1546 }
1547
1548 /* get value */
1549 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
1550 YANG_ERR_RET(ret);
1551
1552 /* check value */
1553 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
1554 free(buf);
1555 return LY_EVALID;
1556 }
1557
1558 /* store value and spend buf if allocated */
1559 strncpy(rev, word, word_len);
1560 free(buf);
1561
1562 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1563 YANG_ERR_RET(ret);
1564
1565 switch (kw) {
1566 case YANG_CUSTOM:
1567 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts);
1568 YANG_ERR_RET(ret);
1569 break;
1570 default:
1571 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "revision-date");
1572 return LY_EVALID;
1573 }
1574 }
1575 YANG_ERR_RET(ret);
1576
1577 return ret;
1578}
1579
1580static LY_ERR
1581parse_include(struct ly_ctx *ctx, const char **data, struct lysp_include **includes)
1582{
1583 LY_ERR ret = 0;
1584 char *buf, *word;
1585 int word_len;
1586 enum yang_keyword kw;
1587 struct lysp_include *inc;
1588
1589 LYSP_ARRAY_NEW_RET(ctx, includes, inc, LY_EMEM);
1590
1591 /* get value */
1592 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
1593 YANG_ERR_RET(ret);
1594
1595 if (buf) {
1596 inc->name = lydict_insert_zc(ctx, word);
1597 } else {
1598 inc->name = lydict_insert(ctx, word, word_len);
1599 }
1600
1601 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1602 YANG_ERR_RET(ret);
1603
1604 switch (kw) {
1605 case YANG_DESCRIPTION:
1606 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts);
1607 break;
1608 case YANG_REFERENCE:
1609 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts);
1610 break;
1611 case YANG_REVISION_DATE:
1612 ret = parse_revisiondate(ctx, data, inc->rev, &inc->exts);
1613 break;
1614 case YANG_CUSTOM:
1615 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts);
1616 break;
1617 default:
1618 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "include");
1619 return LY_EVALID;
1620 }
1621 YANG_ERR_RET(ret);
1622 }
1623 YANG_ERR_RET(ret);
1624
1625 return ret;
1626}
1627
1628static LY_ERR
1629parse_import(struct ly_ctx *ctx, const char **data, struct lysp_import **imports)
1630{
1631 LY_ERR ret = 0;
1632 char *buf, *word;
1633 int word_len;
1634 enum yang_keyword kw;
1635 struct lysp_import *imp;
1636
1637 LYSP_ARRAY_NEW_RET(ctx, imports, imp, LY_EVALID);
1638
1639 /* get value */
1640 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
1641 YANG_ERR_RET(ret);
1642
1643 if (buf) {
1644 imp->name = lydict_insert_zc(ctx, word);
1645 } else {
1646 imp->name = lydict_insert(ctx, word, word_len);
1647 }
1648
1649 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1650 YANG_ERR_RET(ret);
1651
1652 switch (kw) {
1653 case YANG_PREFIX:
1654 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts);
1655 break;
1656 case YANG_DESCRIPTION:
1657 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts);
1658 break;
1659 case YANG_REFERENCE:
1660 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts);
1661 break;
1662 case YANG_REVISION_DATE:
1663 ret = parse_revisiondate(ctx, data, imp->rev, &imp->exts);
1664 break;
1665 case YANG_CUSTOM:
1666 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts);
1667 break;
1668 default:
1669 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "import");
1670 return LY_EVALID;
1671 }
1672 YANG_ERR_RET(ret);
1673 }
1674 YANG_ERR_RET(ret);
1675
1676 /* mandatory substatements */
1677 if (!imp->prefix) {
1678 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "prefix", "import");
1679 return LY_EVALID;
1680 }
1681
1682 return ret;
1683}
1684
1685static LY_ERR
1686parse_revision(struct ly_ctx *ctx, const char **data, struct lysp_revision **revs)
1687{
1688 LY_ERR ret = 0;
1689 char *buf, *word;
1690 int word_len;
1691 enum yang_keyword kw;
1692 struct lysp_revision *rev;
1693
1694 LYSP_ARRAY_NEW_RET(ctx, revs, rev, LY_EMEM);
1695
1696 /* get value */
1697 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
1698 YANG_ERR_RET(ret);
1699
1700 /* check value */
1701 if (lysp_check_date(ctx, word, word_len, "revision")) {
1702 return LY_EVALID;
1703 }
1704
1705 strncpy(rev->rev, word, word_len);
1706 free(buf);
1707
1708 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1709 YANG_ERR_RET(ret);
1710
1711 switch (kw) {
1712 case YANG_DESCRIPTION:
1713 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts);
1714 break;
1715 case YANG_REFERENCE:
1716 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts);
1717 break;
1718 case YANG_CUSTOM:
1719 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts);
1720 break;
1721 default:
1722 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "revision");
1723 return LY_EVALID;
1724 }
1725 YANG_ERR_RET(ret);
1726 }
1727 YANG_ERR_RET(ret);
1728
1729 return ret;
1730}
1731
1732static LY_ERR
1733parse_text_fields(struct ly_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
1734 struct lysp_ext_instance **exts)
1735{
1736 LY_ERR ret = 0;
1737 char *buf, *word;
1738 int count, word_len;
1739 enum yang_keyword kw;
1740
1741 /* allocate new pointer */
1742 for (count = 1; (*texts) && (*texts)[count - 1]; ++count);
1743 *texts = realloc(*texts, count * sizeof **texts);
1744 LY_CHECK_ERR_RET(!*texts, LOGMEM(ctx), LY_EMEM);
1745
1746 /* get value */
1747 ret = get_string(ctx, data, arg, &word, &buf, &word_len);
1748 YANG_ERR_RET(ret);
1749
1750 if (buf) {
1751 (*texts)[count - 1] = lydict_insert_zc(ctx, word);
1752 } else {
1753 (*texts)[count - 1] = lydict_insert(ctx, word, word_len);
1754 }
1755
1756 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1757 YANG_ERR_RET(ret);
1758
1759 switch (kw) {
1760 case YANG_CUSTOM:
1761 ret = parse_ext(ctx, data, word, word_len, substmt, count - 1, exts);
1762 YANG_ERR_RET(ret);
1763 break;
1764 default:
1765 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), substmt2str(substmt));
1766 return LY_EVALID;
1767 }
1768 }
1769 YANG_ERR_RET(ret);
1770
1771 return ret;
1772}
1773
1774static LY_ERR
1775parse_config(struct ly_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
1776{
1777 LY_ERR ret = 0;
1778 char *buf, *word;
1779 int word_len;
1780 enum yang_keyword kw;
1781
1782 if (*flags & LYS_CONFIG_MASK) {
1783 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "config");
1784 return LY_EVALID;
1785 }
1786
1787 /* get value */
1788 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
1789 YANG_ERR_RET(ret);
1790
1791 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1792 *flags |= LYS_CONFIG_W;
1793 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1794 *flags |= LYS_CONFIG_R;
1795 } else {
1796 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "config");
1797 free(buf);
1798 return LY_EVALID;
1799 }
1800 free(buf);
1801
1802 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1803 YANG_ERR_RET(ret);
1804
1805 switch (kw) {
1806 case YANG_CUSTOM:
1807 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts);
1808 YANG_ERR_RET(ret);
1809 break;
1810 default:
1811 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "config");
1812 return LY_EVALID;
1813 }
1814 }
1815 YANG_ERR_RET(ret);
1816
1817 return ret;
1818}
1819
1820static LY_ERR
1821parse_mandatory(struct ly_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
1822{
1823 LY_ERR ret = 0;
1824 char *buf, *word;
1825 int word_len;
1826 enum yang_keyword kw;
1827
1828 if (*flags & LYS_MAND_MASK) {
1829 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "mandatory");
1830 return LY_EVALID;
1831 }
1832
1833 /* get value */
1834 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
1835 YANG_ERR_RET(ret);
1836
1837 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1838 *flags |= LYS_MAND_TRUE;
1839 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1840 *flags |= LYS_MAND_FALSE;
1841 } else {
1842 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "mandatory");
1843 free(buf);
1844 return LY_EVALID;
1845 }
1846 free(buf);
1847
1848 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1849 YANG_ERR_RET(ret);
1850
1851 switch (kw) {
1852 case YANG_CUSTOM:
1853 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts);
1854 YANG_ERR_RET(ret);
1855 break;
1856 default:
1857 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "mandatory");
1858 return LY_EVALID;
1859 }
1860 }
1861 YANG_ERR_RET(ret);
1862
1863 return ret;
1864}
1865
1866static LY_ERR
1867parse_restr(struct ly_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr *restr)
1868{
1869 LY_ERR ret = 0;
1870 char *buf, *word;
1871 int word_len;
1872 enum yang_keyword kw;
1873
1874 /* get value */
1875 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
1876 YANG_ERR_RET(ret);
1877
1878 if (buf) {
1879 restr->arg = lydict_insert_zc(ctx, word);
1880 } else {
1881 restr->arg = lydict_insert(ctx, word, word_len);
1882 }
1883
1884 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1885 YANG_ERR_RET(ret);
1886
1887 switch (kw) {
1888 case YANG_DESCRIPTION:
1889 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
1890 break;
1891 case YANG_REFERENCE:
1892 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
1893 break;
1894 case YANG_ERROR_APP_TAG:
1895 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
1896 break;
1897 case YANG_ERROR_MESSAGE:
1898 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
1899 break;
1900 case YANG_CUSTOM:
1901 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
1902 break;
1903 default:
1904 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), kw2str(restr_kw));
1905 return LY_EVALID;
1906 }
1907 YANG_ERR_RET(ret);
1908 }
1909 YANG_ERR_RET(ret);
1910
1911 return ret;
1912}
1913
1914static LY_ERR
1915parse_restrs(struct ly_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr **restrs)
1916{
1917 struct lysp_restr *restr;
1918
1919 LYSP_ARRAY_NEW_RET(ctx, restrs, restr, LY_EMEM);
1920
1921 return parse_restr(ctx, data, restr_kw, restr);
1922}
1923
1924static LY_ERR
1925parse_status(struct ly_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
1926{
1927 LY_ERR ret = 0;
1928 char *buf, *word;
1929 int word_len;
1930 enum yang_keyword kw;
1931
1932 if (*flags & LYS_STATUS_MASK) {
1933 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "status");
1934 return LY_EVALID;
1935 }
1936
1937 /* get value */
1938 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
1939 YANG_ERR_RET(ret);
1940
1941 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1942 *flags |= LYS_STATUS_CURR;
1943 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1944 *flags |= LYS_STATUS_DEPRC;
1945 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1946 *flags |= LYS_STATUS_OBSLT;
1947 } else {
1948 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "status");
1949 free(buf);
1950 return LY_EVALID;
1951 }
1952 free(buf);
1953
1954 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
1955 YANG_ERR_RET(ret);
1956
1957 switch (kw) {
1958 case YANG_CUSTOM:
1959 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts);
1960 YANG_ERR_RET(ret);
1961 break;
1962 default:
1963 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "status");
1964 return LY_EVALID;
1965 }
1966 }
1967 YANG_ERR_RET(ret);
1968
1969 return ret;
1970}
1971
1972static LY_ERR
1973parse_when(struct ly_ctx *ctx, const char **data, struct lysp_when **when_p)
1974{
1975 LY_ERR ret = 0;
1976 char *buf, *word;
1977 int word_len;
1978 enum yang_keyword kw;
1979 struct lysp_when *when;
1980
1981 if (*when_p) {
1982 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "when");
1983 return LY_EVALID;
1984 }
1985
1986 when = calloc(1, sizeof *when);
1987 LY_CHECK_ERR_RET(!when, LOGMEM(ctx), LY_EMEM);
1988 *when_p = when;
1989
1990 /* get value */
1991 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
1992 YANG_ERR_RET(ret);
1993
1994 if (buf) {
1995 when->cond = lydict_insert_zc(ctx, word);
1996 } else {
1997 when->cond = lydict_insert(ctx, word, word_len);
1998 }
1999
2000 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2001 YANG_ERR_RET(ret);
2002
2003 switch (kw) {
2004 case YANG_DESCRIPTION:
2005 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts);
2006 break;
2007 case YANG_REFERENCE:
2008 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts);
2009 break;
2010 case YANG_CUSTOM:
2011 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts);
2012 break;
2013 default:
2014 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "when");
2015 return LY_EVALID;
2016 }
2017 YANG_ERR_RET(ret);
2018 }
2019 YANG_ERR_RET(ret);
2020
2021 return ret;
2022}
2023
2024static LY_ERR
2025parse_any(struct ly_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node **siblings)
2026{
2027 LY_ERR ret = 0;
2028 char *buf, *word;
2029 int word_len;
2030 struct lysp_node *iter;
2031 struct lysp_node_anydata *any;
2032
2033 /* create structure */
2034 any = calloc(1, sizeof *any);
2035 LY_CHECK_ERR_RET(!any, LOGMEM(ctx), LY_EMEM);
2036 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
2037
2038 /* insert into siblings */
2039 if (!*siblings) {
2040 *siblings = (struct lysp_node *)any;
2041 } else {
2042 for (iter = *siblings; iter->next; iter = iter->next);
2043 iter->next = (struct lysp_node *)any;
2044 }
2045
2046 /* get name */
2047 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
2048 YANG_ERR_RET(ret);
2049
2050 if (buf) {
2051 any->name = lydict_insert_zc(ctx, word);
2052 } else {
2053 any->name = lydict_insert(ctx, word, word_len);
2054 }
2055
2056 /* parse substatements */
2057 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2058 YANG_ERR_RET(ret);
2059
2060 switch (kw) {
2061 case YANG_CONFIG:
2062 ret = parse_config(ctx, data, &any->flags, &any->exts);
2063 break;
2064 case YANG_DESCRIPTION:
2065 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts);
2066 break;
2067 case YANG_IF_FEATURE:
2068 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts);
2069 break;
2070 case YANG_MANDATORY:
2071 ret = parse_mandatory(ctx, data, &any->flags, &any->exts);
2072 break;
2073 case YANG_MUST:
2074 ret = parse_restrs(ctx, data, kw, &any->musts);
2075 break;
2076 case YANG_REFERENCE:
2077 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts);
2078 break;
2079 case YANG_STATUS:
2080 ret = parse_status(ctx, data, &any->flags, &any->exts);
2081 break;
2082 case YANG_WHEN:
2083 ret = parse_when(ctx, data, &any->when);
2084 break;
2085 case YANG_CUSTOM:
2086 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts);
2087 break;
2088 default:
2089 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), nodetype2str(any->nodetype));
2090 return LY_EVALID;
2091 }
2092 YANG_ERR_RET(ret);
2093 }
2094 YANG_ERR_RET(ret);
2095
2096 return ret;
2097}
2098
2099static LY_ERR
2100parse_type_enum_value_pos(struct ly_ctx *ctx, const char **data, enum yang_keyword val_kw, int64_t *value, uint16_t *flags,
2101 struct lysp_ext_instance **exts)
2102{
2103 LY_ERR ret = 0;
2104 char *buf, *word, *ptr;
2105 int word_len;
2106 long int num;
2107 unsigned long int unum;
2108 enum yang_keyword kw;
2109
2110 if (*flags & LYS_SET_VALUE) {
2111 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, kw2str(val_kw));
2112 return LY_EVALID;
2113 }
2114 *flags |= LYS_SET_VALUE;
2115
2116 /* get value */
2117 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
2118 YANG_ERR_RET(ret);
2119
2120 if (!word_len || (word[0] == '+') || ((word[0] == '0') && (word_len > 1)) || ((val_kw == YANG_VALUE) && !strncmp(word, "-0", 2))) {
2121 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, kw2str(val_kw));
2122 free(buf);
2123 return LY_EVALID;
2124 }
2125
2126 errno = 0;
2127 if (val_kw == YANG_VALUE) {
2128 num = strtol(word, &ptr, 10);
2129 } else {
2130 unum = strtoul(word, &ptr, 10);
2131 }
2132 /* we have not parsed the whole argument */
2133 if (ptr - word != word_len) {
2134 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, kw2str(val_kw));
2135 free(buf);
2136 return LY_EVALID;
2137 }
2138 if (errno == ERANGE) {
2139 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_OOB, word_len, word, kw2str(val_kw));
2140 free(buf);
2141 return LY_EVALID;
2142 }
2143 if (val_kw == YANG_VALUE) {
2144 *value = num;
2145 } else {
2146 *value = unum;
2147 }
2148 free(buf);
2149
2150 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2151 YANG_ERR_RET(ret);
2152
2153 switch (kw) {
2154 case YANG_CUSTOM:
2155 ret = parse_ext(ctx, data, word, word_len, val_kw == YANG_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts);
2156 YANG_ERR_RET(ret);
2157 break;
2158 default:
2159 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), kw2str(val_kw));
2160 return LY_EVALID;
2161 }
2162 }
2163 YANG_ERR_RET(ret);
2164
2165 return ret;
2166}
2167
2168static LY_ERR
2169parse_type_enum(struct ly_ctx *ctx, const char **data, enum yang_keyword enum_kw, struct lysp_type_enum **enums)
2170{
2171 LY_ERR ret = 0;
2172 char *buf, *word;
2173 int word_len;
2174 enum yang_keyword kw;
2175 struct lysp_type_enum *enm;
2176
2177 LYSP_ARRAY_NEW_RET(ctx, enums, enm, LY_EMEM);
2178
2179 /* get value */
2180 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
2181 YANG_ERR_RET(ret);
2182
2183 if (buf) {
2184 enm->name = lydict_insert_zc(ctx, word);
2185 } else {
2186 enm->name = lydict_insert(ctx, word, word_len);
2187 }
2188
2189 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2190 YANG_ERR_RET(ret);
2191
2192 switch (kw) {
2193 case YANG_DESCRIPTION:
2194 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts);
2195 break;
2196 case YANG_IF_FEATURE:
2197 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts);
2198 break;
2199 case YANG_REFERENCE:
2200 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts);
2201 break;
2202 case YANG_STATUS:
2203 ret = parse_status(ctx, data, &enm->flags, &enm->exts);
2204 break;
2205 case YANG_VALUE:
2206 case YANG_POSITION:
2207 ret = parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts);
2208 break;
2209 case YANG_CUSTOM:
2210 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts);
2211 break;
2212 default:
2213 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), kw2str(enum_kw));
2214 return LY_EVALID;
2215 }
2216 YANG_ERR_RET(ret);
2217 }
2218 YANG_ERR_RET(ret);
2219
2220 return ret;
2221}
2222
2223static LY_ERR
2224parse_type_fracdigits(struct ly_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
2225{
2226 LY_ERR ret = 0;
2227 char *buf, *word, *ptr;
2228 int word_len;
2229 unsigned long int num;
2230 enum yang_keyword kw;
2231
2232 if (*fracdig) {
2233 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "fraction-digits");
2234 return LY_EVALID;
2235 }
2236
2237 /* get value */
2238 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
2239 YANG_ERR_RET(ret);
2240
2241 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
2242 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "fraction-digits");
2243 free(buf);
2244 return LY_EVALID;
2245 }
2246
2247 errno = 0;
2248 num = strtoul(word, &ptr, 10);
2249 /* we have not parsed the whole argument */
2250 if (ptr - word != word_len) {
2251 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "fraction-digits");
2252 free(buf);
2253 return LY_EVALID;
2254 }
2255 if ((errno == ERANGE) || (num > 18)) {
2256 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_OOB, word_len, word, "fraction-digits");
2257 free(buf);
2258 return LY_EVALID;
2259 }
2260 *fracdig = num;
2261 free(buf);
2262
2263 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2264 YANG_ERR_RET(ret);
2265
2266 switch (kw) {
2267 case YANG_CUSTOM:
2268 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts);
2269 YANG_ERR_RET(ret);
2270 break;
2271 default:
2272 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "fraction-digits");
2273 return LY_EVALID;
2274 }
2275 }
2276 YANG_ERR_RET(ret);
2277
2278 return ret;
2279}
2280
2281static LY_ERR
2282parse_type_reqinstance(struct ly_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
2283 struct lysp_ext_instance **exts)
2284{
2285 LY_ERR ret = 0;
2286 char *buf, *word;
2287 int word_len;
2288 enum yang_keyword kw;
2289
2290 if (*flags & LYS_SET_REQINST) {
2291 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "require-instance");
2292 return LY_EVALID;
2293 }
2294 *flags |= LYS_SET_REQINST;
2295
2296 /* get value */
2297 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
2298 YANG_ERR_RET(ret);
2299
2300 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2301 *reqinst = 1;
2302 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
2303 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "require-instance");
2304 free(buf);
2305 return LY_EVALID;
2306 }
2307 free(buf);
2308
2309 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2310 YANG_ERR_RET(ret);
2311
2312 switch (kw) {
2313 case YANG_CUSTOM:
2314 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts);
2315 YANG_ERR_RET(ret);
2316 break;
2317 default:
2318 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "require-instance");
2319 return LY_EVALID;
2320 }
2321 }
2322 YANG_ERR_RET(ret);
2323
2324 return ret;
2325}
2326
2327static LY_ERR
2328parse_type_pattern_modifier(struct ly_ctx *ctx, const char **data, const char **pat, struct lysp_ext_instance **exts)
2329{
2330 LY_ERR ret = 0;
2331 char *buf, *word;
2332 int word_len;
2333 enum yang_keyword kw;
2334
2335 if ((*pat)[0] == 0x15) {
2336 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "modifier");
2337 return LY_EVALID;
2338 }
2339
2340 /* get value */
2341 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
2342 YANG_ERR_RET(ret);
2343
2344 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
2345 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "modifier");
2346 free(buf);
2347 return LY_EVALID;
2348 }
2349 free(buf);
2350
2351 /* replace the value in the dictionary */
2352 buf = malloc(strlen(*pat) + 1);
2353 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx), LY_EMEM);
2354 strcpy(buf, *pat);
2355 lydict_remove(ctx, *pat);
2356
2357 assert(buf[0] == 0x06);
2358 buf[0] = 0x15;
2359 *pat = lydict_insert_zc(ctx, buf);
2360
2361 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2362 YANG_ERR_RET(ret);
2363
2364 switch (kw) {
2365 case YANG_CUSTOM:
2366 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts);
2367 YANG_ERR_RET(ret);
2368 break;
2369 default:
2370 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "modifier");
2371 return LY_EVALID;
2372 }
2373 }
2374 YANG_ERR_RET(ret);
2375
2376 return ret;
2377}
2378
2379static LY_ERR
2380parse_type_pattern(struct ly_ctx *ctx, const char **data, struct lysp_restr **patterns)
2381{
2382 LY_ERR ret = 0;
2383 char *buf, *word;
2384 int word_len;
2385 enum yang_keyword kw;
2386 struct lysp_restr *restr;
2387
2388 LYSP_ARRAY_NEW_RET(ctx, patterns, restr, LY_EMEM);
2389
2390 /* get value */
2391 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
2392 YANG_ERR_RET(ret);
2393
2394 /* add special meaning first byte */
2395 if (buf) {
2396 buf = realloc(buf, word_len + 2);
2397 word = buf;
2398 } else {
2399 buf = malloc(word_len + 2);
2400 }
2401 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx), LY_EMEM);
2402 memmove(buf + 1, word, word_len + 1);
2403 word[0] = 0x06;
2404 restr->arg = lydict_insert_zc(ctx, word);
2405
2406 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2407 YANG_ERR_RET(ret);
2408
2409 switch (kw) {
2410 case YANG_DESCRIPTION:
2411 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
2412 break;
2413 case YANG_REFERENCE:
2414 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
2415 break;
2416 case YANG_ERROR_APP_TAG:
2417 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
2418 break;
2419 case YANG_ERROR_MESSAGE:
2420 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
2421 break;
2422 case YANG_MODIFIER:
2423 ret = parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts);
2424 break;
2425 case YANG_CUSTOM:
2426 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
2427 break;
2428 default:
2429 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "pattern");
2430 return LY_EVALID;
2431 }
2432 YANG_ERR_RET(ret);
2433 }
2434 YANG_ERR_RET(ret);
2435
2436 return ret;
2437}
2438
2439static LY_ERR
2440parse_type(struct ly_ctx *ctx, const char **data, struct lysp_type *type)
2441{
2442 LY_ERR ret = 0;
2443 char *buf, *word;
2444 int word_len;
2445 enum yang_keyword kw;
2446 struct lysp_type *nest_type;
2447
2448 if (type->name) {
2449 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "type");
2450 return LY_EVALID;
2451 }
2452
2453 /* get value */
2454 ret = get_string(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
2455 YANG_ERR_RET(ret);
2456
2457 if (buf) {
2458 type->name = lydict_insert_zc(ctx, word);
2459 } else {
2460 type->name = lydict_insert(ctx, word, word_len);
2461 }
2462
2463 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2464 YANG_ERR_RET(ret);
2465
2466 switch (kw) {
2467 case YANG_BASE:
2468 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts);
2469 break;
2470 case YANG_BIT:
2471 ret = parse_type_enum(ctx, data, kw, &type->bits);
2472 break;
2473 case YANG_ENUM:
2474 ret = parse_type_enum(ctx, data, kw, &type->enums);
2475 break;
2476 case YANG_FRACTION_DIGITS:
2477 ret = parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts);
2478 break;
2479 case YANG_LENGTH:
2480 if (type->length) {
2481 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, kw2str(kw));
2482 return LY_EVALID;
2483 }
2484 type->length = calloc(1, sizeof *type->length);
2485 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx), LY_EMEM);
2486
2487 ret = parse_restr(ctx, data, kw, type->length);
2488 break;
2489 case YANG_PATH:
2490 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts);
2491 break;
2492 case YANG_PATTERN:
2493 ret = parse_type_pattern(ctx, data, &type->patterns);
2494 break;
2495 case YANG_RANGE:
2496 if (type->range) {
2497 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, kw2str(kw));
2498 return LY_EVALID;
2499 }
2500 type->range = calloc(1, sizeof *type->range);
2501 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx), LY_EVALID);
2502
2503 ret = parse_restr(ctx, data, kw, type->range);
2504 break;
2505 case YANG_REQUIRE_INSTANCE:
2506 ret = parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts);
2507 break;
2508 case YANG_TYPE:
2509 {
2510 LYSP_ARRAY_NEW_RET(ctx, &type->types, nest_type, LY_EMEM);
2511 }
2512 ret = parse_type(ctx, data, nest_type);
2513 break;
2514 case YANG_CUSTOM:
2515 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts);
2516 break;
2517 default:
2518 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "when");
2519 return LY_EVALID;
2520 }
2521 YANG_ERR_RET(ret);
2522 }
2523 YANG_ERR_RET(ret);
2524
2525 return ret;
2526}
2527
2528static LY_ERR
2529parse_leaf(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
2530{
2531 LY_ERR ret = 0;
2532 char *buf, *word;
2533 int word_len;
2534 enum yang_keyword kw;
2535 struct lysp_node *iter;
2536 struct lysp_node_leaf *leaf;
2537
2538 /* create structure */
2539 leaf = calloc(1, sizeof *leaf);
2540 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx), LY_EMEM);
2541 leaf->nodetype = LYS_LEAF;
2542
2543 /* insert into siblings */
2544 if (!*siblings) {
2545 *siblings = (struct lysp_node *)leaf;
2546 } else {
2547 for (iter = *siblings; iter->next; iter = iter->next);
2548 iter->next = (struct lysp_node *)leaf;
2549 }
2550
2551 /* get name */
2552 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
2553 YANG_ERR_RET(ret);
2554
2555 if (buf) {
2556 leaf->name = lydict_insert_zc(ctx, word);
2557 } else {
2558 leaf->name = lydict_insert(ctx, word, word_len);
2559 }
2560
2561 /* parse substatements */
2562 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2563 YANG_ERR_RET(ret);
2564
2565 switch (kw) {
2566 case YANG_CONFIG:
2567 ret = parse_config(ctx, data, &leaf->flags, &leaf->exts);
2568 break;
2569 case YANG_DEFAULT:
2570 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts);
2571 break;
2572 case YANG_DESCRIPTION:
2573 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts);
2574 break;
2575 case YANG_IF_FEATURE:
2576 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts);
2577 break;
2578 case YANG_MANDATORY:
2579 ret = parse_mandatory(ctx, data, &leaf->flags, &leaf->exts);
2580 break;
2581 case YANG_MUST:
2582 ret = parse_restrs(ctx, data, kw, &leaf->musts);
2583 break;
2584 case YANG_REFERENCE:
2585 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts);
2586 break;
2587 case YANG_STATUS:
2588 ret = parse_status(ctx, data, &leaf->flags, &leaf->exts);
2589 break;
2590 case YANG_TYPE:
2591 ret = parse_type(ctx, data, &leaf->type);
2592 break;
2593 case YANG_UNITS:
2594 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts);
2595 break;
2596 case YANG_WHEN:
2597 ret = parse_when(ctx, data, &leaf->when);
2598 break;
2599 case YANG_CUSTOM:
2600 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts);
2601 break;
2602 default:
2603 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "leaf");
2604 return LY_EVALID;
2605 }
2606 YANG_ERR_RET(ret);
2607 }
2608 YANG_ERR_RET(ret);
2609
2610 /* mandatory substatements */
2611 if (!leaf->type.name) {
2612 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "type", "leaf");
2613 return LY_EVALID;
2614 }
2615
2616 return ret;
2617}
2618
2619static LY_ERR
2620parse_maxelements(struct ly_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
2621{
2622 LY_ERR ret = 0;
2623 char *buf, *word, *ptr;
2624 int word_len;
2625 unsigned long int num;
2626 enum yang_keyword kw;
2627
2628 if (*flags & LYS_SET_MAX) {
2629 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "max-elements");
2630 return LY_EVALID;
2631 }
2632 *flags |= LYS_SET_MAX;
2633
2634 /* get value */
2635 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
2636 YANG_ERR_RET(ret);
2637
2638 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
2639 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "max-elements");
2640 free(buf);
2641 return LY_EVALID;
2642 }
2643
2644 if (strncmp(word, "unbounded", word_len)) {
2645 errno = 0;
2646 num = strtoul(word, &ptr, 10);
2647 /* we have not parsed the whole argument */
2648 if (ptr - word != word_len) {
2649 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "max-elements");
2650 free(buf);
2651 return LY_EVALID;
2652 }
2653 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2654 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_OOB, word_len, word, "max-elements");
2655 free(buf);
2656 return LY_EVALID;
2657 }
2658
2659 *max = num;
2660 }
2661 free(buf);
2662
2663 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2664 YANG_ERR_RET(ret);
2665
2666 switch (kw) {
2667 case YANG_CUSTOM:
2668 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts);
2669 YANG_ERR_RET(ret);
2670 break;
2671 default:
2672 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "max-elements");
2673 return LY_EVALID;
2674 }
2675 }
2676 YANG_ERR_RET(ret);
2677
2678 return ret;
2679}
2680
2681static LY_ERR
2682parse_minelements(struct ly_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
2683{
2684 LY_ERR ret = 0;
2685 char *buf, *word, *ptr;
2686 int word_len;
2687 unsigned long int num;
2688 enum yang_keyword kw;
2689
2690 if (*flags & LYS_SET_MIN) {
2691 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "min-elements");
2692 return LY_EVALID;
2693 }
2694 *flags |= LYS_SET_MIN;
2695
2696 /* get value */
2697 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
2698 YANG_ERR_RET(ret);
2699
2700 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
2701 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "min-elements");
2702 free(buf);
2703 return LY_EVALID;
2704 }
2705
2706 errno = 0;
2707 num = strtoul(word, &ptr, 10);
2708 /* we have not parsed the whole argument */
2709 if (ptr - word != word_len) {
2710 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "min-elements");
2711 free(buf);
2712 return LY_EVALID;
2713 }
2714 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2715 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_OOB, word_len, word, "min-elements");
2716 free(buf);
2717 return LY_EVALID;
2718 }
2719 *min = num;
2720 free(buf);
2721
2722 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2723 YANG_ERR_RET(ret);
2724
2725 switch (kw) {
2726 case YANG_CUSTOM:
2727 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts);
2728 YANG_ERR_RET(ret);
2729 break;
2730 default:
2731 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "min-elements");
2732 return LY_EVALID;
2733 }
2734 }
2735 YANG_ERR_RET(ret);
2736
2737 return ret;
2738}
2739
2740static LY_ERR
2741parse_orderedby(struct ly_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
2742{
2743 LY_ERR ret = 0;
2744 char *buf, *word;
2745 int word_len;
2746 enum yang_keyword kw;
2747
2748 if (*flags & LYS_ORDBY_MASK) {
2749 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "ordered-by");
2750 return LY_EVALID;
2751 }
2752
2753 /* get value */
2754 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
2755 YANG_ERR_RET(ret);
2756
2757 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2758 *flags |= LYS_ORDBY_SYSTEM;
2759 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2760 *flags |= LYS_ORDBY_USER;
2761 } else {
2762 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "ordered-by");
2763 free(buf);
2764 return LY_EVALID;
2765 }
2766 free(buf);
2767
2768 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2769 YANG_ERR_RET(ret);
2770
2771 switch (kw) {
2772 case YANG_CUSTOM:
2773 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts);
2774 YANG_ERR_RET(ret);
2775 break;
2776 default:
2777 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "ordered-by");
2778 return LY_EVALID;
2779 }
2780 }
2781 YANG_ERR_RET(ret);
2782
2783 return ret;
2784}
2785
2786static LY_ERR
2787parse_leaflist(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
2788{
2789 LY_ERR ret = 0;
2790 char *buf, *word;
2791 int word_len;
2792 enum yang_keyword kw;
2793 struct lysp_node *iter;
2794 struct lysp_node_leaflist *llist;
2795
2796 /* create structure */
2797 llist = calloc(1, sizeof *llist);
2798 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx), LY_EMEM);
2799 llist->nodetype = LYS_LEAFLIST;
2800
2801 /* insert into siblings */
2802 if (!*siblings) {
2803 *siblings = (struct lysp_node *)llist;
2804 } else {
2805 for (iter = *siblings; iter->next; iter = iter->next);
2806 iter->next = (struct lysp_node *)llist;
2807 }
2808
2809 /* get name */
2810 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
2811 YANG_ERR_RET(ret);
2812
2813 if (buf) {
2814 llist->name = lydict_insert_zc(ctx, word);
2815 } else {
2816 llist->name = lydict_insert(ctx, word, word_len);
2817 }
2818
2819 /* parse substatements */
2820 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2821 YANG_ERR_RET(ret);
2822
2823 switch (kw) {
2824 case YANG_CONFIG:
2825 ret = parse_config(ctx, data, &llist->flags, &llist->exts);
2826 break;
2827 case YANG_DEFAULT:
2828 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts);
2829 break;
2830 case YANG_DESCRIPTION:
2831 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts);
2832 break;
2833 case YANG_IF_FEATURE:
2834 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts);
2835 break;
2836 case YANG_MAX_ELEMENTS:
2837 ret = parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts);
2838 break;
2839 case YANG_MIN_ELEMENTS:
2840 ret = parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts);
2841 break;
2842 case YANG_MUST:
2843 ret = parse_restrs(ctx, data, kw, &llist->musts);
2844 break;
2845 case YANG_ORDERED_BY:
2846 ret = parse_orderedby(ctx, data, &llist->flags, &llist->exts);
2847 break;
2848 case YANG_REFERENCE:
2849 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts);
2850 break;
2851 case YANG_STATUS:
2852 ret = parse_status(ctx, data, &llist->flags, &llist->exts);
2853 break;
2854 case YANG_TYPE:
2855 ret = parse_type(ctx, data, &llist->type);
2856 break;
2857 case YANG_UNITS:
2858 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts);
2859 break;
2860 case YANG_WHEN:
2861 ret = parse_when(ctx, data, &llist->when);
2862 break;
2863 case YANG_CUSTOM:
2864 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts);
2865 break;
2866 default:
2867 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "llist");
2868 return LY_EVALID;
2869 }
2870 YANG_ERR_RET(ret);
2871 }
2872 YANG_ERR_RET(ret);
2873
2874 /* mandatory substatements */
2875 if (!llist->type.name) {
2876 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "type", "leaf-list");
2877 return LY_EVALID;
2878 }
2879
2880 return ret;
2881}
2882
2883static LY_ERR
2884parse_refine(struct ly_ctx *ctx, const char **data, struct lysp_refine **refines)
2885{
2886 LY_ERR ret = 0;
2887 char *buf, *word;
2888 int word_len;
2889 enum yang_keyword kw;
2890 struct lysp_refine *rf;
2891
2892 LYSP_ARRAY_NEW_RET(ctx, refines, rf, LY_EMEM);
2893
2894 /* get value */
2895 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
2896 YANG_ERR_RET(ret);
2897
2898 if (buf) {
2899 rf->nodeid = lydict_insert_zc(ctx, word);
2900 } else {
2901 rf->nodeid = lydict_insert(ctx, word, word_len);
2902 }
2903
2904 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2905 YANG_ERR_RET(ret);
2906
2907 switch (kw) {
2908 case YANG_CONFIG:
2909 ret = parse_config(ctx, data, &rf->flags, &rf->exts);
2910 break;
2911 case YANG_DEFAULT:
2912 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts);
2913 break;
2914 case YANG_DESCRIPTION:
2915 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts);
2916 break;
2917 case YANG_IF_FEATURE:
2918 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts);
2919 break;
2920 case YANG_MAX_ELEMENTS:
2921 ret = parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts);
2922 break;
2923 case YANG_MIN_ELEMENTS:
2924 ret = parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts);
2925 break;
2926 case YANG_MUST:
2927 ret = parse_restrs(ctx, data, kw, &rf->musts);
2928 break;
2929 case YANG_MANDATORY:
2930 ret = parse_mandatory(ctx, data, &rf->flags, &rf->exts);
2931 break;
2932 case YANG_REFERENCE:
2933 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts);
2934 break;
2935 case YANG_PRESENCE:
2936 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts);
2937 break;
2938 case YANG_CUSTOM:
2939 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts);
2940 break;
2941 default:
2942 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "refine");
2943 return LY_EVALID;
2944 }
2945 YANG_ERR_RET(ret);
2946 }
2947 YANG_ERR_RET(ret);
2948
2949 return ret;
2950}
2951
2952static LY_ERR
2953parse_typedef(struct ly_ctx *ctx, const char **data, struct lysp_tpdf **typedefs)
2954{
2955 LY_ERR ret = 0;
2956 char *buf, *word;
2957 int word_len;
2958 enum yang_keyword kw;
2959 struct lysp_tpdf *tpdf;
2960
2961 LYSP_ARRAY_NEW_RET(ctx, typedefs, tpdf, LY_EMEM);
2962
2963 /* get value */
2964 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
2965 YANG_ERR_RET(ret);
2966
2967 if (buf) {
2968 tpdf->name = lydict_insert_zc(ctx, word);
2969 } else {
2970 tpdf->name = lydict_insert(ctx, word, word_len);
2971 }
2972
2973 /* parse substatements */
2974 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
2975 YANG_ERR_RET(ret);
2976
2977 switch (kw) {
2978 case YANG_DEFAULT:
2979 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts);
2980 break;
2981 case YANG_DESCRIPTION:
2982 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts);
2983 break;
2984 case YANG_REFERENCE:
2985 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts);
2986 break;
2987 case YANG_STATUS:
2988 ret = parse_status(ctx, data, &tpdf->flags, &tpdf->exts);
2989 break;
2990 case YANG_TYPE:
2991 ret = parse_type(ctx, data, &tpdf->type);
2992 break;
2993 case YANG_UNITS:
2994 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts);
2995 break;
2996 case YANG_CUSTOM:
2997 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts);
2998 break;
2999 default:
3000 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "typedef");
3001 return LY_EVALID;
3002 }
3003 YANG_ERR_RET(ret);
3004 }
3005 YANG_ERR_RET(ret);
3006
3007 /* mandatory substatements */
3008 if (!tpdf->type.name) {
3009 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "type", "typedef");
3010 return LY_EVALID;
3011 }
3012
3013 return ret;
3014}
3015
3016static LY_ERR
3017parse_inout(struct ly_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_action_inout **inout_p)
3018{
3019 LY_ERR ret = 0;
3020 char *word;
3021 int word_len;
3022 struct lysp_action_inout *inout;
3023
3024 if (*inout_p) {
3025 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, kw2str(kw));
3026 return LY_EVALID;
3027 }
3028
3029 /* create structure */
3030 inout = calloc(1, sizeof *inout);
3031 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx), LY_EMEM);
3032 *inout_p = inout;
3033
3034 /* parse substatements */
3035 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3036 YANG_ERR_RET(ret);
3037
3038 switch (kw) {
3039 case YANG_ANYDATA:
3040 case YANG_ANYXML:
3041 ret = parse_any(ctx, data, kw, &inout->data);
3042 break;
3043 case YANG_CHOICE:
3044 ret = parse_choice(ctx, data, &inout->data);
3045 break;
3046 case YANG_CONTAINER:
3047 ret = parse_container(ctx, data, &inout->data);
3048 break;
3049 case YANG_LEAF:
3050 ret = parse_leaf(ctx, data, &inout->data);
3051 break;
3052 case YANG_LEAF_LIST:
3053 ret = parse_leaflist(ctx, data, &inout->data);
3054 break;
3055 case YANG_LIST:
3056 ret = parse_list(ctx, data, &inout->data);
3057 break;
3058 case YANG_USES:
3059 ret = parse_uses(ctx, data, &inout->data);
3060 break;
3061
3062 case YANG_TYPEDEF:
3063 ret = parse_typedef(ctx, data, &inout->typedefs);
3064 break;
3065 case YANG_MUST:
3066 ret = parse_restrs(ctx, data, kw, &inout->musts);
3067 break;
3068 case YANG_GROUPING:
3069 ret = parse_grouping(ctx, data, &inout->groupings);
3070 break;
3071 case YANG_CUSTOM:
3072 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts);
3073 break;
3074 default:
3075 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "input/output");
3076 return LY_EVALID;
3077 }
3078 YANG_ERR_RET(ret);
3079 }
3080 YANG_ERR_RET(ret);
3081
3082 return ret;
3083}
3084
3085static LY_ERR
3086parse_action(struct ly_ctx *ctx, const char **data, struct lysp_action **actions)
3087{
3088 LY_ERR ret = 0;
3089 char *buf, *word;
3090 int word_len;
3091 enum yang_keyword kw;
3092 struct lysp_action *act;
3093
3094 LYSP_ARRAY_NEW_RET(ctx, actions, act, LY_EMEM);
3095
3096 /* get value */
3097 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
3098 YANG_ERR_RET(ret);
3099
3100 if (buf) {
3101 act->name = lydict_insert_zc(ctx, word);
3102 } else {
3103 act->name = lydict_insert(ctx, word, word_len);
3104 }
3105
3106 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3107 YANG_ERR_RET(ret);
3108
3109 switch (kw) {
3110 case YANG_DESCRIPTION:
3111 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts);
3112 break;
3113 case YANG_IF_FEATURE:
3114 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts);
3115 break;
3116 case YANG_REFERENCE:
3117 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts);
3118 break;
3119 case YANG_STATUS:
3120 ret = parse_status(ctx, data, &act->flags, &act->exts);
3121 break;
3122
3123 case YANG_INPUT:
3124 ret = parse_inout(ctx, data, kw, &act->input);
3125 break;
3126 case YANG_OUTPUT:
3127 ret = parse_inout(ctx, data, kw, &act->output);
3128 break;
3129
3130 case YANG_TYPEDEF:
3131 ret = parse_typedef(ctx, data, &act->typedefs);
3132 break;
3133 case YANG_GROUPING:
3134 ret = parse_grouping(ctx, data, &act->groupings);
3135 break;
3136 case YANG_CUSTOM:
3137 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts);
3138 break;
3139 default:
3140 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "action");
3141 return LY_EVALID;
3142 }
3143 YANG_ERR_RET(ret);
3144 }
3145 YANG_ERR_RET(ret);
3146
3147 return ret;
3148}
3149
3150static LY_ERR
3151parse_notif(struct ly_ctx *ctx, const char **data, struct lysp_notif **notifs)
3152{
3153 LY_ERR ret = 0;
3154 char *buf, *word;
3155 int word_len;
3156 enum yang_keyword kw;
3157 struct lysp_notif *notif;
3158
3159 LYSP_ARRAY_NEW_RET(ctx, notifs, notif, LY_EMEM);
3160
3161 /* get value */
3162 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
3163 YANG_ERR_RET(ret);
3164
3165 if (buf) {
3166 notif->name = lydict_insert_zc(ctx, word);
3167 } else {
3168 notif->name = lydict_insert(ctx, word, word_len);
3169 }
3170
3171 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3172 YANG_ERR_RET(ret);
3173
3174 switch (kw) {
3175 case YANG_DESCRIPTION:
3176 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts);
3177 break;
3178 case YANG_IF_FEATURE:
3179 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts);
3180 break;
3181 case YANG_REFERENCE:
3182 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts);
3183 break;
3184 case YANG_STATUS:
3185 ret = parse_status(ctx, data, &notif->flags, &notif->exts);
3186 break;
3187
3188 case YANG_ANYDATA:
3189 case YANG_ANYXML:
3190 ret = parse_any(ctx, data, kw, &notif->data);
3191 break;
3192 case YANG_CHOICE:
3193 ret = parse_case(ctx, data, &notif->data);
3194 break;
3195 case YANG_CONTAINER:
3196 ret = parse_container(ctx, data, &notif->data);
3197 break;
3198 case YANG_LEAF:
3199 ret = parse_leaf(ctx, data, &notif->data);
3200 break;
3201 case YANG_LEAF_LIST:
3202 ret = parse_leaflist(ctx, data, &notif->data);
3203 break;
3204 case YANG_LIST:
3205 ret = parse_list(ctx, data, &notif->data);
3206 break;
3207 case YANG_USES:
3208 ret = parse_uses(ctx, data, &notif->data);
3209 break;
3210
3211 case YANG_MUST:
3212 ret = parse_restrs(ctx, data, kw, &notif->musts);
3213 break;
3214 case YANG_TYPEDEF:
3215 ret = parse_typedef(ctx, data, &notif->typedefs);
3216 break;
3217 case YANG_GROUPING:
3218 ret = parse_grouping(ctx, data, &notif->groupings);
3219 break;
3220 case YANG_CUSTOM:
3221 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts);
3222 break;
3223 default:
3224 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "notification");
3225 return LY_EVALID;
3226 }
3227 YANG_ERR_RET(ret);
3228 }
3229 YANG_ERR_RET(ret);
3230
3231 return ret;
3232}
3233
3234static LY_ERR
3235parse_grouping(struct ly_ctx *ctx, const char **data, struct lysp_grp **groupings)
3236{
3237 LY_ERR ret = 0;
3238 char *buf, *word;
3239 int word_len;
3240 enum yang_keyword kw;
3241 struct lysp_grp *grp;
3242
3243 LYSP_ARRAY_NEW_RET(ctx, groupings, grp, LY_EMEM);
3244
3245 /* get value */
3246 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
3247 YANG_ERR_RET(ret);
3248
3249 if (buf) {
3250 grp->name = lydict_insert_zc(ctx, word);
3251 } else {
3252 grp->name = lydict_insert(ctx, word, word_len);
3253 }
3254
3255 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3256 YANG_ERR_RET(ret);
3257
3258 switch (kw) {
3259 case YANG_DESCRIPTION:
3260 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts);
3261 break;
3262 case YANG_REFERENCE:
3263 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts);
3264 break;
3265 case YANG_STATUS:
3266 ret = parse_status(ctx, data, &grp->flags, &grp->exts);
3267 break;
3268
3269 case YANG_ANYDATA:
3270 case YANG_ANYXML:
3271 ret = parse_any(ctx, data, kw, &grp->data);
3272 break;
3273 case YANG_CHOICE:
3274 ret = parse_choice(ctx, data, &grp->data);
3275 break;
3276 case YANG_CONTAINER:
3277 ret = parse_container(ctx, data, &grp->data);
3278 break;
3279 case YANG_LEAF:
3280 ret = parse_leaf(ctx, data, &grp->data);
3281 break;
3282 case YANG_LEAF_LIST:
3283 ret = parse_leaflist(ctx, data, &grp->data);
3284 break;
3285 case YANG_LIST:
3286 ret = parse_list(ctx, data, &grp->data);
3287 break;
3288 case YANG_USES:
3289 ret = parse_uses(ctx, data, &grp->data);
3290 break;
3291
3292 case YANG_TYPEDEF:
3293 ret = parse_typedef(ctx, data, &grp->typedefs);
3294 break;
3295 case YANG_ACTION:
3296 ret = parse_action(ctx, data, &grp->actions);
3297 break;
3298 case YANG_GROUPING:
3299 ret = parse_grouping(ctx, data, &grp->groupings);
3300 break;
3301 case YANG_NOTIFICATION:
3302 ret = parse_notif(ctx, data, &grp->notifs);
3303 break;
3304 case YANG_CUSTOM:
3305 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts);
3306 break;
3307 default:
3308 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "augment");
3309 return LY_EVALID;
3310 }
3311 YANG_ERR_RET(ret);
3312 }
3313 YANG_ERR_RET(ret);
3314
3315 return ret;
3316}
3317
3318static LY_ERR
3319parse_augment(struct ly_ctx *ctx, const char **data, struct lysp_augment **augments)
3320{
3321 LY_ERR ret = 0;
3322 char *buf, *word;
3323 int word_len;
3324 enum yang_keyword kw;
3325 struct lysp_augment *aug;
3326
3327 LYSP_ARRAY_NEW_RET(ctx, augments, aug, LY_EMEM);
3328
3329 /* get value */
3330 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
3331 YANG_ERR_RET(ret);
3332
3333 if (buf) {
3334 aug->nodeid = lydict_insert_zc(ctx, word);
3335 } else {
3336 aug->nodeid = lydict_insert(ctx, word, word_len);
3337 }
3338
3339 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3340 YANG_ERR_RET(ret);
3341
3342 switch (kw) {
3343 case YANG_DESCRIPTION:
3344 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts);
3345 break;
3346 case YANG_IF_FEATURE:
3347 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts);
3348 break;
3349 case YANG_REFERENCE:
3350 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts);
3351 break;
3352 case YANG_STATUS:
3353 ret = parse_status(ctx, data, &aug->flags, &aug->exts);
3354 break;
3355 case YANG_WHEN:
3356 ret = parse_when(ctx, data, &aug->when);
3357 break;
3358
3359 case YANG_ANYDATA:
3360 case YANG_ANYXML:
3361 ret = parse_any(ctx, data, kw, &aug->child);
3362 break;
3363 case YANG_CASE:
3364 ret = parse_case(ctx, data, &aug->child);
3365 break;
3366 case YANG_CHOICE:
3367 ret = parse_choice(ctx, data, &aug->child);
3368 break;
3369 case YANG_CONTAINER:
3370 ret = parse_container(ctx, data, &aug->child);
3371 break;
3372 case YANG_LEAF:
3373 ret = parse_leaf(ctx, data, &aug->child);
3374 break;
3375 case YANG_LEAF_LIST:
3376 ret = parse_leaflist(ctx, data, &aug->child);
3377 break;
3378 case YANG_LIST:
3379 ret = parse_list(ctx, data, &aug->child);
3380 break;
3381 case YANG_USES:
3382 ret = parse_uses(ctx, data, &aug->child);
3383 break;
3384
3385 case YANG_ACTION:
3386 ret = parse_action(ctx, data, &aug->actions);
3387 break;
3388 case YANG_NOTIFICATION:
3389 ret = parse_notif(ctx, data, &aug->notifs);
3390 break;
3391 case YANG_CUSTOM:
3392 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts);
3393 break;
3394 default:
3395 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "augment");
3396 return LY_EVALID;
3397 }
3398 YANG_ERR_RET(ret);
3399 }
3400 YANG_ERR_RET(ret);
3401
3402 return ret;
3403}
3404
3405static LY_ERR
3406parse_uses(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
3407{
3408 LY_ERR ret = 0;
3409 char *buf, *word;
3410 int word_len;
3411 enum yang_keyword kw;
3412 struct lysp_node *iter;
3413 struct lysp_node_uses *uses;
3414
3415 /* create structure */
3416 uses = calloc(1, sizeof *uses);
3417 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx), LY_EMEM);
3418 uses->nodetype = LYS_USES;
3419
3420 /* insert into siblings */
3421 if (!*siblings) {
3422 *siblings = (struct lysp_node *)uses;
3423 } else {
3424 for (iter = *siblings; iter->next; iter = iter->next);
3425 iter->next = (struct lysp_node *)uses;
3426 }
3427
3428 /* get name */
3429 ret = get_string(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
3430 YANG_ERR_RET(ret);
3431
3432 if (buf) {
3433 uses->name = lydict_insert_zc(ctx, word);
3434 } else {
3435 uses->name = lydict_insert(ctx, word, word_len);
3436 }
3437
3438 /* parse substatements */
3439 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3440 YANG_ERR_RET(ret);
3441
3442 switch (kw) {
3443 case YANG_DESCRIPTION:
3444 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts);
3445 break;
3446 case YANG_IF_FEATURE:
3447 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts);
3448 break;
3449 case YANG_REFERENCE:
3450 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts);
3451 break;
3452 case YANG_STATUS:
3453 ret = parse_status(ctx, data, &uses->flags, &uses->exts);
3454 break;
3455 case YANG_WHEN:
3456 ret = parse_when(ctx, data, &uses->when);
3457 break;
3458
3459 case YANG_REFINE:
3460 ret = parse_refine(ctx, data, &uses->refines);
3461 break;
3462 case YANG_AUGMENT:
3463 ret = parse_augment(ctx, data, &uses->augments);
3464 break;
3465 case YANG_CUSTOM:
3466 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts);
3467 break;
3468 default:
3469 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "uses");
3470 return LY_EVALID;
3471 }
3472 YANG_ERR_RET(ret);
3473 }
3474 YANG_ERR_RET(ret);
3475
3476 return ret;
3477}
3478
3479static LY_ERR
3480parse_case(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
3481{
3482 LY_ERR ret = 0;
3483 char *buf, *word;
3484 int word_len;
3485 enum yang_keyword kw;
3486 struct lysp_node *iter;
3487 struct lysp_node_case *cas;
3488
3489 /* create structure */
3490 cas = calloc(1, sizeof *cas);
3491 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx), LY_EMEM);
3492 cas->nodetype = LYS_CASE;
3493
3494 /* insert into siblings */
3495 if (!*siblings) {
3496 *siblings = (struct lysp_node *)cas;
3497 } else {
3498 for (iter = *siblings; iter->next; iter = iter->next);
3499 iter->next = (struct lysp_node *)cas;
3500 }
3501
3502 /* get name */
3503 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
3504 YANG_ERR_RET(ret);
3505
3506 if (buf) {
3507 cas->name = lydict_insert_zc(ctx, word);
3508 } else {
3509 cas->name = lydict_insert(ctx, word, word_len);
3510 }
3511
3512 /* parse substatements */
3513 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3514 YANG_ERR_RET(ret);
3515
3516 switch (kw) {
3517 case YANG_DESCRIPTION:
3518 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts);
3519 break;
3520 case YANG_IF_FEATURE:
3521 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts);
3522 break;
3523 case YANG_REFERENCE:
3524 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts);
3525 break;
3526 case YANG_STATUS:
3527 ret = parse_status(ctx, data, &cas->flags, &cas->exts);
3528 break;
3529 case YANG_WHEN:
3530 ret = parse_when(ctx, data, &cas->when);
3531 break;
3532
3533 case YANG_ANYDATA:
3534 case YANG_ANYXML:
3535 ret = parse_any(ctx, data, kw, &cas->child);
3536 break;
3537 case YANG_CHOICE:
3538 ret = parse_case(ctx, data, &cas->child);
3539 break;
3540 case YANG_CONTAINER:
3541 ret = parse_container(ctx, data, &cas->child);
3542 break;
3543 case YANG_LEAF:
3544 ret = parse_leaf(ctx, data, &cas->child);
3545 break;
3546 case YANG_LEAF_LIST:
3547 ret = parse_leaflist(ctx, data, &cas->child);
3548 break;
3549 case YANG_LIST:
3550 ret = parse_list(ctx, data, &cas->child);
3551 break;
3552 case YANG_USES:
3553 ret = parse_uses(ctx, data, &cas->child);
3554 break;
3555 case YANG_CUSTOM:
3556 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts);
3557 break;
3558 default:
3559 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "case");
3560 return LY_EVALID;
3561 }
3562 YANG_ERR_RET(ret);
3563 }
3564 YANG_ERR_RET(ret);
3565
3566 return ret;
3567}
3568
3569static LY_ERR
3570parse_choice(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
3571{
3572 LY_ERR ret = 0;
3573 char *buf, *word;
3574 int word_len;
3575 enum yang_keyword kw;
3576 struct lysp_node *iter;
3577 struct lysp_node_choice *choic;
3578
3579 /* create structure */
3580 choic = calloc(1, sizeof *choic);
3581 LY_CHECK_ERR_RET(!choic, LOGMEM(ctx), LY_EMEM);
3582 choic->nodetype = LYS_CHOICE;
3583
3584 /* insert into siblings */
3585 if (!*siblings) {
3586 *siblings = (struct lysp_node *)choic;
3587 } else {
3588 for (iter = *siblings; iter->next; iter = iter->next);
3589 iter->next = (struct lysp_node *)choic;
3590 }
3591
3592 /* get name */
3593 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
3594 YANG_ERR_RET(ret);
3595
3596 if (buf) {
3597 choic->name = lydict_insert_zc(ctx, word);
3598 } else {
3599 choic->name = lydict_insert(ctx, word, word_len);
3600 }
3601
3602 /* parse substatements */
3603 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3604 YANG_ERR_RET(ret);
3605
3606 switch (kw) {
3607 case YANG_CONFIG:
3608 ret = parse_config(ctx, data, &choic->flags, &choic->exts);
3609 break;
3610 case YANG_DESCRIPTION:
3611 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choic->dsc, Y_STR_ARG, &choic->exts);
3612 break;
3613 case YANG_IF_FEATURE:
3614 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choic->iffeatures, Y_STR_ARG, &choic->exts);
3615 break;
3616 case YANG_MANDATORY:
3617 ret = parse_mandatory(ctx, data, &choic->flags, &choic->exts);
3618 break;
3619 case YANG_REFERENCE:
3620 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choic->ref, Y_STR_ARG, &choic->exts);
3621 break;
3622 case YANG_STATUS:
3623 ret = parse_status(ctx, data, &choic->flags, &choic->exts);
3624 break;
3625 case YANG_WHEN:
3626 ret = parse_when(ctx, data, &choic->when);
3627 break;
3628 case YANG_DEFAULT:
3629 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choic->dflt, Y_IDENTIF_ARG, &choic->exts);
3630 break;
3631
3632 case YANG_ANYDATA:
3633 case YANG_ANYXML:
3634 ret = parse_any(ctx, data, kw, &choic->child);
3635 break;
3636 case YANG_CASE:
3637 ret = parse_case(ctx, data, &choic->child);
3638 break;
3639 case YANG_CHOICE:
3640 ret = parse_choice(ctx, data, &choic->child);
3641 break;
3642 case YANG_CONTAINER:
3643 ret = parse_container(ctx, data, &choic->child);
3644 break;
3645 case YANG_LEAF:
3646 ret = parse_leaf(ctx, data, &choic->child);
3647 break;
3648 case YANG_LEAF_LIST:
3649 ret = parse_leaflist(ctx, data, &choic->child);
3650 break;
3651 case YANG_LIST:
3652 ret = parse_list(ctx, data, &choic->child);
3653 break;
3654 case YANG_CUSTOM:
3655 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choic->exts);
3656 break;
3657 default:
3658 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "choice");
3659 return LY_EVALID;
3660 }
3661 YANG_ERR_RET(ret);
3662 }
3663 YANG_ERR_RET(ret);
3664
3665 return ret;
3666}
3667
3668static LY_ERR
3669parse_container(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
3670{
3671 LY_ERR ret = 0;
3672 char *buf, *word;
3673 int word_len;
3674 enum yang_keyword kw;
3675 struct lysp_node *iter;
3676 struct lysp_node_container *cont;
3677
3678 /* create structure */
3679 cont = calloc(1, sizeof *cont);
3680 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx), LY_EMEM);
3681 cont->nodetype = LYS_CONTAINER;
3682
3683 /* insert into siblings */
3684 if (!*siblings) {
3685 *siblings = (struct lysp_node *)cont;
3686 } else {
3687 for (iter = *siblings; iter->next; iter = iter->next);
3688 iter->next = (struct lysp_node *)cont;
3689 }
3690
3691 /* get name */
3692 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
3693 YANG_ERR_RET(ret);
3694
3695 if (buf) {
3696 cont->name = lydict_insert_zc(ctx, word);
3697 } else {
3698 cont->name = lydict_insert(ctx, word, word_len);
3699 }
3700
3701 /* parse substatements */
3702 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3703 YANG_ERR_RET(ret);
3704
3705 switch (kw) {
3706 case YANG_CONFIG:
3707 ret = parse_config(ctx, data, &cont->flags, &cont->exts);
3708 break;
3709 case YANG_DESCRIPTION:
3710 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts);
3711 break;
3712 case YANG_IF_FEATURE:
3713 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts);
3714 break;
3715 case YANG_REFERENCE:
3716 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts);
3717 break;
3718 case YANG_STATUS:
3719 ret = parse_status(ctx, data, &cont->flags, &cont->exts);
3720 break;
3721 case YANG_WHEN:
3722 ret = parse_when(ctx, data, &cont->when);
3723 break;
3724 case YANG_PRESENCE:
3725 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts);
3726 break;
3727
3728 case YANG_ANYDATA:
3729 case YANG_ANYXML:
3730 ret = parse_any(ctx, data, kw, &cont->child);
3731 break;
3732 case YANG_CHOICE:
3733 ret = parse_choice(ctx, data, &cont->child);
3734 break;
3735 case YANG_CONTAINER:
3736 ret = parse_container(ctx, data, &cont->child);
3737 break;
3738 case YANG_LEAF:
3739 ret = parse_leaf(ctx, data, &cont->child);
3740 break;
3741 case YANG_LEAF_LIST:
3742 ret = parse_leaflist(ctx, data, &cont->child);
3743 break;
3744 case YANG_LIST:
3745 ret = parse_list(ctx, data, &cont->child);
3746 break;
3747 case YANG_USES:
3748 ret = parse_uses(ctx, data, &cont->child);
3749 break;
3750
3751 case YANG_TYPEDEF:
3752 ret = parse_typedef(ctx, data, &cont->typedefs);
3753 break;
3754 case YANG_MUST:
3755 ret = parse_restrs(ctx, data, kw, &cont->musts);
3756 break;
3757 case YANG_ACTION:
3758 ret = parse_action(ctx, data, &cont->actions);
3759 break;
3760 case YANG_GROUPING:
3761 ret = parse_grouping(ctx, data, &cont->groupings);
3762 break;
3763 case YANG_NOTIFICATION:
3764 ret = parse_notif(ctx, data, &cont->notifs);
3765 break;
3766 case YANG_CUSTOM:
3767 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts);
3768 break;
3769 default:
3770 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "container");
3771 return LY_EVALID;
3772 }
3773 YANG_ERR_RET(ret);
3774 }
3775 YANG_ERR_RET(ret);
3776
3777 return ret;
3778}
3779
3780static LY_ERR
3781parse_list(struct ly_ctx *ctx, const char **data, struct lysp_node **siblings)
3782{
3783 LY_ERR ret = 0;
3784 char *buf, *word;
3785 int word_len;
3786 enum yang_keyword kw;
3787 struct lysp_node *iter;
3788 struct lysp_node_list *list;
3789
3790 /* create structure */
3791 list = calloc(1, sizeof *list);
3792 LY_CHECK_ERR_RET(!list, LOGMEM(ctx), LY_EMEM);
3793 list->nodetype = LYS_LIST;
3794
3795 /* insert into siblings */
3796 if (!*siblings) {
3797 *siblings = (struct lysp_node *)list;
3798 } else {
3799 for (iter = *siblings; iter->next; iter = iter->next);
3800 iter->next = (struct lysp_node *)list;
3801 }
3802
3803 /* get name */
3804 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
3805 YANG_ERR_RET(ret);
3806
3807 if (buf) {
3808 list->name = lydict_insert_zc(ctx, word);
3809 } else {
3810 list->name = lydict_insert(ctx, word, word_len);
3811 }
3812
3813 /* parse substatements */
3814 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3815 YANG_ERR_RET(ret);
3816
3817 switch (kw) {
3818 case YANG_CONFIG:
3819 ret = parse_config(ctx, data, &list->flags, &list->exts);
3820 break;
3821 case YANG_DESCRIPTION:
3822 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts);
3823 break;
3824 case YANG_IF_FEATURE:
3825 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts);
3826 break;
3827 case YANG_REFERENCE:
3828 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts);
3829 break;
3830 case YANG_STATUS:
3831 ret = parse_status(ctx, data, &list->flags, &list->exts);
3832 break;
3833 case YANG_WHEN:
3834 ret = parse_when(ctx, data, &list->when);
3835 break;
3836 case YANG_KEY:
3837 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts);
3838 break;
3839 case YANG_MAX_ELEMENTS:
3840 ret = parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts);
3841 break;
3842 case YANG_MIN_ELEMENTS:
3843 ret = parse_minelements(ctx, data, &list->min, &list->flags, &list->exts);
3844 break;
3845 case YANG_ORDERED_BY:
3846 ret = parse_orderedby(ctx, data, &list->flags, &list->exts);
3847 break;
3848 case YANG_UNIQUE:
3849 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts);
3850 break;
3851
3852 case YANG_ANYDATA:
3853 case YANG_ANYXML:
3854 ret = parse_any(ctx, data, kw, &list->child);
3855 break;
3856 case YANG_CHOICE:
3857 ret = parse_choice(ctx, data, &list->child);
3858 break;
3859 case YANG_CONTAINER:
3860 ret = parse_container(ctx, data, &list->child);
3861 break;
3862 case YANG_LEAF:
3863 ret = parse_leaf(ctx, data, &list->child);
3864 break;
3865 case YANG_LEAF_LIST:
3866 ret = parse_leaflist(ctx, data, &list->child);
3867 break;
3868 case YANG_LIST:
3869 ret = parse_list(ctx, data, &list->child);
3870 break;
3871 case YANG_USES:
3872 ret = parse_uses(ctx, data, &list->child);
3873 break;
3874
3875 case YANG_TYPEDEF:
3876 ret = parse_typedef(ctx, data, &list->typedefs);
3877 break;
3878 case YANG_MUST:
3879 ret = parse_restrs(ctx, data, kw, &list->musts);
3880 break;
3881 case YANG_ACTION:
3882 ret = parse_action(ctx, data, &list->actions);
3883 break;
3884 case YANG_GROUPING:
3885 ret = parse_grouping(ctx, data, &list->groupings);
3886 break;
3887 case YANG_NOTIFICATION:
3888 ret = parse_notif(ctx, data, &list->notifs);
3889 break;
3890 case YANG_CUSTOM:
3891 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts);
3892 break;
3893 default:
3894 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "container");
3895 return LY_EVALID;
3896 }
3897 YANG_ERR_RET(ret);
3898 }
3899 YANG_ERR_RET(ret);
3900
3901 return ret;
3902}
3903
3904static LY_ERR
3905parse_yinelement(struct ly_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
3906{
3907 LY_ERR ret = 0;
3908 char *buf, *word;
3909 int word_len;
3910 enum yang_keyword kw;
3911
3912 if (*flags & LYS_YINELEM_MASK) {
3913 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "yin-element");
3914 return LY_EVALID;
3915 }
3916
3917 /* get value */
3918 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
3919 YANG_ERR_RET(ret);
3920
3921 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3922 *flags |= LYS_YINELEM_TRUE;
3923 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3924 *flags |= LYS_YINELEM_FALSE;
3925 } else {
3926 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "yin-element");
3927 free(buf);
3928 return LY_EVALID;
3929 }
3930 free(buf);
3931
3932 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3933 YANG_ERR_RET(ret);
3934
3935 switch (kw) {
3936 case YANG_CUSTOM:
3937 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts);
3938 YANG_ERR_RET(ret);
3939 break;
3940 default:
3941 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "yin-element");
3942 return LY_EVALID;
3943 }
3944 }
3945 YANG_ERR_RET(ret);
3946
3947 return ret;
3948}
3949
3950static LY_ERR
3951parse_argument(struct ly_ctx *ctx, const char **data, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
3952{
3953 LY_ERR ret = 0;
3954 char *buf, *word;
3955 int word_len;
3956 enum yang_keyword kw;
3957
3958 if (*argument) {
3959 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_DUPSTMT, "argument");
3960 return LY_EVALID;
3961 }
3962
3963 /* get value */
3964 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
3965 YANG_ERR_RET(ret);
3966
3967 if (buf) {
3968 *argument = lydict_insert_zc(ctx, word);
3969 } else {
3970 *argument = lydict_insert(ctx, word, word_len);
3971 }
3972
3973 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
3974 YANG_ERR_RET(ret);
3975
3976 switch (kw) {
3977 case YANG_YIN_ELEMENT:
3978 ret = parse_yinelement(ctx, data, flags, exts);
3979 break;
3980 case YANG_CUSTOM:
3981 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts);
3982 break;
3983 default:
3984 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "argument");
3985 return LY_EVALID;
3986 }
3987 YANG_ERR_RET(ret);
3988 }
3989 YANG_ERR_RET(ret);
3990
3991 return ret;
3992}
3993
3994static LY_ERR
3995parse_extension(struct ly_ctx *ctx, const char **data, struct lysp_ext **extensions)
3996{
3997 LY_ERR ret = 0;
3998 char *buf, *word;
3999 int word_len;
4000 enum yang_keyword kw;
4001 struct lysp_ext *ex;
4002
4003 LYSP_ARRAY_NEW_RET(ctx, extensions, ex, LY_EMEM);
4004
4005 /* get value */
4006 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
4007 YANG_ERR_RET(ret);
4008
4009 if (buf) {
4010 ex->name = lydict_insert_zc(ctx, word);
4011 } else {
4012 ex->name = lydict_insert(ctx, word, word_len);
4013 }
4014
4015 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
4016 YANG_ERR_RET(ret);
4017
4018 switch (kw) {
4019 case YANG_DESCRIPTION:
4020 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts);
4021 break;
4022 case YANG_REFERENCE:
4023 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts);
4024 break;
4025 case YANG_STATUS:
4026 ret = parse_status(ctx, data, &ex->flags, &ex->exts);
4027 break;
4028 case YANG_ARGUMENT:
4029 ret = parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts);
4030 break;
4031 case YANG_CUSTOM:
4032 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts);
4033 break;
4034 default:
4035 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "extension");
4036 return LY_EVALID;
4037 }
4038 YANG_ERR_RET(ret);
4039 }
4040 YANG_ERR_RET(ret);
4041
4042 return ret;
4043}
4044
4045static LY_ERR
4046parse_deviate(struct ly_ctx *ctx, const char **data, struct lysp_deviate **deviates)
4047{
4048 LY_ERR ret = 0;
4049 char *buf, *word;
4050 int word_len, dev_mod;
4051 enum yang_keyword kw;
4052 struct lysp_deviate *iter, *d;
4053 struct lysp_deviate_add *d_add = NULL;
4054 struct lysp_deviate_rpl *d_rpl = NULL;
4055 struct lysp_deviate_del *d_del = NULL;
4056 const char **d_units, ***d_uniques, ***d_dflts;
4057 struct lysp_restr **d_musts;
4058 uint16_t *d_flags;
4059 uint32_t *d_min, *d_max;
4060
4061 /* get value */
4062 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
4063 YANG_ERR_RET(ret);
4064
4065 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4066 dev_mod = LYS_DEV_NOT_SUPPORTED;
4067 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4068 dev_mod = LYS_DEV_ADD;
4069 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4070 dev_mod = LYS_DEV_REPLACE;
4071 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4072 dev_mod = LYS_DEV_DELETE;
4073 } else {
4074 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, word_len, word, "deviate");
4075 free(buf);
4076 return LY_EVALID;
4077 }
4078 free(buf);
4079
4080 /* create structure */
4081 switch (dev_mod) {
4082 case LYS_DEV_NOT_SUPPORTED:
4083 d = calloc(1, sizeof *d);
4084 LY_CHECK_ERR_RET(!d, LOGMEM(ctx), LY_EMEM);
4085 break;
4086 case LYS_DEV_ADD:
4087 d_add = calloc(1, sizeof *d_add);
4088 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx), LY_EMEM);
4089 d = (struct lysp_deviate *)d_add;
4090 d_units = &d_add->units;
4091 d_uniques = &d_add->uniques;
4092 d_dflts = &d_add->dflts;
4093 d_musts = &d_add->musts;
4094 d_flags = &d_add->flags;
4095 d_min = &d_add->min;
4096 d_max = &d_add->max;
4097 break;
4098 case LYS_DEV_REPLACE:
4099 d_rpl = calloc(1, sizeof *d_rpl);
4100 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx), LY_EMEM);
4101 d = (struct lysp_deviate *)d_rpl;
4102 d_units = &d_rpl->units;
4103 d_flags = &d_rpl->flags;
4104 d_min = &d_rpl->min;
4105 d_max = &d_rpl->max;
4106 break;
4107 case LYS_DEV_DELETE:
4108 d_del = calloc(1, sizeof *d_del);
4109 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx), LY_EMEM);
4110 d = (struct lysp_deviate *)d_del;
4111 d_units = &d_del->units;
4112 d_uniques = &d_del->uniques;
4113 d_dflts = &d_del->dflts;
4114 d_musts = &d_del->musts;
4115 d_flags = &d_del->flags;
4116 d_min = &d_del->min;
4117 d_max = &d_del->max;
4118 break;
4119 default:
4120 assert(0);
4121 LOGINT_RET(ctx);
4122 }
4123 d->mod = dev_mod;
4124
4125 /* insert into siblings */
4126 if (!*deviates) {
4127 *deviates = d;
4128 } else {
4129 for (iter = *deviates; iter->next; iter = iter->next);
4130 iter->next = d;
4131 }
4132
4133 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
4134 YANG_ERR_RET(ret);
4135
4136 switch (kw) {
4137 case YANG_CONFIG:
4138 switch (dev_mod) {
4139 case LYS_DEV_NOT_SUPPORTED:
4140 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, devmod2str(dev_mod), kw2str(kw));
4141 return LY_EVALID;
4142 default:
4143 ret = parse_config(ctx, data, d_flags, &d->exts);
4144 break;
4145 }
4146 break;
4147 case YANG_DEFAULT:
4148 switch (dev_mod) {
4149 case LYS_DEV_NOT_SUPPORTED:
4150 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, devmod2str(dev_mod), kw2str(kw));
4151 return LY_EVALID;
4152 case LYS_DEV_REPLACE:
4153 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts);
4154 break;
4155 default:
4156 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts);
4157 break;
4158 }
4159 break;
4160 case YANG_MANDATORY:
4161 switch (dev_mod) {
4162 case LYS_DEV_NOT_SUPPORTED:
4163 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, devmod2str(dev_mod), kw2str(kw));
4164 return LY_EVALID;
4165 default:
4166 ret = parse_mandatory(ctx, data, d_flags, &d->exts);
4167 break;
4168 }
4169 break;
4170 case YANG_MAX_ELEMENTS:
4171 switch (dev_mod) {
4172 case LYS_DEV_NOT_SUPPORTED:
4173 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, devmod2str(dev_mod), kw2str(kw));
4174 return LY_EVALID;
4175 default:
4176 ret = parse_maxelements(ctx, data, d_max, d_flags, &d->exts);
4177 break;
4178 }
4179 break;
4180 case YANG_MIN_ELEMENTS:
4181 switch (dev_mod) {
4182 case LYS_DEV_NOT_SUPPORTED:
4183 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, devmod2str(dev_mod), kw2str(kw));
4184 return LY_EVALID;
4185 default:
4186 ret = parse_minelements(ctx, data, d_min, d_flags, &d->exts);
4187 break;
4188 }
4189 break;
4190 case YANG_MUST:
4191 switch (dev_mod) {
4192 case LYS_DEV_NOT_SUPPORTED:
4193 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, devmod2str(dev_mod), kw2str(kw));
4194 return LY_EVALID;
4195 default:
4196 ret = parse_restrs(ctx, data, kw, d_musts);
4197 break;
4198 }
4199 break;
4200 case YANG_TYPE:
4201 switch (dev_mod) {
4202 case LYS_DEV_NOT_SUPPORTED:
4203 case LYS_DEV_ADD:
4204 case LYS_DEV_DELETE:
4205 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, devmod2str(dev_mod), kw2str(kw));
4206 return LY_EVALID;
4207 default:
4208 d_rpl->type = calloc(1, sizeof *d_rpl->type);
4209 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx), LY_EMEM);
4210 ret = parse_type(ctx, data, d_rpl->type);
4211 break;
4212 }
4213 break;
4214 case YANG_UNIQUE:
4215 switch (dev_mod) {
4216 case LYS_DEV_NOT_SUPPORTED:
4217 case LYS_DEV_REPLACE:
4218 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, devmod2str(dev_mod), kw2str(kw));
4219 return LY_EVALID;
4220 default:
4221 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts);
4222 break;
4223 }
4224 break;
4225 case YANG_UNITS:
4226 switch (dev_mod) {
4227 case LYS_DEV_NOT_SUPPORTED:
4228 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INDEV, devmod2str(dev_mod), kw2str(kw));
4229 return LY_EVALID;
4230 default:
4231 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts);
4232 break;
4233 }
4234 break;
4235 case YANG_CUSTOM:
4236 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts);
4237 break;
4238 default:
4239 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "deviate");
4240 return LY_EVALID;
4241 }
4242 YANG_ERR_RET(ret);
4243 }
4244 YANG_ERR_RET(ret);
4245
4246 return ret;
4247}
4248
4249static LY_ERR
4250parse_deviation(struct ly_ctx *ctx, const char **data, struct lysp_deviation **deviations)
4251{
4252 LY_ERR ret = 0;
4253 char *buf, *word;
4254 int word_len;
4255 enum yang_keyword kw;
4256 struct lysp_deviation *dev;
4257
4258 LYSP_ARRAY_NEW_RET(ctx, deviations, dev, LY_EMEM);
4259
4260 /* get value */
4261 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
4262 YANG_ERR_RET(ret);
4263
4264 if (buf) {
4265 dev->nodeid = lydict_insert_zc(ctx, word);
4266 } else {
4267 dev->nodeid = lydict_insert(ctx, word, word_len);
4268 }
4269
4270 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
4271 YANG_ERR_RET(ret);
4272
4273 switch (kw) {
4274 case YANG_DESCRIPTION:
4275 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts);
4276 break;
4277 case YANG_DEVIATE:
4278 ret = parse_deviate(ctx, data, &dev->deviates);
4279 break;
4280 case YANG_REFERENCE:
4281 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts);
4282 break;
4283 case YANG_CUSTOM:
4284 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts);
4285 break;
4286 default:
4287 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "deviation");
4288 return LY_EVALID;
4289 }
4290 YANG_ERR_RET(ret);
4291 }
4292 YANG_ERR_RET(ret);
4293
4294 /* mandatory substatements */
4295 if (!dev->deviates) {
4296 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "deviate", "deviation");
4297 return LY_EVALID;
4298 }
4299
4300 return ret;
4301}
4302
4303static LY_ERR
4304parse_feature(struct ly_ctx *ctx, const char **data, struct lysp_feature **features)
4305{
4306 LY_ERR ret = 0;
4307 char *buf, *word;
4308 int word_len;
4309 enum yang_keyword kw;
4310 struct lysp_feature *feat;
4311
4312 LYSP_ARRAY_NEW_RET(ctx, features, feat, LY_EMEM);
4313
4314 /* get value */
4315 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
4316 YANG_ERR_RET(ret);
4317
4318 if (buf) {
4319 feat->name = lydict_insert_zc(ctx, word);
4320 } else {
4321 feat->name = lydict_insert(ctx, word, word_len);
4322 }
4323
4324 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
4325 YANG_ERR_RET(ret);
4326
4327 switch (kw) {
4328 case YANG_DESCRIPTION:
4329 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts);
4330 break;
4331 case YANG_IF_FEATURE:
4332 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts);
4333 break;
4334 case YANG_REFERENCE:
4335 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts);
4336 break;
4337 case YANG_STATUS:
4338 ret = parse_status(ctx, data, &feat->flags, &feat->exts);
4339 break;
4340 case YANG_CUSTOM:
4341 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts);
4342 break;
4343 default:
4344 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "feature");
4345 return LY_EMEM;
4346 }
4347 YANG_ERR_RET(ret);
4348 }
4349 YANG_ERR_RET(ret);
4350
4351 return ret;
4352}
4353
4354static LY_ERR
4355parse_identity(struct ly_ctx *ctx, const char **data, struct lysp_ident **identities)
4356{
4357 LY_ERR ret = 0;
4358 char *buf, *word;
4359 int word_len;
4360 enum yang_keyword kw;
4361 struct lysp_ident *ident;
4362
4363 LYSP_ARRAY_NEW_RET(ctx, identities, ident, LY_EMEM);
4364
4365 /* get value */
4366 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
4367 YANG_ERR_RET(ret);
4368
4369 if (buf) {
4370 ident->name = lydict_insert_zc(ctx, word);
4371 } else {
4372 ident->name = lydict_insert(ctx, word, word_len);
4373 }
4374
4375 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
4376 YANG_ERR_RET(ret);
4377
4378 switch (kw) {
4379 case YANG_DESCRIPTION:
4380 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts);
4381 break;
4382 case YANG_IF_FEATURE:
4383 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts);
4384 break;
4385 case YANG_REFERENCE:
4386 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts);
4387 break;
4388 case YANG_STATUS:
4389 ret = parse_status(ctx, data, &ident->flags, &ident->exts);
4390 break;
4391 case YANG_BASE:
4392 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts);
4393 break;
4394 case YANG_CUSTOM:
4395 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts);
4396 break;
4397 default:
4398 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "identity");
4399 return LY_EVALID;
4400 }
4401 YANG_ERR_RET(ret);
4402 }
4403 YANG_ERR_RET(ret);
4404
4405 return ret;
4406}
4407
4408static LY_ERR
4409parse_sub_module(struct ly_ctx *ctx, const char **data, struct lysp_module *mod)
4410{
4411 LY_ERR ret = 0;
4412 char *buf, *word;
4413 int word_len;
4414 enum yang_keyword kw, prev_kw = 0;
4415 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4416
4417 /* (sub)module name */
4418 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
4419 YANG_ERR_RET(ret);
4420
4421 if (buf) {
4422 mod->name = lydict_insert_zc(ctx, word);
4423 } else {
4424 mod->name = lydict_insert(ctx, word, word_len);
4425 }
4426
4427 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
4428 YANG_ERR_RET(ret);
4429
4430 switch (kw) {
4431 /* module header */
4432 case YANG_NAMESPACE:
4433 case YANG_PREFIX:
4434 if (mod->submodule) {
4435 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "submodule");
4436 return LY_EVALID;
4437 }
4438 /* fallthrough */
4439 case YANG_BELONGS_TO:
4440 if ((kw == YANG_BELONGS_TO) && !mod->submodule) {
4441 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), "module");
4442 return LY_EVALID;
4443 }
4444 /* fallthrough */
4445 case YANG_YANG_VERSION:
4446 if (mod_stmt > Y_MOD_MODULE_HEADER) {
4447 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INORD, kw2str(kw), kw2str(prev_kw));
4448 return LY_EVALID;
4449 }
4450 break;
4451 /* linkage */
4452 case YANG_INCLUDE:
4453 case YANG_IMPORT:
4454 if (mod_stmt > Y_MOD_LINKAGE) {
4455 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INORD, kw2str(kw), kw2str(prev_kw));
4456 return LY_EVALID;
4457 }
4458 mod_stmt = Y_MOD_LINKAGE;
4459 break;
4460 /* meta */
4461 case YANG_ORGANIZATION:
4462 case YANG_CONTACT:
4463 case YANG_DESCRIPTION:
4464 case YANG_REFERENCE:
4465 if (mod_stmt > Y_MOD_META) {
4466 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INORD, kw2str(kw), kw2str(prev_kw));
4467 return LY_EVALID;
4468 }
4469 mod_stmt = Y_MOD_META;
4470 break;
4471
4472 /* revision */
4473 case YANG_REVISION:
4474 if (mod_stmt > Y_MOD_REVISION) {
4475 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INORD, kw2str(kw), kw2str(prev_kw));
4476 return LY_EVALID;
4477 }
4478 mod_stmt = Y_MOD_REVISION;
4479 break;
4480
4481 /* body */
4482 case YANG_ANYDATA:
4483 case YANG_ANYXML:
4484 case YANG_AUGMENT:
4485 case YANG_CHOICE:
4486 case YANG_CONTAINER:
4487 case YANG_DEVIATION:
4488 case YANG_EXTENSION:
4489 case YANG_FEATURE:
4490 case YANG_GROUPING:
4491 case YANG_IDENTITY:
4492 case YANG_LEAF:
4493 case YANG_LEAF_LIST:
4494 case YANG_LIST:
4495 case YANG_NOTIFICATION:
4496 case YANG_RPC:
4497 case YANG_TYPEDEF:
4498 case YANG_USES:
4499 case YANG_CUSTOM:
4500 mod_stmt = Y_MOD_BODY;
4501 break;
4502 default:
4503 /* error handled in the next switch */
4504 break;
4505 }
4506 prev_kw = kw;
4507
4508 switch (kw) {
4509 /* module header */
4510 case YANG_YANG_VERSION:
4511 ret = parse_yangversion(ctx, data, mod);
4512 break;
4513 case YANG_NAMESPACE:
4514 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts);
4515 break;
4516 case YANG_PREFIX:
4517 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts);
4518 break;
4519 case YANG_BELONGS_TO:
4520 ret = parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts);
4521 break;
4522
4523 /* linkage */
4524 case YANG_INCLUDE:
4525 ret = parse_include(ctx, data, &mod->includes);
4526 break;
4527 case YANG_IMPORT:
4528 ret = parse_import(ctx, data, &mod->imports);
4529 break;
4530
4531 /* meta */
4532 case YANG_ORGANIZATION:
4533 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts);
4534 break;
4535 case YANG_CONTACT:
4536 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts);
4537 break;
4538 case YANG_DESCRIPTION:
4539 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts);
4540 break;
4541 case YANG_REFERENCE:
4542 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts);
4543 break;
4544
4545 /* revision */
4546 case YANG_REVISION:
4547 ret = parse_revision(ctx, data, &mod->revs);
4548 break;
4549
4550 /* body */
4551 case YANG_ANYDATA:
4552 case YANG_ANYXML:
4553 ret = parse_any(ctx, data, kw, &mod->data);
4554 break;
4555 case YANG_CHOICE:
4556 ret = parse_choice(ctx, data, &mod->data);
4557 break;
4558 case YANG_CONTAINER:
4559 ret = parse_container(ctx, data, &mod->data);
4560 break;
4561 case YANG_LEAF:
4562 ret = parse_leaf(ctx, data, &mod->data);
4563 break;
4564 case YANG_LEAF_LIST:
4565 ret = parse_leaflist(ctx, data, &mod->data);
4566 break;
4567 case YANG_LIST:
4568 ret = parse_list(ctx, data, &mod->data);
4569 break;
4570 case YANG_USES:
4571 ret = parse_uses(ctx, data, &mod->data);
4572 break;
4573
4574 case YANG_AUGMENT:
4575 ret = parse_augment(ctx, data, &mod->augments);
4576 break;
4577 case YANG_DEVIATION:
4578 ret = parse_deviation(ctx, data, &mod->deviations);
4579 break;
4580 case YANG_EXTENSION:
4581 ret = parse_extension(ctx, data, &mod->extensions);
4582 break;
4583 case YANG_FEATURE:
4584 ret = parse_feature(ctx, data, &mod->features);
4585 break;
4586 case YANG_GROUPING:
4587 ret = parse_grouping(ctx, data, &mod->groupings);
4588 break;
4589 case YANG_IDENTITY:
4590 ret = parse_identity(ctx, data, &mod->identities);
4591 break;
4592 case YANG_NOTIFICATION:
4593 ret = parse_notif(ctx, data, &mod->notifs);
4594 break;
4595 case YANG_RPC:
4596 ret = parse_action(ctx, data, &mod->rpcs);
4597 break;
4598 case YANG_TYPEDEF:
4599 ret = parse_typedef(ctx, data, &mod->typedefs);
4600 break;
4601 case YANG_CUSTOM:
4602 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts);
4603 break;
4604
4605 default:
4606 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INCHILDSTMT, kw2str(kw), mod->submodule ? "submodule" : "module");
4607 return LY_EVALID;
4608 }
4609 YANG_ERR_RET(ret);
4610 }
4611 YANG_ERR_RET(ret);
4612
4613 /* mandatory substatements */
4614 if (mod->submodule) {
4615 if (!mod->belongsto) {
4616 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "belongs-to", "submodule");
4617 return LY_EVALID;
4618 }
4619 } else {
4620 if (!mod->ns) {
4621 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "namespace", "module");
4622 return LY_EVALID;
4623 } else if (!mod->prefix) {
4624 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_MISSTMT, "prefix", "module");
4625 return LY_EVALID;
4626 }
4627 }
4628
4629 return ret;
4630}
4631
4632static LY_ERR
4633yang_parse(struct ly_ctx *ctx, const char *data, struct lysp_module **mod_p)
4634{
4635 LY_ERR ret = 0;
4636 char *word, *buf;
4637 int word_len;
4638 const char *data_start;
4639 enum yang_keyword kw;
4640 struct lysp_module *mod;
4641
4642 data_start = data;
4643
4644 /* "module"/"submodule" */
4645 ret = get_keyword(ctx, &data, &kw, &word, &word_len);
4646 YANG_ERR_GOTO(ret, error);
4647
4648 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
4649 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".\n",
4650 kw2str(kw));
4651 goto error;
4652 }
4653
4654 mod = calloc(1, sizeof *mod);
4655 LY_CHECK_ERR_GOTO(!mod, LOGMEM(ctx), error);
4656 if (kw == YANG_SUBMODULE) {
4657 mod->submodule = 1;
4658 }
4659
4660 /* substatements */
4661 ret = parse_sub_module(ctx, &data, mod);
4662 YANG_ERR_GOTO(ret, error);
4663
4664 /* read some trailing spaces or new lines */
4665 ret = get_string(ctx, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4666 YANG_ERR_GOTO(ret, error);
4667
4668 if (word) {
4669 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
4670 word_len, word);
4671 free(buf);
4672 goto error;
4673 }
4674 assert(!buf);
4675
4676 *mod_p = mod;
4677 return ret;
4678
4679error:
4680 LOGERR(ctx, LY_EINVAL, "Module parsing failed on line %d.", lysp_get_data_line(data_start, data - data_start));
4681 /* TODO free module */
4682 return ret;
4683}
4684
4685int
4686main(int argc, char **argv)
4687{
4688 char *data = NULL;
4689 int fd = -1;
4690 struct stat st;
4691 struct lysp_module *mod;
4692 struct ly_ctx *ctx = NULL;
4693
4694 if (argc != 2) {
4695 fprintf(stderr, "No arguments specified.\n");
4696 goto cleanup;
4697 }
4698
4699 ly_verb(LY_LLERR);
4700
4701 if (ly_ctx_new(NULL, 0, &ctx)) {
4702 fprintf(stderr, "ly_ctx_new() failed.\n");
4703 goto cleanup;
4704 }
4705
4706 fd = open(argv[1], O_RDONLY);
4707 if (fd == -1) {
4708 fprintf(stderr, "open() failed (%s).\n", strerror(errno));
4709 goto cleanup;
4710 }
4711
4712 if (fstat(fd, &st)) {
4713 fprintf(stderr, "fstat() failed (%s).\n", strerror(errno));
4714 goto cleanup;
4715 }
4716
4717 data = malloc(st.st_size + 1);
4718 if (read(fd, data, st.st_size) < st.st_size) {
4719 fprintf(stderr, "read() failed.\n");
4720 goto cleanup;
4721 }
4722 data[st.st_size] = '\0';
4723
4724 yang_parse(ctx, data, &mod);
4725
4726cleanup:
4727 if (ctx) {
4728 ly_ctx_destroy(ctx, NULL);
4729 }
4730 /* free mod */
4731 close(fd);
4732 free(data);
4733 return 0;
4734}