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/babeltrace-internal.h>
28 #include <babeltrace/list.h>
29 #include "ctf-scanner.h"
30 #include "ctf-parser.h"
33 #define _bt_list_first_entry(ptr, type, member) \
34 bt_list_entry((ptr)->next, type, member)
36 #define fprintf_dbg(fd, fmt, args...) fprintf(fd, "%s: " fmt, __func__, ## args)
39 int _ctf_visitor_semantic_check(FILE *fd
, int depth
, struct ctf_node
*node
);
42 int ctf_visitor_unary_expression(FILE *fd
, int depth
, struct ctf_node
*node
)
44 struct ctf_node
*iter
;
45 int is_ctf_exp
= 0, is_ctf_exp_left
= 0;
47 switch (node
->parent
->type
) {
48 case NODE_CTF_EXPRESSION
:
50 bt_list_for_each_entry(iter
, &node
->parent
->u
.ctf_expression
.left
,
55 * We are a left child of a ctf expression.
56 * We are only allowed to be a string.
58 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
59 fprintf(fd
, "[error]: semantic error (left child of a ctf expression is only allowed to be a string)\n");
66 /* Right child of a ctf expression can be any type of unary exp. */
68 case NODE_TYPE_DECLARATOR
:
70 * We are the length of a type declarator.
72 switch (node
->u
.unary_expression
.type
) {
73 case UNARY_UNSIGNED_CONSTANT
:
77 fprintf(fd
, "[error]: semantic error (children of type declarator and enum can only be unsigned numeric constants or references to fields (a.b.c))\n");
84 * We are the size of a struct align attribute.
86 switch (node
->u
.unary_expression
.type
) {
87 case UNARY_UNSIGNED_CONSTANT
:
90 fprintf(fd
, "[error]: semantic error (structure alignment attribute can only be unsigned numeric constants)\n");
96 /* The enumerator's parent has validated its validity already. */
99 case NODE_UNARY_EXPRESSION
:
101 * We disallow nested unary expressions and "sbrac" unary
104 fprintf(fd
, "[error]: semantic error (nested unary expressions not allowed ( () and [] ))\n");
114 case NODE_TYPEALIAS_TARGET
:
115 case NODE_TYPEALIAS_ALIAS
:
117 case NODE_TYPE_SPECIFIER
:
119 case NODE_FLOATING_POINT
:
123 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
129 switch (node
->u
.unary_expression
.link
) {
130 case UNARY_LINK_UNKNOWN
:
131 /* We don't allow empty link except on the first node of the list */
132 if (is_ctf_exp
&& _bt_list_first_entry(is_ctf_exp_left
?
133 &node
->parent
->u
.ctf_expression
.left
:
134 &node
->parent
->u
.ctf_expression
.right
,
137 fprintf(fd
, "[error]: semantic error (empty link not allowed except on first node of unary expression (need to separate nodes with \".\" or \"->\")\n");
142 case UNARY_ARROWLINK
:
143 /* We only allow -> and . links between children of ctf_expression. */
144 if (node
->parent
->type
!= NODE_CTF_EXPRESSION
) {
145 fprintf(fd
, "[error]: semantic error (links \".\" and \"->\" are only allowed as children of ctf expression)\n");
149 * Only strings can be separated linked by . or ->.
150 * This includes "", '' and non-quoted identifiers.
152 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
153 fprintf(fd
, "[error]: semantic error (links \".\" and \"->\" are only allowed to separate strings and identifiers)\n");
156 /* We don't allow link on the first node of the list */
157 if (is_ctf_exp
&& _bt_list_first_entry(is_ctf_exp_left
?
158 &node
->parent
->u
.ctf_expression
.left
:
159 &node
->parent
->u
.ctf_expression
.right
,
162 fprintf(fd
, "[error]: semantic error (links \".\" and \"->\" are not allowed before first node of the unary expression list)\n");
166 case UNARY_DOTDOTDOT
:
167 /* We only allow ... link between children of enumerator. */
168 if (node
->parent
->type
!= NODE_ENUMERATOR
) {
169 fprintf(fd
, "[error]: semantic error (link \"...\" is only allowed within enumerator)\n");
172 /* We don't allow link on the first node of the list */
173 if (_bt_list_first_entry(&node
->parent
->u
.enumerator
.values
,
176 fprintf(fd
, "[error]: semantic error (link \"...\" is not allowed on the first node of the unary expression list)\n");
181 fprintf(fd
, "[error] %s: unknown expression link type %d\n", __func__
,
182 (int) node
->u
.unary_expression
.link
);
188 fprintf(fd
, "[error] %s: incoherent parent type %s for node type %s\n", __func__
,
189 node_type(node
->parent
), node_type(node
));
190 return -EINVAL
; /* Incoherent structure */
193 fprintf(fd
, "[error] %s: semantic error (parent type %s for node type %s)\n", __func__
,
194 node_type(node
->parent
), node_type(node
));
195 return -EPERM
; /* Structure not allowed */
199 int ctf_visitor_type_specifier_list(FILE *fd
, int depth
, struct ctf_node
*node
)
201 switch (node
->parent
->type
) {
202 case NODE_CTF_EXPRESSION
:
203 case NODE_TYPE_DECLARATOR
:
205 case NODE_TYPEALIAS_TARGET
:
206 case NODE_TYPEALIAS_ALIAS
:
208 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
217 case NODE_UNARY_EXPRESSION
:
219 case NODE_TYPE_SPECIFIER
:
220 case NODE_TYPE_SPECIFIER_LIST
:
222 case NODE_FLOATING_POINT
:
225 case NODE_ENUMERATOR
:
233 fprintf(fd
, "[error] %s: incoherent parent type %s for node type %s\n", __func__
,
234 node_type(node
->parent
), node_type(node
));
235 return -EINVAL
; /* Incoherent structure */
239 int ctf_visitor_type_specifier(FILE *fd
, int depth
, struct ctf_node
*node
)
241 switch (node
->parent
->type
) {
242 case NODE_TYPE_SPECIFIER_LIST
:
245 case NODE_CTF_EXPRESSION
:
246 case NODE_TYPE_DECLARATOR
:
248 case NODE_TYPEALIAS_TARGET
:
249 case NODE_TYPEALIAS_ALIAS
:
251 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
258 case NODE_UNARY_EXPRESSION
:
260 case NODE_TYPE_SPECIFIER
:
262 case NODE_FLOATING_POINT
:
265 case NODE_ENUMERATOR
:
273 fprintf(fd
, "[error] %s: incoherent parent type %s for node type %s\n", __func__
,
274 node_type(node
->parent
), node_type(node
));
275 return -EINVAL
; /* Incoherent structure */
279 int ctf_visitor_type_declarator(FILE *fd
, int depth
, struct ctf_node
*node
)
282 struct ctf_node
*iter
;
286 switch (node
->parent
->type
) {
287 case NODE_TYPE_DECLARATOR
:
289 * A nested type declarator is not allowed to contain pointers.
291 if (!bt_list_empty(&node
->u
.type_declarator
.pointers
))
294 case NODE_TYPEALIAS_TARGET
:
296 case NODE_TYPEALIAS_ALIAS
:
298 * Only accept alias name containing:
300 * - identifier * (any number of pointers)
301 * NOT accepting alias names containing [] (would otherwise
302 * cause semantic clash for later declarations of
303 * arrays/sequences of elements, where elements could be
304 * arrays/sequences themselves (if allowed in typealias).
305 * NOT accepting alias with identifier. The declarator should
306 * be either empty or contain pointer(s).
308 if (node
->u
.type_declarator
.type
== TYPEDEC_NESTED
)
310 bt_list_for_each_entry(iter
, &node
->parent
->u
.typealias_alias
.type_specifier_list
->u
.type_specifier_list
.head
,
312 switch (iter
->u
.type_specifier
.type
) {
313 case TYPESPEC_FLOATING_POINT
:
314 case TYPESPEC_INTEGER
:
315 case TYPESPEC_STRING
:
316 case TYPESPEC_STRUCT
:
317 case TYPESPEC_VARIANT
:
319 if (bt_list_empty(&node
->u
.type_declarator
.pointers
))
326 if (node
->u
.type_declarator
.type
== TYPEDEC_ID
&&
327 node
->u
.type_declarator
.u
.id
!= NULL
)
331 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
340 case NODE_CTF_EXPRESSION
:
341 case NODE_UNARY_EXPRESSION
:
343 case NODE_TYPE_SPECIFIER
:
345 case NODE_FLOATING_POINT
:
348 case NODE_ENUMERATOR
:
356 bt_list_for_each_entry(iter
, &node
->u
.type_declarator
.pointers
,
358 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
363 switch (node
->u
.type_declarator
.type
) {
368 if (node
->u
.type_declarator
.u
.nested
.type_declarator
) {
369 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1,
370 node
->u
.type_declarator
.u
.nested
.type_declarator
);
374 if (!node
->u
.type_declarator
.u
.nested
.abstract_array
) {
375 bt_list_for_each_entry(iter
, &node
->u
.type_declarator
.u
.nested
.length
,
377 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
378 fprintf(fd
, "[error] %s: expecting unary expression as length\n", __func__
);
381 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
386 if (node
->parent
->type
== NODE_TYPEALIAS_TARGET
) {
387 fprintf(fd
, "[error] %s: abstract array declarator not permitted as target of typealias\n", __func__
);
391 if (node
->u
.type_declarator
.bitfield_len
) {
392 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1,
393 node
->u
.type_declarator
.bitfield_len
);
399 case TYPEDEC_UNKNOWN
:
401 fprintf(fd
, "[error] %s: unknown type declarator %d\n", __func__
,
402 (int) node
->u
.type_declarator
.type
);
409 fprintf(fd
, "[error] %s: incoherent parent type %s for node type %s\n", __func__
,
410 node_type(node
->parent
), node_type(node
));
411 return -EINVAL
; /* Incoherent structure */
414 fprintf(fd
, "[error] %s: semantic error (parent type %s for node type %s)\n", __func__
,
415 node_type(node
->parent
), node_type(node
));
416 return -EPERM
; /* Structure not allowed */
420 int _ctf_visitor_semantic_check(FILE *fd
, int depth
, struct ctf_node
*node
)
423 struct ctf_node
*iter
;
425 switch (node
->type
) {
427 bt_list_for_each_entry(iter
, &node
->u
.root
.declaration_list
, siblings
) {
428 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
432 bt_list_for_each_entry(iter
, &node
->u
.root
.trace
, siblings
) {
433 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
437 bt_list_for_each_entry(iter
, &node
->u
.root
.stream
, siblings
) {
438 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
442 bt_list_for_each_entry(iter
, &node
->u
.root
.event
, siblings
) {
443 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
450 switch (node
->parent
->type
) {
457 bt_list_for_each_entry(iter
, &node
->u
.event
.declaration_list
, siblings
) {
458 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
464 switch (node
->parent
->type
) {
471 bt_list_for_each_entry(iter
, &node
->u
.stream
.declaration_list
, siblings
) {
472 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
478 switch (node
->parent
->type
) {
485 bt_list_for_each_entry(iter
, &node
->u
.env
.declaration_list
, siblings
) {
486 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
492 switch (node
->parent
->type
) {
499 bt_list_for_each_entry(iter
, &node
->u
.trace
.declaration_list
, siblings
) {
500 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
506 switch (node
->parent
->type
) {
513 bt_list_for_each_entry(iter
, &node
->u
.clock
.declaration_list
, siblings
) {
514 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
521 case NODE_CTF_EXPRESSION
:
522 switch (node
->parent
->type
) {
529 case NODE_FLOATING_POINT
:
534 case NODE_CTF_EXPRESSION
:
535 case NODE_UNARY_EXPRESSION
:
537 case NODE_TYPEALIAS_TARGET
:
538 case NODE_TYPEALIAS_ALIAS
:
539 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
541 case NODE_TYPE_SPECIFIER
:
542 case NODE_TYPE_SPECIFIER_LIST
:
544 case NODE_TYPE_DECLARATOR
:
545 case NODE_ENUMERATOR
:
554 bt_list_for_each_entry(iter
, &node
->u
.ctf_expression
.left
, siblings
) {
555 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
559 bt_list_for_each_entry(iter
, &node
->u
.ctf_expression
.right
, siblings
) {
560 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
566 case NODE_UNARY_EXPRESSION
:
567 return ctf_visitor_unary_expression(fd
, depth
, node
);
570 switch (node
->parent
->type
) {
579 case NODE_CTF_EXPRESSION
:
580 case NODE_UNARY_EXPRESSION
:
582 case NODE_TYPEALIAS_TARGET
:
583 case NODE_TYPEALIAS_ALIAS
:
585 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
586 case NODE_TYPE_SPECIFIER
:
587 case NODE_TYPE_SPECIFIER_LIST
:
589 case NODE_TYPE_DECLARATOR
:
590 case NODE_FLOATING_POINT
:
593 case NODE_ENUMERATOR
:
602 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1,
603 node
->u
._typedef
.type_specifier_list
);
606 bt_list_for_each_entry(iter
, &node
->u
._typedef
.type_declarators
, siblings
) {
607 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
613 case NODE_TYPEALIAS_TARGET
:
617 switch (node
->parent
->type
) {
625 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1,
626 node
->u
.typealias_target
.type_specifier_list
);
630 bt_list_for_each_entry(iter
, &node
->u
.typealias_target
.type_declarators
, siblings
) {
631 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
636 if (nr_declarators
> 1) {
637 fprintf(fd
, "[error] %s: Too many declarators in typealias alias (%d, max is 1)\n", __func__
, nr_declarators
);
644 case NODE_TYPEALIAS_ALIAS
:
648 switch (node
->parent
->type
) {
656 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1,
657 node
->u
.typealias_alias
.type_specifier_list
);
661 bt_list_for_each_entry(iter
, &node
->u
.typealias_alias
.type_declarators
, siblings
) {
662 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
667 if (nr_declarators
> 1) {
668 fprintf(fd
, "[error] %s: Too many declarators in typealias alias (%d, max is 1)\n", __func__
, nr_declarators
);
676 switch (node
->parent
->type
) {
685 case NODE_CTF_EXPRESSION
:
686 case NODE_UNARY_EXPRESSION
:
688 case NODE_TYPEALIAS_TARGET
:
689 case NODE_TYPEALIAS_ALIAS
:
691 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
692 case NODE_TYPE_SPECIFIER
:
693 case NODE_TYPE_SPECIFIER_LIST
:
695 case NODE_TYPE_DECLARATOR
:
696 case NODE_FLOATING_POINT
:
699 case NODE_ENUMERATOR
:
707 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, node
->u
.typealias
.target
);
710 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, node
->u
.typealias
.alias
);
715 case NODE_TYPE_SPECIFIER_LIST
:
716 ret
= ctf_visitor_type_specifier_list(fd
, depth
, node
);
720 case NODE_TYPE_SPECIFIER
:
721 ret
= ctf_visitor_type_specifier(fd
, depth
, node
);
726 switch (node
->parent
->type
) {
727 case NODE_TYPE_DECLARATOR
:
733 case NODE_TYPE_DECLARATOR
:
734 ret
= ctf_visitor_type_declarator(fd
, depth
, node
);
739 case NODE_FLOATING_POINT
:
740 switch (node
->parent
->type
) {
741 case NODE_TYPE_SPECIFIER
:
746 case NODE_UNARY_EXPRESSION
:
749 bt_list_for_each_entry(iter
, &node
->u
.floating_point
.expressions
, siblings
) {
750 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
756 switch (node
->parent
->type
) {
757 case NODE_TYPE_SPECIFIER
:
764 bt_list_for_each_entry(iter
, &node
->u
.integer
.expressions
, siblings
) {
765 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
771 switch (node
->parent
->type
) {
772 case NODE_TYPE_SPECIFIER
:
777 case NODE_UNARY_EXPRESSION
:
781 bt_list_for_each_entry(iter
, &node
->u
.string
.expressions
, siblings
) {
782 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
787 case NODE_ENUMERATOR
:
788 switch (node
->parent
->type
) {
795 * Enumerators are only allows to contain:
796 * numeric unary expression
797 * or num. unary exp. ... num. unary exp
802 bt_list_for_each_entry(iter
, &node
->u
.enumerator
.values
,
805 case 0: if (iter
->type
!= NODE_UNARY_EXPRESSION
806 || (iter
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
807 && iter
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
)
808 || iter
->u
.unary_expression
.link
!= UNARY_LINK_UNKNOWN
) {
809 fprintf(fd
, "[error]: semantic error (first unary expression of enumerator is unexpected)\n");
813 case 1: if (iter
->type
!= NODE_UNARY_EXPRESSION
814 || (iter
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
815 && iter
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
)
816 || iter
->u
.unary_expression
.link
!= UNARY_DOTDOTDOT
) {
817 fprintf(fd
, "[error]: semantic error (second unary expression of enumerator is unexpected)\n");
827 bt_list_for_each_entry(iter
, &node
->u
.enumerator
.values
, siblings
) {
828 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
834 switch (node
->parent
->type
) {
835 case NODE_TYPE_SPECIFIER
:
840 case NODE_UNARY_EXPRESSION
:
845 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, node
->u
._enum
.container_type
);
849 bt_list_for_each_entry(iter
, &node
->u
._enum
.enumerator_list
, siblings
) {
850 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
856 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
857 switch (node
->parent
->type
) {
864 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1,
865 node
->u
.struct_or_variant_declaration
.type_specifier_list
);
868 bt_list_for_each_entry(iter
, &node
->u
.struct_or_variant_declaration
.type_declarators
, siblings
) {
869 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
875 switch (node
->parent
->type
) {
876 case NODE_TYPE_SPECIFIER
:
881 case NODE_UNARY_EXPRESSION
:
884 bt_list_for_each_entry(iter
, &node
->u
.variant
.declaration_list
, siblings
) {
885 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
892 switch (node
->parent
->type
) {
893 case NODE_TYPE_SPECIFIER
:
898 case NODE_UNARY_EXPRESSION
:
901 bt_list_for_each_entry(iter
, &node
->u
._struct
.declaration_list
, siblings
) {
902 ret
= _ctf_visitor_semantic_check(fd
, depth
+ 1, iter
);
910 fprintf(fd
, "[error] %s: unknown node type %d\n", __func__
,
917 fprintf(fd
, "[error] %s: incoherent parent type %s for node type %s\n", __func__
,
918 node_type(node
->parent
), node_type(node
));
919 return -EINVAL
; /* Incoherent structure */
922 fprintf(fd
, "[error] %s: semantic error (parent type %s for node type %s)\n", __func__
,
923 node_type(node
->parent
), node_type(node
));
924 return -EPERM
; /* Structure not allowed */
927 int ctf_visitor_semantic_check(FILE *fd
, int depth
, struct ctf_node
*node
)
932 * First make sure we create the parent links for all children. Let's
933 * take the safe route and recreate them at each validation, just in
934 * case the structure has changed.
936 printf_verbose("CTF visitor: parent links creation... ");
937 ret
= ctf_visitor_parent_links(fd
, depth
, node
);
940 printf_verbose("done.\n");
941 printf_verbose("CTF visitor: semantic check... ");
942 ret
= _ctf_visitor_semantic_check(fd
, depth
, node
);
945 printf_verbose("done.\n");