Bug499183 - FreeBSD: differences in avx-vmovq output
[valgrind.git] / tests / check_headers_and_includes
blob6e2238e9d3a133543daf204baaf97f4f6031ab0f
1 #!/usr/bin/env perl
3 #-------------------------------------------------------------------
4 # Check header files and #include directives
6 # (1) include/*.h must not include pub_core_...h
7 # (2) coregrind/pub_core_xyzzy.h may include pub_tool_xyzzy.h
8 # other coregrind headers may not include pub_tool_xyzzy.h
9 # (3) coregrind/ *.c must not include pub_tool_xyzzy.h
10 # (4) tool *.[ch] files must not include pub_core_...h
11 # (5) include pub_core/tool_clreq.h instead of valgrind.h except in tools'
12 # export headers
13 # (6) coregrind/ *.[ch] must not use tl_assert
14 # (7) include/*.h and tool *.[ch] must not use vg_assert
15 # (8) coregrind/ *.[ch] must not use VG_(tool_panic)
16 # (9) include/*.h and tool *.[ch] must not use VG_(core_panic)
17 # (10) *.S must unconditionally instantiate MARK_STACK_NO_EXEC
19 # There can be false positives as we don't really parse the source files.
20 # Instead we only match regular expressions.
21 #-------------------------------------------------------------------
23 use strict;
24 use warnings;
25 use File::Basename;
26 use Getopt::Long;
28 my $this_script = basename($0);
30 # The list of top-level directories is divided into three sets:
32 # (1) coregrind directories
33 # (2) tool directories
34 # (3) directories to ignore
36 # If a directory is found that does not belong to any of those sets, the
37 # script will terminate unsuccessfully.
39 my %coregrind_dirs = (
40 "include" => 1,
41 "coregrind" => 1,
44 my %tool_dirs = (
45 "memcheck" => 1,
46 "cachegrind" => 1,
47 "callgrind" => 1,
48 "helgrind", => 1,
49 "drd" => 1,
50 "massif" => 1,
51 "dhat" => 1,
52 "lackey" => 1,
53 "none" => 1,
54 "exp-bbv" => 1,
55 "shared" => 1,
58 my %dirs_to_ignore = (
59 ".deps" => 1,
60 ".git" => 1,
61 ".in_place" => 1,
62 "Inst" => 1, # the nightly scripts creates this
63 "VEX" => 1,
64 "docs" => 1,
65 "auxprogs" => 1,
66 "autom4te.cache" => 1,
67 "m4" => 1,
68 "nightly" => 1,
69 "perf" => 1,
70 "tests" => 1,
71 "gdbserver_tests" => 1,
72 "mpi" => 1,
73 "solaris" => 1
76 my %tool_export_header = (
77 "dhat/dhat.h" => 1,
78 "drd/drd.h" => 1,
79 "helgrind/helgrind.h" => 1,
80 "memcheck/memcheck.h" => 1,
81 "callgrind/callgrind.h" => 1,
82 "cachegrind/cachegrind.h" => 1
85 my $usage=<<EOF;
86 USAGE
88 $this_script
90 [--debug] Debugging output
92 dir ... Directories to process
93 EOF
95 my $debug = 0;
96 my $num_errors = 0;
98 &main;
100 sub main {
101 GetOptions( "debug" => \$debug ) || die $usage;
103 my $argc = $#ARGV + 1;
105 if ($argc < 1) {
106 die $usage;
109 foreach my $dir (@ARGV) {
110 process_dir(undef, $dir, 0);
113 my $rc = ($num_errors == 0) ? 0 : 1;
114 exit $rc;
117 sub process_dir {
118 my ($path, $dir, $depth) = @_;
119 my $hdir;
121 if ($depth == 0) {
122 # The root directory is always processed
123 } elsif ($depth == 1) {
124 # Toplevel directories
125 return if ($dirs_to_ignore{$dir});
127 if (! $tool_dirs{$dir} && ! $coregrind_dirs{$dir}) {
128 die "Unknown directory '$dir'. Please update $this_script\n";
130 } else {
131 # Subdirectories
132 return if ($dirs_to_ignore{$dir});
135 print "DIR = $dir DEPTH = $depth\n" if ($debug);
137 chdir($dir) || die "Cannot chdir '$dir'\n";
139 opendir($hdir, ".") || die "cannot open directory '.'";
141 while (my $file = readdir($hdir)) {
142 next if ($file eq ".");
143 next if ($file eq "..");
145 # Subdirectories
146 if (-d $file) {
147 my $full_path = defined $path ? "$path/$file" : $file;
148 process_dir($full_path, $file, $depth + 1);
149 next;
152 # Regular files; only interested in *.c, *.S and *.h
153 next if (! ($file =~ /\.[cSh]$/));
154 my $path_name = defined $path ? "$path/$file" : $file;
155 process_file($path_name);
157 close($hdir);
158 chdir("..") || die "Cannot chdir '..'\n";
161 #---------------------------------------------------------------------
162 # Return 1, if file is located in <valgrind>/include
163 #---------------------------------------------------------------------
164 sub is_coregrind_export_header {
165 my ($path_name) = @_;
167 return ($path_name =~ /^include\//) ? 1 : 0;
170 #---------------------------------------------------------------------
171 # Return 1, if file is located underneath <valgrind>/coregrind
172 #---------------------------------------------------------------------
173 sub is_coregrind_file {
174 my ($path_name) = @_;
176 return ($path_name =~ /^coregrind\//) ? 1 : 0;
179 #---------------------------------------------------------------------
180 # Return 1, if file is located underneath <valgrind>/<tool>
181 #---------------------------------------------------------------------
182 sub is_tool_file {
183 my ($path_name) = @_;
185 for my $tool (keys %tool_dirs) {
186 return 1 if ($path_name =~ /^$tool\//);
188 return 0
191 #---------------------------------------------------------------------
192 # Return array of files #include'd by file.
193 #---------------------------------------------------------------------
194 sub get_included_files {
195 my ($path_name) = @_;
196 my @includes = ();
197 my $file = basename($path_name);
199 open(FILE, "<$file") || die "Cannot open file '$file'";
201 while (my $line = <FILE>) {
202 if ($line =~ /^\s*#\s*include "([^"]*)"/) {
203 push @includes, $1;
205 if ($line =~ /^\s*#\s*include <([^>]*)>/) {
206 push @includes, $1;
209 close FILE;
210 return @includes;
213 #---------------------------------------------------------------------
214 # Check a file from <valgrind>/include
215 #---------------------------------------------------------------------
216 sub check_coregrind_export_header {
217 my ($path_name) = @_;
218 my $file = basename($path_name);
220 foreach my $inc (get_included_files($path_name)) {
221 $inc = basename($inc);
222 # Must not include pub_core_....
223 if ($inc =~ /pub_core_/) {
224 error("File $path_name must not include $inc\n");
226 # Only pub_tool_clreq.h may include valgrind.h
227 if (($inc eq "valgrind.h") && ($path_name ne "include/pub_tool_clreq.h")) {
228 error("File $path_name should include pub_tool_clreq.h instead of $inc\n");
231 # Must not use vg_assert
232 my $assert = `grep vg_assert $file`;
233 if ($assert ne "") {
234 error("File $path_name must not use vg_assert\n");
236 # Must not use VG_(core_panic)
237 my $panic = `grep 'VG_(core_panic)' $file`;
238 if ($panic ne "") {
239 error("File $path_name must not use VG_(core_panic)\n");
243 #---------------------------------------------------------------------
244 # Check a file from <valgrind>/coregrind
245 #---------------------------------------------------------------------
246 sub check_coregrind_file {
247 my ($path_name) = @_;
248 my $file = basename($path_name);
250 foreach my $inc (get_included_files($path_name)) {
251 print "\tINCLUDE $inc\n" if ($debug);
252 # Only pub_tool_xyzzy.h may include pub_core_xyzzy.h
253 if ($inc =~ /pub_tool_/) {
254 my $buddy = $inc;
255 $buddy =~ s/pub_tool/pub_core/;
256 if ($file ne $buddy) {
257 error("File $path_name must not include $inc\n");
260 # Must not include valgrind.h
261 if ($inc eq "valgrind.h") {
262 error("File $path_name should include pub_core_clreq.h instead of $inc\n");
265 # Must not use tl_assert
266 my $assert = `grep tl_assert $file`;
267 if ($assert ne "") {
268 error("File $path_name must not use tl_assert\n");
270 # Must not use VG_(tool_panic)
271 my $panic = `grep 'VG_(tool_panic)' $file`;
272 if ($panic ne "") {
273 chomp($panic);
274 # Do not complain about the definition of VG_(tool_panic)
275 if (($path_name eq "coregrind/m_libcassert.c") &&
276 ($panic eq "void VG_(tool_panic) ( const HChar* str )")) {
277 # OK
278 } else {
279 error("File $path_name must not use VG_(tool_panic)\n");
284 #---------------------------------------------------------------------
285 # Check a file from <valgrind>/<tool>
286 #---------------------------------------------------------------------
287 sub check_tool_file {
288 my ($path_name) = @_;
289 my $file = basename($path_name);
291 foreach my $inc (get_included_files($path_name)) {
292 print "\tINCLUDE $inc\n" if ($debug);
293 # Must not include pub_core_...
294 if ($inc =~ /pub_core_/) {
295 error("File $path_name must not include $inc\n");
297 # Must not include valgrind.h unless this is an export header
298 if ($inc eq "valgrind.h" && ! $tool_export_header{$path_name}) {
299 error("File $path_name should include pub_tool_clreq.h instead of $inc\n");
302 # Must not use vg_assert
303 my $assert = `grep vg_assert $file`;
304 if ($assert ne "") {
305 error("File $path_name must not use vg_assert\n");
307 # Must not use VG_(core_panic)
308 my $panic = `grep 'VG_(core_panic)' $file`;
309 if ($panic ne "") {
310 error("File $path_name must not use VG_(core_panic)\n");
314 #---------------------------------------------------------------------
315 # Check an assembler file
316 #---------------------------------------------------------------------
317 sub check_assembler_file {
318 my ($path_name) = @_;
319 my $file = basename($path_name);
320 my $found = 0;
322 open(FILE, "<$file") || die "Cannot open file '$file'";
324 while (my $line = <FILE>) {
325 if ($line =~ /^\s*MARK_STACK_NO_EXEC/) {
326 $found = 1;
327 last;
330 if ($found == 0) {
331 error("File $path_name does not instantiate MARK_STACK_NO_EXEC\n");
332 } else {
333 while (my $line = <FILE>) {
334 if ($line =~ /^\s*#\s*endif/) {
335 error("File $path_name instantiates MARK_STACK_NO_EXEC"
336 . " under a condition\n");
337 last;
341 close FILE;
344 sub process_file {
345 my ($path_name) = @_;
347 print "FILE = $path_name\n" if ($debug);
349 if (is_coregrind_export_header($path_name)) {
350 check_coregrind_export_header($path_name);
351 } elsif (is_coregrind_file($path_name)) {
352 check_coregrind_file($path_name);
353 } elsif (is_tool_file($path_name)) {
354 check_tool_file($path_name);
357 if ($path_name =~ /\.S$/) {
358 check_assembler_file($path_name);
362 sub error {
363 my ($message) = @_;
364 print STDERR "*** $message";
365 ++$num_errors;