2 * ctf-visitor-semantic-validator.c
4 * Common Trace Format Metadata Semantic Validator.
6 * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
27 #include <babeltrace/list.h>
28 #include "ctf-scanner.h"
29 #include "ctf-parser.h"
32 #define _cds_list_first_entry(ptr, type, member) \
33 cds_list_entry((ptr)->next, type, member)
35 #define printf_dbg(fmt, args...) fprintf(fd, "%s: " fmt, __func__, ## args)
38 int _ctf_visitor_semantic_check(FILE *fd
, int depth
, struct ctf_node
*node
);
41 int ctf_visitor_unary_expression(FILE *fd
, int depth
, struct ctf_node
*node
)
43 struct ctf_node
*iter
;
44 int is_ctf_exp_left
= 0;
46 switch (node
->parent
->type
) {
47 case NODE_CTF_EXPRESSION
:
48 cds_list_for_each_entry(iter
, &node
->parent
->u
.ctf_expression
.left
,
53 * We are a left child of a ctf expression.
54 * We are only allowed to be a string.
56 if (node
->u
.unary_expression
.type
!= UNARY_STRING
)
61 /* Right child of a ctf expression can be any type of unary exp. */
63 case NODE_TYPE_DECLARATOR
:
65 * We are the length of a type declarator. We can only be
68 switch (node
->u
.unary_expression
.type
) {
69 case UNARY_SIGNED_CONSTANT
:
70 case UNARY_UNSIGNED_CONSTANT
:
77 /* The enumerator's parent has validated its validity already. */
80 case NODE_UNARY_EXPRESSION
:
82 * We disallow nested unary expressions and "sbrac" unary
92 case NODE_TYPEALIAS_TARGET
:
93 case NODE_TYPEALIAS_ALIAS
:
95 case NODE_TYPE_SPECIFIER
:
97 case NODE_FLOATING_POINT
:
101 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
108 switch (node
->u
.unary_expression
.link
) {
109 case UNARY_LINK_UNKNOWN
:
110 /* We don't allow empty link except on the first node of the list */
111 if (_cds_list_first_entry(is_ctf_exp_left
?
112 &node
->parent
->u
.ctf_expression
.left
:
113 &node
->parent
->u
.ctf_expression
.right
,
119 case UNARY_ARROWLINK
:
120 /* We only allow -> and . links between children of ctf_expression. */
121 if (node
->parent
->type
!= NODE_CTF_EXPRESSION
)
123 /* We don't allow link on the first node of the list */
124 if (_cds_list_first_entry(is_ctf_exp_left
?
125 &node
->parent
->u
.ctf_expression
.left
:
126 &node
->parent
->u
.ctf_expression
.right
,
131 * Only strings can be separated linked by . or ->.
132 * This includes "", '' and non-quoted identifiers.
134 if (node
->u
.unary_expression
.type
!= UNARY_STRING
)
137 case UNARY_DOTDOTDOT
:
138 /* We only allow ... link between children of enumerator. */
139 if (node
->parent
->type
!= NODE_ENUMERATOR
)
141 /* We don't allow link on the first node of the list */
142 if (_cds_list_first_entry(&node
->parent
->u
.enumerator
.values
,
148 fprintf(fd
, "[error] %s: unknown expression link type %d\n", __func__
,
149 (int) node
->u
.unary_expression
.link
);
155 fprintf(fd
, "[error] %s: incoherent parent type %d for node type %d\n", __func__
,
156 (int) node
->parent
->type
, (int) node
->type
);
157 return -EINVAL
; /* Incoherent structure */
160 return -EPERM
; /* Structure not allowed */
164 int ctf_visitor_type_specifier(FILE *fd
, int depth
, struct ctf_node
*node
)
166 switch (node
->parent
->type
) {
167 case NODE_CTF_EXPRESSION
:
168 case NODE_TYPE_DECLARATOR
:
170 case NODE_TYPEALIAS_TARGET
:
171 case NODE_TYPEALIAS_ALIAS
:
179 case NODE_UNARY_EXPRESSION
:
181 case NODE_TYPE_SPECIFIER
:
183 case NODE_FLOATING_POINT
:
186 case NODE_ENUMERATOR
:
187 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
195 fprintf(fd
, "[error] %s: incoherent parent type %d for node type %d\n", __func__
,
196 (int) node
->parent
->type
, (int) node
->type
);
197 return -EINVAL
; /* Incoherent structure */
201 int ctf_visitor_type_declarator(FILE *fd
, int depth
, struct ctf_node
*node
)
204 struct ctf_node
*iter
;
208 switch (node
->parent
->type
) {
209 case NODE_TYPE_DECLARATOR
:
211 * A nested type declarator is not allowed to contain pointers.
213 if (!cds_list_empty(&node
->u
.type_declarator
.pointers
))
217 case NODE_TYPEALIAS_TARGET
:
218 case NODE_TYPEALIAS_ALIAS
:
219 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
226 case NODE_CTF_EXPRESSION
:
227 case NODE_UNARY_EXPRESSION
:
229 case NODE_TYPE_SPECIFIER
:
231 case NODE_FLOATING_POINT
:
234 case NODE_ENUMERATOR
:
242 if (!cds_list_empty(&node
->u
.type_declarator
.pointers
)) {
243 cds_list_for_each_entry(iter
, &node
->u
.type_declarator
.pointers
,
245 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
251 switch (node
->u
.type_declarator
.type
) {
255 if (node
->u
.type_declarator
.u
.nested
.type_declarator
) {
256 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1,
257 node
->u
.type_declarator
.u
.nested
.type_declarator
);
261 if (node
->u
.type_declarator
.u
.nested
.length
) {
262 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1,
263 node
->u
.type_declarator
.u
.nested
.length
);
267 if (node
->u
.type_declarator
.bitfield_len
) {
268 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1,
269 node
->u
.type_declarator
.bitfield_len
);
274 case TYPEDEC_UNKNOWN
:
276 fprintf(fd
, "[error] %s: unknown type declarator %d\n", __func__
,
277 (int) node
->u
.type_declarator
.type
);
284 fprintf(fd
, "[error] %s: incoherent parent type %d for node type %d\n", __func__
,
285 (int) node
->parent
->type
, (int) node
->type
);
286 return -EINVAL
; /* Incoherent structure */
289 return -EPERM
; /* Structure not allowed */
293 int _ctf_visitor_semantic_check(FILE *fd
, int depth
, struct ctf_node
*node
)
296 struct ctf_node
*iter
;
298 switch (node
->type
) {
300 cds_list_for_each_entry(iter
, &node
->u
.root
._typedef
,
302 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
306 cds_list_for_each_entry(iter
, &node
->u
.root
.typealias
,
308 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
312 cds_list_for_each_entry(iter
, &node
->u
.root
.declaration_specifier
, siblings
) {
313 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
317 cds_list_for_each_entry(iter
, &node
->u
.root
.trace
, siblings
) {
318 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
322 cds_list_for_each_entry(iter
, &node
->u
.root
.stream
, siblings
) {
323 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
327 cds_list_for_each_entry(iter
, &node
->u
.root
.event
, siblings
) {
328 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
335 switch (node
->parent
->type
) {
342 cds_list_for_each_entry(iter
, &node
->u
.event
.declaration_list
, siblings
) {
343 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
349 switch (node
->parent
->type
) {
356 cds_list_for_each_entry(iter
, &node
->u
.stream
.declaration_list
, siblings
) {
357 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
363 switch (node
->parent
->type
) {
370 cds_list_for_each_entry(iter
, &node
->u
.trace
.declaration_list
, siblings
) {
371 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
377 case NODE_CTF_EXPRESSION
:
378 switch (node
->parent
->type
) {
383 case NODE_FLOATING_POINT
:
388 case NODE_CTF_EXPRESSION
:
389 case NODE_UNARY_EXPRESSION
:
391 case NODE_TYPEALIAS_TARGET
:
392 case NODE_TYPEALIAS_ALIAS
:
393 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
395 case NODE_TYPE_SPECIFIER
:
397 case NODE_TYPE_DECLARATOR
:
398 case NODE_ENUMERATOR
:
407 cds_list_for_each_entry(iter
, &node
->u
.ctf_expression
.left
, siblings
) {
408 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
412 cds_list_for_each_entry(iter
, &node
->u
.ctf_expression
.right
, siblings
) {
413 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
419 case NODE_UNARY_EXPRESSION
:
420 return ctf_visitor_unary_expression(fd
, depth
, node
);
423 switch (node
->parent
->type
) {
432 case NODE_CTF_EXPRESSION
:
433 case NODE_UNARY_EXPRESSION
:
435 case NODE_TYPEALIAS_TARGET
:
436 case NODE_TYPEALIAS_ALIAS
:
438 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
439 case NODE_TYPE_SPECIFIER
:
441 case NODE_TYPE_DECLARATOR
:
442 case NODE_FLOATING_POINT
:
445 case NODE_ENUMERATOR
:
452 cds_list_for_each_entry(iter
, &node
->u
._typedef
.declaration_specifier
, siblings
) {
453 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
457 cds_list_for_each_entry(iter
, &node
->u
._typedef
.type_declarators
, siblings
) {
458 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
464 case NODE_TYPEALIAS_TARGET
:
465 switch (node
->parent
->type
) {
473 cds_list_for_each_entry(iter
, &node
->u
.typealias_target
.declaration_specifier
, siblings
) {
474 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
478 cds_list_for_each_entry(iter
, &node
->u
.typealias_target
.type_declarators
, siblings
) {
479 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
485 case NODE_TYPEALIAS_ALIAS
:
486 switch (node
->parent
->type
) {
494 cds_list_for_each_entry(iter
, &node
->u
.typealias_alias
.declaration_specifier
, siblings
) {
495 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
499 cds_list_for_each_entry(iter
, &node
->u
.typealias_alias
.type_declarators
, siblings
) {
500 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
507 switch (node
->parent
->type
) {
516 case NODE_CTF_EXPRESSION
:
517 case NODE_UNARY_EXPRESSION
:
519 case NODE_TYPEALIAS_TARGET
:
520 case NODE_TYPEALIAS_ALIAS
:
522 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
523 case NODE_TYPE_SPECIFIER
:
525 case NODE_TYPE_DECLARATOR
:
526 case NODE_FLOATING_POINT
:
529 case NODE_ENUMERATOR
:
535 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, node
->u
.typealias
.target
);
538 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, node
->u
.typealias
.alias
);
543 case NODE_TYPE_SPECIFIER
:
544 ret
= ctf_visitor_type_specifier(fd
, depth
, node
);
549 switch (node
->parent
->type
) {
550 case NODE_TYPE_DECLARATOR
:
556 case NODE_TYPE_DECLARATOR
:
557 ret
= ctf_visitor_type_declarator(fd
, depth
, node
);
562 case NODE_FLOATING_POINT
:
563 switch (node
->parent
->type
) {
564 case NODE_CTF_EXPRESSION
:
566 case NODE_TYPEALIAS_TARGET
:
567 case NODE_TYPEALIAS_ALIAS
:
568 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
576 case NODE_TYPE_SPECIFIER
:
578 case NODE_TYPE_DECLARATOR
:
579 case NODE_FLOATING_POINT
:
582 case NODE_ENUMERATOR
:
589 case NODE_UNARY_EXPRESSION
:
592 cds_list_for_each_entry(iter
, &node
->u
.floating_point
.expressions
, siblings
) {
593 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
599 switch (node
->parent
->type
) {
600 case NODE_CTF_EXPRESSION
:
601 case NODE_UNARY_EXPRESSION
:
603 case NODE_TYPEALIAS_TARGET
:
604 case NODE_TYPEALIAS_ALIAS
:
605 case NODE_TYPE_DECLARATOR
:
607 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
615 case NODE_TYPE_SPECIFIER
:
617 case NODE_FLOATING_POINT
:
620 case NODE_ENUMERATOR
:
628 cds_list_for_each_entry(iter
, &node
->u
.integer
.expressions
, siblings
) {
629 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
635 switch (node
->parent
->type
) {
636 case NODE_CTF_EXPRESSION
:
638 case NODE_TYPEALIAS_TARGET
:
639 case NODE_TYPEALIAS_ALIAS
:
640 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
648 case NODE_TYPE_SPECIFIER
:
650 case NODE_TYPE_DECLARATOR
:
651 case NODE_FLOATING_POINT
:
654 case NODE_ENUMERATOR
:
661 case NODE_UNARY_EXPRESSION
:
665 cds_list_for_each_entry(iter
, &node
->u
.string
.expressions
, siblings
) {
666 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
671 case NODE_ENUMERATOR
:
672 switch (node
->parent
->type
) {
679 * Enumerators are only allows to contain:
680 * numeric unary expression
681 * or num. unary exp. ... num. unary exp
686 cds_list_for_each_entry(iter
, &node
->parent
->u
.enumerator
.values
,
689 case 0: if (iter
->type
!= NODE_UNARY_EXPRESSION
690 || (iter
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
691 && iter
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
)
692 || iter
->u
.unary_expression
.link
!= UNARY_LINK_UNKNOWN
)
695 case 1: if (iter
->type
!= NODE_UNARY_EXPRESSION
696 || (iter
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
697 && iter
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
)
698 || iter
->u
.unary_expression
.link
!= UNARY_DOTDOTDOT
)
707 cds_list_for_each_entry(iter
, &node
->u
.enumerator
.values
, siblings
) {
708 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
714 switch (node
->parent
->type
) {
719 case NODE_CTF_EXPRESSION
:
721 case NODE_TYPEALIAS_TARGET
:
722 case NODE_TYPEALIAS_ALIAS
:
723 case NODE_TYPE_DECLARATOR
:
724 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
728 case NODE_TYPE_SPECIFIER
:
730 case NODE_FLOATING_POINT
:
733 case NODE_ENUMERATOR
:
740 case NODE_UNARY_EXPRESSION
:
745 if (node
->u
._enum
.container_type
) {
746 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, node
->u
._enum
.container_type
);
751 cds_list_for_each_entry(iter
, &node
->u
._enum
.enumerator_list
, siblings
) {
752 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
758 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
759 switch (node
->parent
->type
) {
766 cds_list_for_each_entry(iter
, &node
->u
.struct_or_variant_declaration
.declaration_specifier
, siblings
) {
767 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
771 cds_list_for_each_entry(iter
, &node
->u
.struct_or_variant_declaration
.type_declarators
, siblings
) {
772 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
778 switch (node
->parent
->type
) {
783 case NODE_CTF_EXPRESSION
:
785 case NODE_TYPEALIAS_TARGET
:
786 case NODE_TYPEALIAS_ALIAS
:
787 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
791 case NODE_TYPE_SPECIFIER
:
793 case NODE_TYPE_DECLARATOR
:
794 case NODE_FLOATING_POINT
:
797 case NODE_ENUMERATOR
:
804 case NODE_UNARY_EXPRESSION
:
807 cds_list_for_each_entry(iter
, &node
->u
.variant
.declaration_list
, siblings
) {
808 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
815 switch (node
->parent
->type
) {
820 case NODE_CTF_EXPRESSION
:
822 case NODE_TYPEALIAS_TARGET
:
823 case NODE_TYPEALIAS_ALIAS
:
824 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
828 case NODE_TYPE_SPECIFIER
:
830 case NODE_TYPE_DECLARATOR
:
831 case NODE_FLOATING_POINT
:
834 case NODE_ENUMERATOR
:
841 case NODE_UNARY_EXPRESSION
:
844 cds_list_for_each_entry(iter
, &node
->u
._struct
.declaration_list
, siblings
) {
845 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
853 fprintf(fd
, "[error] %s: unknown node type %d\n", __func__
,
860 fprintf(fd
, "[error] %s: incoherent parent type %d for node type %d\n", __func__
,
861 (int) node
->parent
->type
, (int) node
->type
);
862 return -EINVAL
; /* Incoherent structure */
865 return -EPERM
; /* Structure not allowed */
868 int ctf_visitor_semantic_check(FILE *fd
, int depth
, struct ctf_node
*node
)
873 * First make sure we create the parent links for all children. Let's
874 * take the safe route and recreate them at each validation, just in
875 * case the structure has changed.
877 ret
= ctf_visitor_parent_links(fd
, depth
, node
);
880 return _ctf_visitor_semantic_check(fd
, depth
, node
);