scan-build revision 6195c373b86963b029a2d1d2501f899789d74ba8
19cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek#!/usr/bin/env perl 29cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 39cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# The LLVM Compiler Infrastructure 49cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 59cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# This file is distributed under the University of Illinois Open Source 69cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# License. See LICENSE.TXT for details. 79cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 89cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##===----------------------------------------------------------------------===## 99cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# A script designed to wrap a build so that all calls to gcc are intercepted 119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# and piped to the static analyzer. 129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##===----------------------------------------------------------------------===## 149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse strict; 169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse warnings; 179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse File::Temp qw/ :mktemp /; 1822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenekuse FindBin qw($RealBin); 19a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenekuse Digest::MD5; 207a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekuse File::Basename; 219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Verbose = 0; # Verbose output from this script. 239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Prog = "scan-build"; 24f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildName; 25f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildDate; 269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current run. 299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 31a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir { 329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "Not enough arguments." if (@_ == 0); 349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift @_; 369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Get current date and time. 389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @CurrentTime = localtime(); 409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $year = $CurrentTime[5] + 1900; 429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $day = $CurrentTime[3]; 439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $month = $CurrentTime[4] + 1; 449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 459d7405fafd5bc08d38bc75579927bf414570bd61Ted Kremenek my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day); 469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Determine the run number. 489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $RunNumber; 509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-d $Dir) { 529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -r $Dir) { 54a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop die "error: '$Dir' exists but is not readable.\n"; 559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Iterate over all files in the specified directory. 589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $max = 0; 609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @FILES= readdir(DIR); 639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek foreach my $f (@FILES) { 669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @x = split/-/, $f; 689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if (scalar(@x) != 4); 709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[0] != $year); 719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[1] != $month); 729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[2] != $day); 739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($x[3] > $max) { 759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $max = $x[3]; 769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = $max + 1; 809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek else { 829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-x $Dir) { 84a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop die "error: '$Dir' exists but is not a directory.\n"; 859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # $Dir does not exist. It will be automatically created by the 889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # clang driver. Set the run number to 1. 899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = 1; 919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "RunNumber must be defined!" if (!defined($RunNumber)); 949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Append the run number. 969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return "$Dir/$DateString-$RunNumber"; 989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 100a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv { 1019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "Wrong number of arguments." if (scalar(@_) != 2); 1039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Args = shift; 1059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 1069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "No build command." if (scalar(@$Args) == 0); 1089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Cmd = $$Args[0]; 1109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Cmd =~ /configure/) { 1129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 1139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Verbose) { 1169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek print "$Prog: Emitting reports for this run to '$Dir'.\n"; 1179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_HTML'} = $Dir; 1209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 1219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 12357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file. 12457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 12557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 12657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest { 12757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $FName = shift; 12857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek die "Cannot read $FName" if (! -r $FName); 129a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 130a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek # Use Digest::MD5. We don't have to be cryptographically secure. We're 1317ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek # just looking for duplicate files that come from a non-malicious source. 1327ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek # We use Digest::MD5 because it is a standard Perl module that should 133a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek # come bundled on most systems. 134a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 135a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek open(FILE, $FName) or die "Cannot open $FName."; 136a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek binmode FILE; 137a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest; 138a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek close(FILE); 139a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 140a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek # Return the digest. 141a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 142a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek return $Result; 14357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek} 14457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 14557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 1467a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek# UpdatePrefix - Compute the common prefix of files. 1477a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 1487a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1497a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekmy $Prefix; 1507a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1517a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdatePrefix { 1527a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1537a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $x = shift; 1547a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $y = basename($x); 1557a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $x =~ s/\Q$y\E$//; 1567a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1577a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek # Ignore /usr, /Library, /System, /Developer 1587a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1597a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return if ( $x =~ /^\/usr/ or $x =~ /^\/Library/ 1607a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek or $x =~ /^\/System/ or $x =~ /^\/Developer/); 1617a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1627a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1637a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek if (!defined $Prefix) { 1647a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $Prefix = $x; 1657a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return; 1667a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 1677a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1687a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek chop $Prefix while (!($x =~ /^$Prefix/)); 1697a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 1707a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1717a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub GetPrefix { 1727a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return $Prefix; 1737a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 1747a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1757a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 1767a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek# UpdateInFilePath - Update the path in the report file. 1777a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 1787a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1797a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdateInFilePath { 1807a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $fname = shift; 1817a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $regex = shift; 1827a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $newtext = shift; 1837a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1847a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek open (RIN, $fname) or die "cannot open $fname"; 1857a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek open (ROUT, ">$fname.tmp") or die "cannot open $fname.tmp"; 1867a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1877a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek while (<RIN>) { 1887a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek s/$regex/$newtext/; 1897a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek print ROUT $_; 1907a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 1917a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1927a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek close (ROUT); 1937a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek close (RIN); 1947a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek `mv $fname.tmp $fname`; 1957a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 1967a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1977a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 1985744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes. 1995744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 2005744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 20157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces 20257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports. We use a cache to solve this problem. 20357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 20457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned; 20557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 2065744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile { 2075744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2085744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Index = shift; 2095744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Dir = shift; 2105744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $FName = shift; 2115744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 21257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Compute a digest for the report file. Determine if we have already 21357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # scanned a file that looks just like it. 21457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 21557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $digest = ComputeDigest("$Dir/$FName"); 21657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 21757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek if (defined($AlreadyScanned{$digest})) { 21857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Redundant file. Remove it. 21957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek `rm -f $Dir/$FName`; 22057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek return; 22157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek } 22257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 22357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek $AlreadyScanned{$digest} = 1; 22457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 225809709f46f2516b4054681f0b76284055a84a50fTed Kremenek # At this point the report file is not world readable. Make it happen. 226684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek `chmod 644 $Dir/$FName`; 227684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek 228684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek # Scan the report file for tags. 2295744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek open(IN, "$Dir/$FName") or die "$Prog: Cannot open '$Dir/$FName'\n"; 2305744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2315744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $BugDesc = ""; 23222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugFile = ""; 23322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugPathLength = 1; 23422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugLine = 0; 2355744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2365744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek while (<IN>) { 2375744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2385744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek if (/<!-- BUGDESC (.*) -->$/) { 2395744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek $BugDesc = $1; 2405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 24122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGFILE (.*) -->$/) { 24222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugFile = $1; 2437a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek UpdatePrefix($BugFile); 24422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 24522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGPATHLENGTH (.*) -->$/) { 24622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugPathLength = $1; 24722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 24822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGLINE (.*) -->$/) { 24922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugLine = $1; 25022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 2515744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 2525744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2535744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(IN); 2545744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 25522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek push @$Index,[ $FName, $BugDesc, $BugFile, $BugLine, $BugPathLength ]; 25622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek} 25722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 25822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 25922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek# CopyJS - Copy JavaScript code to target directory. 26022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 26122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 26222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremeneksub CopyJS { 26322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 26422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $Dir = shift; 26522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 26622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek die "$Prog: Cannot find 'sorttable.js'.\n" 26722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$RealBin/sorttable.js"); 26822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 26922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek `cp $RealBin/sorttable.js $Dir`; 27022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 27122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek die "$Prog: Could not copy 'sorttable.js' to '$Dir'." 27222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$Dir/sorttable.js"); 2735744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek} 2745744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2755744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 2769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan. 2779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 2789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 279a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess { 2809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 282684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek my $BaseDir = shift; 2839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "No directory specified." if (!defined($Dir)); 285684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek die "No base directory specified." if (!defined($BaseDir)); 2869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -d $Dir) { 2889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 2899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 2909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 2929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @files = grep(/^report-.*\.html$/,readdir(DIR)); 2939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 2949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (scalar(@files) == 0) { 29602493782bd4620969041921f2a842528ffdfc940Ted Kremenek print "$Prog: Removing directory '$Dir' because it contains no reports.\n"; 2979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek `rm -fR $Dir`; 2989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 2999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 3005744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3015744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek # Scan each report file and build an index. 3025744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3035744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my @Index; 3045744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3055744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); } 3065744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3075744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek # Generate an index.html file. 3085744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3095744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $FName = "$Dir/index.html"; 3105744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3115744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek open(OUT, ">$FName") or die "$Prog: Cannot create file '$FName'\n"; 3125744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3136e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the header. 3146e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3155744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT; 3165744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html> 3175744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head> 3187f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<style type="text/css"> 3197f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek body { color:#000000; background-color:#ffffff } 32022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek body { font-family: Helvetica, sans-serif; font-size:9pt } 3217f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek h1 { font-size:12pt } 32222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable thead { 32322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek background-color:#eee; color:#666666; 32422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek font-weight: bold; cursor: default; 325bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek text-align:center; 326bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek border-top: 2px solid #000000; 327bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek border-bottom: 2px solid #000000; 328bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek font-weight: bold; font-family: Verdana 329bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek } 33022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border: 1px #000000 solid } 33122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border-collapse: collapse; border-spacing: 0px } 3327f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek td { border-bottom: 1px #000000 dotted } 33322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td { padding:5px; padding-left:8px; padding-right:8px } 334d8c6d0c8a5f970240cc4cbf8eddeae037d1b29eaTed Kremenek td { text-align:left; font-size:9pt } 33522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td.View { padding-left: 10px } 3367f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</style> 33722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script> 3386e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript"> 3396e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal) 3406e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{ 3416e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek var Rows = document.getElementsByTagName("tr"); 3426e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for ( var i = 0 ; i < Rows.length; ++i ) { 3436e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (Rows[i].className == RowClass) { 3446e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek Rows[i].style.display = DisplayVal; 3456e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3466e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3476e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 3486e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3496e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) { 3506e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (CheckButton.checked) { 3516e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, ""); 3526e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3536e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek else { 3546e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, "none"); 3556e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3566e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 3576e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script> 3586e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head> 3596e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body> 3606e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 3616e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3626e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the summary table. 3636e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3646e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek my %Totals; 3656e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3666e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for my $row ( @Index ) { 3676e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 368432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek #my $bug_type = lc($row->[1]); 369432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek my $bug_type = ($row->[1]); 3706e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3716e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (!defined($Totals{$bug_type})) { 3726e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek $Totals{$bug_type} = 1; 3736e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3746e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek else { 3756e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek $Totals{$bug_type}++; 3766e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3776e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 378f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 379f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print OUT "<h3>Summary</h3>"; 380f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 381f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek if (defined($BuildName)) { 382f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n" 383f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek } 384f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 3856e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 3866e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<table class="sortable"> 3876e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<tr> 3886e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td>Bug Type</td> 3896e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td>Quantity</td> 3906e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td "sorttable_nosort">Display?</td> 3916e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</tr> 3926e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 3936e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3946e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for my $key ( sort { $a cmp $b } keys %Totals ) { 395bdf66c7373159aa80403d313629330fd11d4c48aTed Kremenek my $x = lc($key); 396bdf66c7373159aa80403d313629330fd11d4c48aTed Kremenek $x =~ s/\s[,]/_/g; 3976e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek print OUT "<tr><td>$key</td><td>$Totals{$key}</td><td><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></td></tr>\n"; 3986e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3996e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4006e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the table of errors. 4016e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4026e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 4036e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table> 4046e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<h3>Reports</h3> 40522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<table class="sortable"> 4067f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<tr> 407bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Bug Type</td> 408bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>File</td> 409bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Line</td> 410bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Path Length</td> 411bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td "sorttable_nosort"></td> 4127f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</tr> 4135744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT 4149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4157a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $prefix = GetPrefix(); 4167a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $regex; 4177a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $InFileRegex; 4187a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $InFilePrefix = "File:</td><td>"; 4197a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 4207a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek if (defined($prefix)) { 4217a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $regex = qr/^\Q$prefix\E/is; 4227a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is; 4237a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 4247a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 4255744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek for my $row ( sort { $a->[1] cmp $b->[1] } @Index ) { 4265744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4276e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek my $x = lc($row->[1]); 428bdf66c7373159aa80403d313629330fd11d4c48aTed Kremenek $x =~ s/\s[,]/_/g; 4296e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4306e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek print OUT "<tr class=\"bt_$x\">\n"; 4315744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4325744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $ReportFile = $row->[0]; 4339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 43422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT " <td class=\"DESC\">"; 435432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek #print OUT lc($row->[1]); 436432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek print OUT $row->[1]; 43722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT "</td>\n"; 4385744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4397a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek # Update the file prefix. 4407a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 4417a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $fname = $row->[2]; 4427a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek if (defined($regex)) { 4437a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $fname =~ s/$regex//; 4447a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix) 4457a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 4463e56e0b8b285e86eed4d191b1da93ded7382a847Ted Kremenek 4477a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek print OUT "<td>$fname</td>\n"; 4487a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 4497a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek # Print the rest of the columns. 4507a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 4517a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek for my $j ( 3 .. $#{$row} ) { 4525744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "<td>$row->[$j]</td>\n" 4535744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 4547f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 4557f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # Emit the "View" link. 4567f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 45722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT " <td class=\"View\"><a href=\"$ReportFile#EndPath\">View</a></td>\n"; 4585744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4597f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # End the row. 4605744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "</tr>\n"; 4615744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 4625744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4635744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "</table>\n</body></html>\n"; 4645744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(OUT); 46522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 46622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek CopyJS($Dir); 467684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek 468684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek # Make sure $Dir and $BaseDir is world readable/executable. 469684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek `chmod 755 $Dir`; 470684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek `chmod 755 $BaseDir`; 4719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 4729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 474dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command. 475dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 476dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 4776b6289848e215ff12d4d54fe0602d3371db52788Ted Kremeneksub AddIfNotPresent { 4786b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $Args = shift; 4796b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $Arg = shift; 4806b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $found = 0; 4816b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 4826b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek foreach my $k (@$Args) { 4836b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($k eq $Arg) { 4846b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek $found = 1; 4856b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek last; 4866b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 4876b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 4886b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 4896b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($found == 0) { 4906b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek push @$Args, $Arg; 4916b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 4926b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek} 4936b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 494dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremeneksub RunBuildCommand { 495dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 496dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Args = shift; 4977442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek my $IgnoreErrors = shift; 498dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Cmd = $Args->[0]; 4996195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek my $CCAnalyzer = shift; 500dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 5016a43ba9cd247811b6d48ffbd4ee3c911c8c4b458Ted Kremenek if ($Cmd eq "gcc" or $Cmd eq "cc" or $Cmd eq "llvm-gcc") { 502dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek shift @$Args; 5036195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek unshift @$Args, $CCAnalyzer; 504dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek } 5057442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($IgnoreErrors) { 5067442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek if ($Cmd eq "make" or $Cmd eq "gmake") { 5076b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-k"); 5088912b5427a22d9032cad959c5c22cd9d28d4a66cTed Kremenek AddIfNotPresent($Args,"-i"); 5097442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 5107442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($Cmd eq "xcodebuild") { 5116b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES"); 5127442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 5136b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 5146b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 5156b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($Cmd eq "xcodebuild") { 516cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek # Disable distributed builds for xcodebuild. 5176b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-nodistribute"); 518cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek 519cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek # Disable PCH files until clang supports them. 520cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO"); 521915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek 522915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # When 'CC' is set, xcodebuild uses it to do all linking, even if we are 523915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # linking C++ object files. Set 'LDPLUSPLUS' so that xcodebuild uses 'g++' 524915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # when linking such files. 525915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek my $LDPLUSPLUS = `which g++`; 526915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek $LDPLUSPLUS =~ s/\015?\012//; # strip newlines 527915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS; 5286b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 529dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 530dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek system(@$Args); 531dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek} 532dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 533dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 5349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options. 5359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 5369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 537a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp { 5389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5395744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT; 540a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options] 5412b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 542f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted KremenekENDTEXT 543f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 544f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek if (defined($BuildName)) { 545f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n"; 546f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek } 547f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 548f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekprint <<ENDTEXT; 5492b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS: 5502b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 5511262fc4d66584224234691d30d779f8ff004585cTed Kremenek -a - The analysis to run. The default is 'checker-cfref'. 5521262fc4d66584224234691d30d779f8ff004585cTed Kremenek Valid options are: 'checker-cfref', 'fsyntax-only' 5531262fc4d66584224234691d30d779f8ff004585cTed Kremenek 5542b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek -o - Target directory for HTML report files. Subdirectories 555a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop will be created as needed to represent separate "runs" of 5562b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek the analyzer. If this option is not specified, a directory 5572b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek is created in /tmp to store the reports. 5581262fc4d66584224234691d30d779f8ff004585cTed Kremenek 55910f883fe7ef74139f8778e49acacf0ce408e7088Ted Kremenek -h - Display this message. 5602b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek --help 5611262fc4d66584224234691d30d779f8ff004585cTed Kremenek 562af08f64abc38af5914d96106aeb014a2e06eb865Ted Kremenek -k - Add a "keep on going" option to the specified build command. 563f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek --keep-going This option currently supports make and xcodebuild. 564f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek This is a convenience option; one can specify this 565f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek behavior directly using build options. 5662b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 567dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek -v - Verbose output from $Prog and the analyzer. 568dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek A second "-v" increases verbosity. 5692b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 5707f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek -V - View analysis results in a web browser when the build 5717f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek --view completes. 5727f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 5732b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS 5742b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 57539eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek You can specify any build option acceptable to the build command. 57639eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek 5775744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE 5782b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 5795744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek $Prog -o /tmp/myhtmldir make -j4 5802b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 58139eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek The above example causes analysis reports to be deposited into 58239eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option. 58339eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek A different subdirectory is created each time $Prog analyzes a project. 58439eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek The analyzer should support most parallel builds, but not distributed builds. 5852b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 5862b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT 5879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 5889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 5909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments. 5919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 5929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir; # Parent directory to store HTML files. 5949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0; # Ignore build errors. 5957f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults = 0; # View results when the build terminates. 5961262fc4d66584224234691d30d779f8ff004585cTed Kremenekmy $Analysis = "checker-cfref"; 5979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 5999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 600a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 6019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 6029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) { 6049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Scan for options we recognize. 6069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $arg = $ARGV[0]; 6089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6092f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop if ($arg eq "-h" or $arg eq "--help") { 6109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 611a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 0; 6129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6141262fc4d66584224234691d30d779f8ff004585cTed Kremenek if ($arg eq "-a") { 6151262fc4d66584224234691d30d779f8ff004585cTed Kremenek shift @ARGV; 6161262fc4d66584224234691d30d779f8ff004585cTed Kremenek 6171262fc4d66584224234691d30d779f8ff004585cTed Kremenek if (!@ARGV) { 6181262fc4d66584224234691d30d779f8ff004585cTed Kremenek die "$Prog: '-a' option requires an analysis type.\n"; 6191262fc4d66584224234691d30d779f8ff004585cTed Kremenek } 6201262fc4d66584224234691d30d779f8ff004585cTed Kremenek 6211262fc4d66584224234691d30d779f8ff004585cTed Kremenek $Analysis = shift @ARGV; 6221262fc4d66584224234691d30d779f8ff004585cTed Kremenek 6231262fc4d66584224234691d30d779f8ff004585cTed Kremenek if (!($Analysis eq "checker-cfref" or $Analysis eq "fsyntax-only")) { 6241262fc4d66584224234691d30d779f8ff004585cTed Kremenek die "$Prog: Invalid argument '$Analysis' to -a.\n"; 6251262fc4d66584224234691d30d779f8ff004585cTed Kremenek } 6261262fc4d66584224234691d30d779f8ff004585cTed Kremenek 6271262fc4d66584224234691d30d779f8ff004585cTed Kremenek next; 6281262fc4d66584224234691d30d779f8ff004585cTed Kremenek } 6291262fc4d66584224234691d30d779f8ff004585cTed Kremenek 6309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-o") { 6319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 6329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!@ARGV) { 6340062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek die "$Prog: '-o' option requires a target directory name.\n"; 6359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $HtmlDir = shift @ARGV; 6389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 6399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6412b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek if ($arg eq "-k" or $arg eq "--keep-going") { 6429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 6439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $IgnoreErrors = 1; 6449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 6459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-v") { 6489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 6499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $Verbose++; 6509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 6519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6537f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek if ($arg eq "-V" or $arg eq "--view") { 6547f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek shift @ARGV; 6557f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek $ViewResults = 1; 6567f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek next; 6577f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek } 6587f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 6590062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek die "$Prog: unrecognized option '$arg'\n" if ($arg =~ /^-/); 6600062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek 6619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek last; 6629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 6639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 6659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek print STDERR "$Prog: No build command specified.\n\n"; 6669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 667a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 6689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 6699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports. 6719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!defined($HtmlDir)) { 6739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 674a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop $HtmlDir = mkdtemp("/tmp/$Prog-XXXXXX"); 6759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!defined($HtmlDir)) { 677a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop die "error: Cannot create HTML directory in /tmp.\n"; 6789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!$Verbose) { 6819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek print "$Prog: Using '$HtmlDir' as base HTML report directory.\n"; 6829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 6849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 685684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir; 686a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir); 6879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Set the appropriate environment variables. 6899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 690a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopSetHtmlEnv(\@ARGV, $HtmlDir); 6919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6920b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekmy $Cmd = "$RealBin/ccc-analyzer"; 6930b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 6940b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekdie "$Prog: Executable 'ccc-analyzer' does not exist at '$Cmd'\n" 6950b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek if (! -x $Cmd); 696f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek 697f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenekmy $Clang = "$RealBin/clang"; 698f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek 699f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenekif (! -x $Clang) { 700f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek print "$Prog: 'clang' executable not found in '$RealBin'. Using 'clang' from path.\n"; 701f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek $Clang = "clang"; 702f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek} 7030b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 7044f4b17da43d3be87a248e1e10bf0b7d8b5891efdTed Kremenek$ENV{'CC'} = $Cmd; 705f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek$ENV{'CLANG'} = $Clang; 7069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif ($Verbose >= 2) { 7089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_VERBOSE'} = 1; 7099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 7109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 711a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenekif ($Verbose >= 3) { 712a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek $ENV{'CCC_ANALYZER_LOG'} = 1; 713a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek} 714a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek 7151262fc4d66584224234691d30d779f8ff004585cTed Kremenek$ENV{'CCC_ANALYZER_ANALYSIS'} = $Analysis; 7161262fc4d66584224234691d30d779f8ff004585cTed Kremenek 7179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build. 7189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7196195c373b86963b029a2d1d2501f899789d74ba8Ted KremenekRunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd); 7209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess the HTML directory. 7229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 723684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted KremenekPostprocess($HtmlDir, $BaseDir); 7247f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 7257f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekif ($ViewResults and -r "$HtmlDir/index.html") { 7267f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # Only works on Mac OS X (for now). 7277f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek print "Viewing analysis results: '$HtmlDir/index.html'\n"; 7287f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek `open $HtmlDir/index.html` 7297f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek} 730