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 = (
62 ".git" => 1, # allow git mirrors of the svn repo
64 "Inst" => 1, # the nightly scripts creates this
68 "autom4te.cache" => 1,
72 "gdbserver_tests" => 1,
77 my %tool_export_header = (
79 "helgrind/helgrind.h" => 1,
80 "memcheck/memcheck.h" => 1,
81 "callgrind/callgrind.h" => 1
89 [--debug] Debugging output
91 dir ... Directories to process
100 GetOptions
( "debug" => \
$debug ) || die $usage;
102 my $argc = $#ARGV + 1;
108 foreach my $dir (@ARGV) {
109 process_dir
(undef, $dir, 0);
112 my $rc = ($num_errors == 0) ?
0 : 1;
117 my ($path, $dir, $depth) = @_;
121 # The root directory is always processed
122 } elsif ($depth == 1) {
123 # Toplevel directories
124 return if ($dirs_to_ignore{$dir});
126 if (! $tool_dirs{$dir} && ! $coregrind_dirs{$dir}) {
127 die "Unknown directory '$dir'. Please update $this_script\n";
131 return if ($dirs_to_ignore{$dir});
134 print "DIR = $dir DEPTH = $depth\n" if ($debug);
136 chdir($dir) || die "Cannot chdir '$dir'\n";
138 opendir($hdir, ".") || die "cannot open directory '.'";
140 while (my $file = readdir($hdir)) {
141 next if ($file eq ".");
142 next if ($file eq "..");
146 my $full_path = defined $path ?
"$path/$file" : $file;
147 process_dir
($full_path, $file, $depth + 1);
151 # Regular files; only interested in *.c, *.S and *.h
152 next if (! ($file =~ /\.[cSh]$/));
153 my $path_name = defined $path ?
"$path/$file" : $file;
154 process_file
($path_name);
157 chdir("..") || die "Cannot chdir '..'\n";
160 #---------------------------------------------------------------------
161 # Return 1, if file is located in <valgrind>/include
162 #---------------------------------------------------------------------
163 sub is_coregrind_export_header
{
164 my ($path_name) = @_;
166 return ($path_name =~ /^include\//) ?
1 : 0;
169 #---------------------------------------------------------------------
170 # Return 1, if file is located underneath <valgrind>/coregrind
171 #---------------------------------------------------------------------
172 sub is_coregrind_file
{
173 my ($path_name) = @_;
175 return ($path_name =~ /^coregrind\//) ?
1 : 0;
178 #---------------------------------------------------------------------
179 # Return 1, if file is located underneath <valgrind>/<tool>
180 #---------------------------------------------------------------------
182 my ($path_name) = @_;
184 for my $tool (keys %tool_dirs) {
185 return 1 if ($path_name =~ /^$tool\//);
190 #---------------------------------------------------------------------
191 # Return array of files #include'd by file.
192 #---------------------------------------------------------------------
193 sub get_included_files
{
194 my ($path_name) = @_;
196 my $file = basename
($path_name);
198 open(FILE
, "<$file") || die "Cannot open file '$file'";
200 while (my $line = <FILE
>) {
201 if ($line =~ /^\s*#\s*include "([^"]*)"/) {
204 if ($line =~ /^\s*#\s*include <([^>]*)>/) {
212 #---------------------------------------------------------------------
213 # Check a file from <valgrind>/include
214 #---------------------------------------------------------------------
215 sub check_coregrind_export_header
{
216 my ($path_name) = @_;
217 my $file = basename
($path_name);
219 foreach my $inc (get_included_files
($path_name)) {
220 $inc = basename
($inc);
221 # Must not include pub_core_....
222 if ($inc =~ /pub_core_/) {
223 error
("File $path_name must not include $inc\n");
225 # Only pub_tool_clreq.h may include valgrind.h
226 if (($inc eq "valgrind.h") && ($path_name ne "include/pub_tool_clreq.h")) {
227 error
("File $path_name should include pub_tool_clreq.h instead of $inc\n");
230 # Must not use vg_assert
231 my $assert = `grep vg_assert $file`;
233 error
("File $path_name must not use vg_assert\n");
235 # Must not use VG_(core_panic)
236 my $panic = `grep 'VG_(core_panic)' $file`;
238 error
("File $path_name must not use VG_(core_panic)\n");
242 #---------------------------------------------------------------------
243 # Check a file from <valgrind>/coregrind
244 #---------------------------------------------------------------------
245 sub check_coregrind_file
{
246 my ($path_name) = @_;
247 my $file = basename
($path_name);
249 foreach my $inc (get_included_files
($path_name)) {
250 print "\tINCLUDE $inc\n" if ($debug);
251 # Only pub_tool_xyzzy.h may include pub_core_xyzzy.h
252 if ($inc =~ /pub_tool_/) {
254 $buddy =~ s/pub_tool/pub_core/;
255 if ($file ne $buddy) {
256 error
("File $path_name must not include $inc\n");
259 # Must not include valgrind.h
260 if ($inc eq "valgrind.h") {
261 error
("File $path_name should include pub_core_clreq.h instead of $inc\n");
264 # Must not use tl_assert
265 my $assert = `grep tl_assert $file`;
267 error
("File $path_name must not use tl_assert\n");
269 # Must not use VG_(tool_panic)
270 my $panic = `grep 'VG_(tool_panic)' $file`;
273 # Do not complain about the definition of VG_(tool_panic)
274 if (($path_name eq "coregrind/m_libcassert.c") &&
275 ($panic eq "void VG_(tool_panic) ( const HChar* str )")) {
278 error
("File $path_name must not use VG_(tool_panic)\n");
283 #---------------------------------------------------------------------
284 # Check a file from <valgrind>/<tool>
285 #---------------------------------------------------------------------
286 sub check_tool_file
{
287 my ($path_name) = @_;
288 my $file = basename
($path_name);
290 foreach my $inc (get_included_files
($path_name)) {
291 print "\tINCLUDE $inc\n" if ($debug);
292 # Must not include pub_core_...
293 if ($inc =~ /pub_core_/) {
294 error
("File $path_name must not include $inc\n");
296 # Must not include valgrind.h unless this is an export header
297 if ($inc eq "valgrind.h" && ! $tool_export_header{$path_name}) {
298 error
("File $path_name should include pub_tool_clreq.h instead of $inc\n");
301 # Must not use vg_assert
302 my $assert = `grep vg_assert $file`;
304 error
("File $path_name must not use vg_assert\n");
306 # Must not use VG_(core_panic)
307 my $panic = `grep 'VG_(core_panic)' $file`;
309 error
("File $path_name must not use VG_(core_panic)\n");
313 #---------------------------------------------------------------------
314 # Check an assembler file
315 #---------------------------------------------------------------------
316 sub check_assembler_file
{
317 my ($path_name) = @_;
318 my $file = basename
($path_name);
321 open(FILE
, "<$file") || die "Cannot open file '$file'";
323 while (my $line = <FILE
>) {
324 if ($line =~ /^\s*MARK_STACK_NO_EXEC/) {
330 error
("File $path_name does not instantiate MARK_STACK_NO_EXEC\n");
332 while (my $line = <FILE
>) {
333 if ($line =~ /^\s*#\s*endif/) {
334 error
("File $path_name instantiates MARK_STACK_NO_EXEC"
335 . " under a condition\n");
344 my ($path_name) = @_;
346 print "FILE = $path_name\n" if ($debug);
348 if (is_coregrind_export_header
($path_name)) {
349 check_coregrind_export_header
($path_name);
350 } elsif (is_coregrind_file
($path_name)) {
351 check_coregrind_file
($path_name);
352 } elsif (is_tool_file
($path_name)) {
353 check_tool_file
($path_name);
356 if ($path_name =~ /\.S$/) {
357 check_assembler_file
($path_name);
363 print STDERR
"*** $message";