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 #-------------------------------------------------------------------
24 my $this_script = basename
($0);
26 # The list of top-level directories is divided into three sets:
28 # (1) coregrind directories
29 # (2) tool directories
30 # (3) directories to ignore
32 # If a directory is found that does not belong to any of those sets, the
33 # script will terminate unsuccessfully.
35 my %coregrind_dirs = (
55 my %dirs_to_ignore = (
58 ".git" => 1, # allow git mirrors of the svn repo
60 "Inst" => 1, # the nightly scripts creates this
64 "autom4te.cache" => 1,
68 "gdbserver_tests" => 1,
73 my %tool_export_header = (
75 "helgrind/helgrind.h" => 1,
76 "memcheck/memcheck.h" => 1,
77 "callgrind/callgrind.h" => 1
85 [--debug] Debugging output
87 dir ... Directories to process
96 GetOptions
( "debug" => \
$debug ) || die $usage;
98 my $argc = $#ARGV + 1;
104 foreach my $dir (@ARGV) {
105 process_dir
(undef, $dir, 0);
108 my $rc = ($num_errors == 0) ?
0 : 1;
113 my ($path, $dir, $depth) = @_;
117 # The root directory is always processed
118 } elsif ($depth == 1) {
119 # Toplevel directories
120 return if ($dirs_to_ignore{$dir});
122 if (! $tool_dirs{$dir} && ! $coregrind_dirs{$dir}) {
123 die "Unknown directory '$dir'. Please update $this_script\n";
127 return if ($dirs_to_ignore{$dir});
130 print "DIR = $dir DEPTH = $depth\n" if ($debug);
132 chdir($dir) || die "Cannot chdir '$dir'\n";
134 opendir($hdir, ".") || die "cannot open directory '.'";
136 while (my $file = readdir($hdir)) {
137 next if ($file eq ".");
138 next if ($file eq "..");
142 my $full_path = defined $path ?
"$path/$file" : $file;
143 process_dir
($full_path, $file, $depth + 1);
147 # Regular files; only interested in *.c and *.h
148 next if (! ($file =~ /\.[ch]$/));
149 my $path_name = defined $path ?
"$path/$file" : $file;
150 process_file
($path_name);
153 chdir("..") || die "Cannot chdir '..'\n";
156 #---------------------------------------------------------------------
157 # Return 1, if file is located in <valgrind>/include
158 #---------------------------------------------------------------------
159 sub is_coregrind_export_header
{
160 my ($path_name) = @_;
162 return ($path_name =~ /^include\//) ?
1 : 0;
165 #---------------------------------------------------------------------
166 # Return 1, if file is located underneath <valgrind>/coregrind
167 #---------------------------------------------------------------------
168 sub is_coregrind_file
{
169 my ($path_name) = @_;
171 return ($path_name =~ /^coregrind\//) ?
1 : 0;
174 #---------------------------------------------------------------------
175 # Return 1, if file is located underneath <valgrind>/<tool>
176 #---------------------------------------------------------------------
178 my ($path_name) = @_;
180 for my $tool (keys %tool_dirs) {
181 return 1 if ($path_name =~ /^$tool\//);
186 #---------------------------------------------------------------------
187 # Return array of files #include'd by file.
188 #---------------------------------------------------------------------
189 sub get_included_files
{
190 my ($path_name) = @_;
192 my $file = basename
($path_name);
194 open(FILE
, "<$file") || die "Cannot open file '$file'";
196 while (my $line = <FILE
>) {
197 if ($line =~ /^\s*#\s*include "([^"]*)"/) {
200 if ($line =~ /^\s*#\s*include <([^>]*)>/) {
208 #---------------------------------------------------------------------
209 # Check a file from <valgrind>/include
210 #---------------------------------------------------------------------
211 sub check_coregrind_export_header
{
212 my ($path_name) = @_;
213 my $file = basename
($path_name);
215 foreach my $inc (get_included_files
($path_name)) {
216 $inc = basename
($inc);
217 # Must not include pub_core_....
218 if ($inc =~ /pub_core_/) {
219 error
("File $path_name must not include $inc\n");
221 # Only pub_tool_clreq.h may include valgrind.h
222 if (($inc eq "valgrind.h") && ($path_name ne "include/pub_tool_clreq.h")) {
223 error
("File $path_name should include pub_tool_clreq.h instead of $inc\n");
226 # Must not use vg_assert
227 my $assert = `grep vg_assert $file`;
229 error
("File $path_name must not use vg_assert\n");
231 # Must not use VG_(core_panic)
232 my $panic = `grep 'VG_(core_panic)' $file`;
234 error
("File $path_name must not use VG_(core_panic)\n");
238 #---------------------------------------------------------------------
239 # Check a file from <valgrind>/coregrind
240 #---------------------------------------------------------------------
241 sub check_coregrind_file
{
242 my ($path_name) = @_;
243 my $file = basename
($path_name);
245 foreach my $inc (get_included_files
($path_name)) {
246 print "\tINCLUDE $inc\n" if ($debug);
247 # Only pub_tool_xyzzy.h may include pub_core_xyzzy.h
248 if ($inc =~ /pub_tool_/) {
250 $buddy =~ s/pub_tool/pub_core/;
251 if ($file ne $buddy) {
252 error
("File $path_name must not include $inc\n");
255 # Must not include valgrind.h
256 if ($inc eq "valgrind.h") {
257 error
("File $path_name should include pub_core_clreq.h instead of $inc\n");
260 # Must not use tl_assert
261 my $assert = `grep tl_assert $file`;
263 error
("File $path_name must not use tl_assert\n");
265 # Must not use VG_(tool_panic)
266 my $panic = `grep 'VG_(tool_panic)' $file`;
269 # Do not complain about the definition of VG_(tool_panic)
270 if (($path_name eq "coregrind/m_libcassert.c") &&
271 ($panic eq "void VG_(tool_panic) ( const HChar* str )")) {
274 error
("File $path_name must not use VG_(tool_panic)\n");
279 #---------------------------------------------------------------------
280 # Check a file from <valgrind>/<tool>
281 #---------------------------------------------------------------------
282 sub check_tool_file
{
283 my ($path_name) = @_;
284 my $file = basename
($path_name);
286 foreach my $inc (get_included_files
($path_name)) {
287 print "\tINCLUDE $inc\n" if ($debug);
288 # Must not include pub_core_...
289 if ($inc =~ /pub_core_/) {
290 error
("File $path_name must not include $inc\n");
292 # Must not include valgrind.h unless this is an export header
293 if ($inc eq "valgrind.h" && ! $tool_export_header{$path_name}) {
294 error
("File $path_name should include pub_tool_clreq.h instead of $inc\n");
297 # Must not use vg_assert
298 my $assert = `grep vg_assert $file`;
300 error
("File $path_name must not use vg_assert\n");
302 # Must not use VG_(core_panic)
303 my $panic = `grep 'VG_(core_panic)' $file`;
305 error
("File $path_name must not use VG_(core_panic)\n");
310 my ($path_name) = @_;
312 print "FILE = $path_name\n" if ($debug);
314 if (is_coregrind_export_header
($path_name)) {
315 check_coregrind_export_header
($path_name);
316 } elsif (is_coregrind_file
($path_name)) {
317 check_coregrind_file
($path_name);
318 } elsif (is_tool_file
($path_name)) {
319 check_tool_file
($path_name);
325 print STDERR
"*** $message";