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,
72 my %tool_export_header = (
74 "helgrind/helgrind.h" => 1,
75 "memcheck/memcheck.h" => 1,
76 "callgrind/callgrind.h" => 1
84 [--debug] Debugging output
86 dir ... Directories to process
95 GetOptions
( "debug" => \
$debug ) || die $usage;
97 my $argc = $#ARGV + 1;
103 foreach my $dir (@ARGV) {
104 process_dir
(undef, $dir, 0);
107 my $rc = ($num_errors == 0) ?
0 : 1;
112 my ($path, $dir, $depth) = @_;
116 # The root directory is always processed
117 } elsif ($depth == 1) {
118 # Toplevel directories
119 return if ($dirs_to_ignore{$dir});
121 if (! $tool_dirs{$dir} && ! $coregrind_dirs{$dir}) {
122 die "Unknown directory '$dir'. Please update $this_script\n";
126 return if ($dirs_to_ignore{$dir});
129 print "DIR = $dir DEPTH = $depth\n" if ($debug);
131 chdir($dir) || die "Cannot chdir '$dir'\n";
133 opendir($hdir, ".") || die "cannot open directory '.'";
135 while (my $file = readdir($hdir)) {
136 next if ($file eq ".");
137 next if ($file eq "..");
141 my $full_path = defined $path ?
"$path/$file" : $file;
142 process_dir
($full_path, $file, $depth + 1);
146 # Regular files; only interested in *.c and *.h
147 next if (! ($file =~ /\.[ch]$/));
148 my $path_name = defined $path ?
"$path/$file" : $file;
149 process_file
($path_name);
152 chdir("..") || die "Cannot chdir '..'\n";
155 #---------------------------------------------------------------------
156 # Return 1, if file is located in <valgrind>/include
157 #---------------------------------------------------------------------
158 sub is_coregrind_export_header
{
159 my ($path_name) = @_;
161 return ($path_name =~ /^include\//) ?
1 : 0;
164 #---------------------------------------------------------------------
165 # Return 1, if file is located underneath <valgrind>/coregrind
166 #---------------------------------------------------------------------
167 sub is_coregrind_file
{
168 my ($path_name) = @_;
170 return ($path_name =~ /^coregrind\//) ?
1 : 0;
173 #---------------------------------------------------------------------
174 # Return 1, if file is located underneath <valgrind>/<tool>
175 #---------------------------------------------------------------------
177 my ($path_name) = @_;
179 for my $tool (keys %tool_dirs) {
180 return 1 if ($path_name =~ /^$tool\//);
185 #---------------------------------------------------------------------
186 # Return array of files #include'd by file.
187 #---------------------------------------------------------------------
188 sub get_included_files
{
189 my ($path_name) = @_;
191 my $file = basename
($path_name);
193 open(FILE
, "<$file") || die "Cannot open file '$file'";
195 while (my $line = <FILE
>) {
196 if ($line =~ /^\s*#\s*include "([^"]*)"/) {
199 if ($line =~ /^\s*#\s*include <([^>]*)>/) {
207 #---------------------------------------------------------------------
208 # Check a file from <valgrind>/include
209 #---------------------------------------------------------------------
210 sub check_coregrind_export_header
{
211 my ($path_name) = @_;
212 my $file = basename
($path_name);
214 foreach my $inc (get_included_files
($path_name)) {
215 $inc = basename
($inc);
216 # Must not include pub_core_....
217 if ($inc =~ /pub_core_/) {
218 error
("File $path_name must not include $inc\n");
220 # Only pub_tool_clreq.h may include valgrind.h
221 if (($inc eq "valgrind.h") && ($path_name ne "include/pub_tool_clreq.h")) {
222 error
("File $path_name should include pub_tool_clreq.h instead of $inc\n");
225 # Must not use vg_assert
226 my $assert = `grep vg_assert $file`;
228 error
("File $path_name must not use vg_assert\n");
230 # Must not use VG_(core_panic)
231 my $panic = `grep 'VG_(core_panic)' $file`;
233 error
("File $path_name must not use VG_(core_panic)\n");
237 #---------------------------------------------------------------------
238 # Check a file from <valgrind>/coregrind
239 #---------------------------------------------------------------------
240 sub check_coregrind_file
{
241 my ($path_name) = @_;
242 my $file = basename
($path_name);
244 foreach my $inc (get_included_files
($path_name)) {
245 print "\tINCLUDE $inc\n" if ($debug);
246 # Only pub_tool_xyzzy.h may include pub_core_xyzzy.h
247 if ($inc =~ /pub_tool_/) {
249 $buddy =~ s/pub_tool/pub_core/;
250 if ($file ne $buddy) {
251 error
("File $path_name must not include $inc\n");
254 # Must not include valgrind.h
255 if ($inc eq "valgrind.h") {
256 error
("File $path_name should include pub_core_clreq.h instead of $inc\n");
259 # Must not use tl_assert
260 my $assert = `grep tl_assert $file`;
262 error
("File $path_name must not use tl_assert\n");
264 # Must not use VG_(tool_panic)
265 my $panic = `grep 'VG_(tool_panic)' $file`;
268 # Do not complain about the definition of VG_(tool_panic)
269 if (($path_name eq "coregrind/m_libcassert.c") &&
270 ($panic eq "void VG_(tool_panic) ( const HChar* str )")) {
273 error
("File $path_name must not use VG_(tool_panic)\n");
278 #---------------------------------------------------------------------
279 # Check a file from <valgrind>/<tool>
280 #---------------------------------------------------------------------
281 sub check_tool_file
{
282 my ($path_name) = @_;
283 my $file = basename
($path_name);
285 foreach my $inc (get_included_files
($path_name)) {
286 print "\tINCLUDE $inc\n" if ($debug);
287 # Must not include pub_core_...
288 if ($inc =~ /pub_core_/) {
289 error
("File $path_name must not include $inc\n");
291 # Must not include valgrind.h unless this is an export header
292 if ($inc eq "valgrind.h" && ! $tool_export_header{$path_name}) {
293 error
("File $path_name should include pub_tool_clreq.h instead of $inc\n");
296 # Must not use vg_assert
297 my $assert = `grep vg_assert $file`;
299 error
("File $path_name must not use vg_assert\n");
301 # Must not use VG_(core_panic)
302 my $panic = `grep 'VG_(core_panic)' $file`;
304 error
("File $path_name must not use VG_(core_panic)\n");
309 my ($path_name) = @_;
311 print "FILE = $path_name\n" if ($debug);
313 if (is_coregrind_export_header
($path_name)) {
314 check_coregrind_export_header
($path_name);
315 } elsif (is_coregrind_file
($path_name)) {
316 check_coregrind_file
($path_name);
317 } elsif (is_tool_file
($path_name)) {
318 check_tool_file
($path_name);
324 print STDERR
"*** $message";