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'
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 #-------------------------------------------------------------------
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 = (
59 my %dirs_to_ignore = (
63 "Inst" => 1, # the nightly scripts creates this
67 "autom4te.cache" => 1,
71 "gdbserver_tests" => 1,
76 my %tool_export_header = (
78 "helgrind/helgrind.h" => 1,
79 "memcheck/memcheck.h" => 1,
80 "callgrind/callgrind.h" => 1
88 [--debug] Debugging output
90 dir ... Directories to process
99 GetOptions
( "debug" => \
$debug ) || die $usage;
101 my $argc = $#ARGV + 1;
107 foreach my $dir (@ARGV) {
108 process_dir
(undef, $dir, 0);
111 my $rc = ($num_errors == 0) ?
0 : 1;
116 my ($path, $dir, $depth) = @_;
120 # The root directory is always processed
121 } elsif ($depth == 1) {
122 # Toplevel directories
123 return if ($dirs_to_ignore{$dir});
125 if (! $tool_dirs{$dir} && ! $coregrind_dirs{$dir}) {
126 die "Unknown directory '$dir'. Please update $this_script\n";
130 return if ($dirs_to_ignore{$dir});
133 print "DIR = $dir DEPTH = $depth\n" if ($debug);
135 chdir($dir) || die "Cannot chdir '$dir'\n";
137 opendir($hdir, ".") || die "cannot open directory '.'";
139 while (my $file = readdir($hdir)) {
140 next if ($file eq ".");
141 next if ($file eq "..");
145 my $full_path = defined $path ?
"$path/$file" : $file;
146 process_dir
($full_path, $file, $depth + 1);
150 # Regular files; only interested in *.c, *.S and *.h
151 next if (! ($file =~ /\.[cSh]$/));
152 my $path_name = defined $path ?
"$path/$file" : $file;
153 process_file
($path_name);
156 chdir("..") || die "Cannot chdir '..'\n";
159 #---------------------------------------------------------------------
160 # Return 1, if file is located in <valgrind>/include
161 #---------------------------------------------------------------------
162 sub is_coregrind_export_header
{
163 my ($path_name) = @_;
165 return ($path_name =~ /^include\//) ?
1 : 0;
168 #---------------------------------------------------------------------
169 # Return 1, if file is located underneath <valgrind>/coregrind
170 #---------------------------------------------------------------------
171 sub is_coregrind_file
{
172 my ($path_name) = @_;
174 return ($path_name =~ /^coregrind\//) ?
1 : 0;
177 #---------------------------------------------------------------------
178 # Return 1, if file is located underneath <valgrind>/<tool>
179 #---------------------------------------------------------------------
181 my ($path_name) = @_;
183 for my $tool (keys %tool_dirs) {
184 return 1 if ($path_name =~ /^$tool\//);
189 #---------------------------------------------------------------------
190 # Return array of files #include'd by file.
191 #---------------------------------------------------------------------
192 sub get_included_files
{
193 my ($path_name) = @_;
195 my $file = basename
($path_name);
197 open(FILE
, "<$file") || die "Cannot open file '$file'";
199 while (my $line = <FILE
>) {
200 if ($line =~ /^\s*#\s*include "([^"]*)"/) {
203 if ($line =~ /^\s*#\s*include <([^>]*)>/) {
211 #---------------------------------------------------------------------
212 # Check a file from <valgrind>/include
213 #---------------------------------------------------------------------
214 sub check_coregrind_export_header
{
215 my ($path_name) = @_;
216 my $file = basename
($path_name);
218 foreach my $inc (get_included_files
($path_name)) {
219 $inc = basename
($inc);
220 # Must not include pub_core_....
221 if ($inc =~ /pub_core_/) {
222 error
("File $path_name must not include $inc\n");
224 # Only pub_tool_clreq.h may include valgrind.h
225 if (($inc eq "valgrind.h") && ($path_name ne "include/pub_tool_clreq.h")) {
226 error
("File $path_name should include pub_tool_clreq.h instead of $inc\n");
229 # Must not use vg_assert
230 my $assert = `grep vg_assert $file`;
232 error
("File $path_name must not use vg_assert\n");
234 # Must not use VG_(core_panic)
235 my $panic = `grep 'VG_(core_panic)' $file`;
237 error
("File $path_name must not use VG_(core_panic)\n");
241 #---------------------------------------------------------------------
242 # Check a file from <valgrind>/coregrind
243 #---------------------------------------------------------------------
244 sub check_coregrind_file
{
245 my ($path_name) = @_;
246 my $file = basename
($path_name);
248 foreach my $inc (get_included_files
($path_name)) {
249 print "\tINCLUDE $inc\n" if ($debug);
250 # Only pub_tool_xyzzy.h may include pub_core_xyzzy.h
251 if ($inc =~ /pub_tool_/) {
253 $buddy =~ s/pub_tool/pub_core/;
254 if ($file ne $buddy) {
255 error
("File $path_name must not include $inc\n");
258 # Must not include valgrind.h
259 if ($inc eq "valgrind.h") {
260 error
("File $path_name should include pub_core_clreq.h instead of $inc\n");
263 # Must not use tl_assert
264 my $assert = `grep tl_assert $file`;
266 error
("File $path_name must not use tl_assert\n");
268 # Must not use VG_(tool_panic)
269 my $panic = `grep 'VG_(tool_panic)' $file`;
272 # Do not complain about the definition of VG_(tool_panic)
273 if (($path_name eq "coregrind/m_libcassert.c") &&
274 ($panic eq "void VG_(tool_panic) ( const HChar* str )")) {
277 error
("File $path_name must not use VG_(tool_panic)\n");
282 #---------------------------------------------------------------------
283 # Check a file from <valgrind>/<tool>
284 #---------------------------------------------------------------------
285 sub check_tool_file
{
286 my ($path_name) = @_;
287 my $file = basename
($path_name);
289 foreach my $inc (get_included_files
($path_name)) {
290 print "\tINCLUDE $inc\n" if ($debug);
291 # Must not include pub_core_...
292 if ($inc =~ /pub_core_/) {
293 error
("File $path_name must not include $inc\n");
295 # Must not include valgrind.h unless this is an export header
296 if ($inc eq "valgrind.h" && ! $tool_export_header{$path_name}) {
297 error
("File $path_name should include pub_tool_clreq.h instead of $inc\n");
300 # Must not use vg_assert
301 my $assert = `grep vg_assert $file`;
303 error
("File $path_name must not use vg_assert\n");
305 # Must not use VG_(core_panic)
306 my $panic = `grep 'VG_(core_panic)' $file`;
308 error
("File $path_name must not use VG_(core_panic)\n");
312 #---------------------------------------------------------------------
313 # Check an assembler file
314 #---------------------------------------------------------------------
315 sub check_assembler_file
{
316 my ($path_name) = @_;
317 my $file = basename
($path_name);
320 open(FILE
, "<$file") || die "Cannot open file '$file'";
322 while (my $line = <FILE
>) {
323 if ($line =~ /^\s*MARK_STACK_NO_EXEC/) {
329 error
("File $path_name does not instantiate MARK_STACK_NO_EXEC\n");
331 while (my $line = <FILE
>) {
332 if ($line =~ /^\s*#\s*endif/) {
333 error
("File $path_name instantiates MARK_STACK_NO_EXEC"
334 . " under a condition\n");
343 my ($path_name) = @_;
345 print "FILE = $path_name\n" if ($debug);
347 if (is_coregrind_export_header
($path_name)) {
348 check_coregrind_export_header
($path_name);
349 } elsif (is_coregrind_file
($path_name)) {
350 check_coregrind_file
($path_name);
351 } elsif (is_tool_file
($path_name)) {
352 check_tool_file
($path_name);
355 if ($path_name =~ /\.S$/) {
356 check_assembler_file
($path_name);
362 print STDERR
"*** $message";