scan-build revision 23cfca3760c482f8543daab62051f5eaa1f98fb4
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; 2123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenekuse Term::ANSIColor; 2223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenekuse Term::ANSIColor qw(:constants); 239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Verbose = 0; # Verbose output from this script. 259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Prog = "scan-build"; 26f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildName; 27f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildDate; 289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenekmy $UseColor = (($ENV{'TERM'} eq 'xterm-color') and -t STDOUT); 3023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 3123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub Diag { 3223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek if ($UseColor) { 3323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print BOLD, MAGENTA "$Prog: @_"; 3423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET; 3523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 3623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek else { 3723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print "$Prog: @_"; 3823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 3923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek} 4023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 4123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub DieDiag { 4223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek if ($UseColor) { 4323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print BOLD, RED "$Prog: "; 4423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET, RED @_; 4523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET; 4623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 4723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek else { 4823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print "$Prog: ", @_; 4923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 5023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek exit(0); 5123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek} 5223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current run. 559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 57a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir { 589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "Not enough arguments." if (@_ == 0); 609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift @_; 629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Get current date and time. 649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @CurrentTime = localtime(); 669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $year = $CurrentTime[5] + 1900; 689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $day = $CurrentTime[3]; 699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $month = $CurrentTime[4] + 1; 709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 719d7405fafd5bc08d38bc75579927bf414570bd61Ted Kremenek my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day); 729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Determine the run number. 749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $RunNumber; 769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-d $Dir) { 789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -r $Dir) { 8023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("directory '$Dir' exists but is not readable.\n"); 819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Iterate over all files in the specified directory. 849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $max = 0; 869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @FILES= readdir(DIR); 899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek foreach my $f (@FILES) { 929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @x = split/-/, $f; 949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if (scalar(@x) != 4); 969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[0] != $year); 979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[1] != $month); 989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[2] != $day); 999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($x[3] > $max) { 1019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $max = $x[3]; 1029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = $max + 1; 1069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek else { 1089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-x $Dir) { 11023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("'$Dir' exists but is not a directory.\n"); 1119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # $Dir does not exist. It will be automatically created by the 1149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # clang driver. Set the run number to 1. 1159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = 1; 1179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "RunNumber must be defined!" if (!defined($RunNumber)); 1209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Append the run number. 1229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return "$Dir/$DateString-$RunNumber"; 1249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 1259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 126a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv { 1279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "Wrong number of arguments." if (scalar(@_) != 2); 1299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Args = shift; 1319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 1329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "No build command." if (scalar(@$Args) == 0); 1349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Cmd = $$Args[0]; 1369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Cmd =~ /configure/) { 1389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 1399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Verbose) { 14223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("Emitting reports for this run to '$Dir'.\n"); 1439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_HTML'} = $Dir; 1469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 1479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 14957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file. 15057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 15157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 15257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest { 15357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $FName = shift; 15423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName); 155a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 156a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek # Use Digest::MD5. We don't have to be cryptographically secure. We're 1577ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek # just looking for duplicate files that come from a non-malicious source. 1587ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek # We use Digest::MD5 because it is a standard Perl module that should 159a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek # come bundled on most systems. 160a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 16123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n"); 162a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek binmode FILE; 163a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest; 164a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek close(FILE); 165a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 166a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek # Return the digest. 167a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 168a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek return $Result; 16957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek} 17057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 17157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 1727a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek# UpdatePrefix - Compute the common prefix of files. 1737a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 1747a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1757a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekmy $Prefix; 1767a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1777a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdatePrefix { 1787a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1797a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $x = shift; 1807a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $y = basename($x); 1817a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $x =~ s/\Q$y\E$//; 1827a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1837a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek # Ignore /usr, /Library, /System, /Developer 1847a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1857a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return if ( $x =~ /^\/usr/ or $x =~ /^\/Library/ 1867a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek or $x =~ /^\/System/ or $x =~ /^\/Developer/); 1877a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1887a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1897a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek if (!defined $Prefix) { 1907a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $Prefix = $x; 1917a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return; 1927a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 1937a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1947a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek chop $Prefix while (!($x =~ /^$Prefix/)); 1957a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 1967a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 1977a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub GetPrefix { 1987a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return $Prefix; 1997a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 2007a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2017a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2027a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek# UpdateInFilePath - Update the path in the report file. 2037a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2047a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2057a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdateInFilePath { 2067a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $fname = shift; 2077a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $regex = shift; 2087a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $newtext = shift; 2097a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2107a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek open (RIN, $fname) or die "cannot open $fname"; 2117a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek open (ROUT, ">$fname.tmp") or die "cannot open $fname.tmp"; 2127a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2137a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek while (<RIN>) { 2147a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek s/$regex/$newtext/; 2157a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek print ROUT $_; 2167a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 2177a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2187a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek close (ROUT); 2197a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek close (RIN); 2207a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek `mv $fname.tmp $fname`; 2217a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 2227a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2237a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2245744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes. 2255744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 2265744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 22757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces 22857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports. We use a cache to solve this problem. 22957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 23057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned; 23157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 2325744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile { 2335744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2345744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Index = shift; 2355744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Dir = shift; 2365744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $FName = shift; 2375744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 23857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Compute a digest for the report file. Determine if we have already 23957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # scanned a file that looks just like it. 24057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 24157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $digest = ComputeDigest("$Dir/$FName"); 24257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 24357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek if (defined($AlreadyScanned{$digest})) { 24457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Redundant file. Remove it. 24557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek `rm -f $Dir/$FName`; 24657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek return; 24757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek } 24857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 24957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek $AlreadyScanned{$digest} = 1; 25057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 251809709f46f2516b4054681f0b76284055a84a50fTed Kremenek # At this point the report file is not world readable. Make it happen. 252684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek `chmod 644 $Dir/$FName`; 253684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek 254684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek # Scan the report file for tags. 25523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n"); 2565744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2575744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $BugDesc = ""; 25822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugFile = ""; 25922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugPathLength = 1; 26022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugLine = 0; 2615744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2625744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek while (<IN>) { 2635744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2645744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek if (/<!-- BUGDESC (.*) -->$/) { 2655744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek $BugDesc = $1; 2665744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 26722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGFILE (.*) -->$/) { 26822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugFile = $1; 2697a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek UpdatePrefix($BugFile); 27022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 27122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGPATHLENGTH (.*) -->$/) { 27222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugPathLength = $1; 27322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 27422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGLINE (.*) -->$/) { 27522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugLine = $1; 27622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 2775744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 2785744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2795744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(IN); 2805744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 28122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek push @$Index,[ $FName, $BugDesc, $BugFile, $BugLine, $BugPathLength ]; 28222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek} 28322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 28422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 28522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek# CopyJS - Copy JavaScript code to target directory. 28622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 28722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 28822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremeneksub CopyJS { 28922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 29022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $Dir = shift; 29122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 29223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Cannot find 'sorttable.js'.\n") 29322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$RealBin/sorttable.js"); 29422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 29522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek `cp $RealBin/sorttable.js $Dir`; 29622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 29723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n") 29822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$Dir/sorttable.js"); 2995744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek} 3005744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3015744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 3029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan. 3039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 3049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 305a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess { 3069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 308684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek my $BaseDir = shift; 3099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "No directory specified." if (!defined($Dir)); 311684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek die "No base directory specified." if (!defined($BaseDir)); 3129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -d $Dir) { 31423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("No bugs found.\n"); 3159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 3169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 3179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 3199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @files = grep(/^report-.*\.html$/,readdir(DIR)); 3209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 3219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (scalar(@files) == 0) { 32323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("Removing directory '$Dir' because it contains no reports.\n"); 3249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek `rm -fR $Dir`; 32523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 32623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek # Remove the base directory if it contains no files (don't use '-R'). 32723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek `rm -f $BaseDir`; 32823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 32923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("No bugs found.\n"); 3309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 3319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 3325744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3335744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek # Scan each report file and build an index. 3345744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3355744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my @Index; 3365744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3375744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); } 3385744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3395744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek # Generate an index.html file. 3405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3415744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $FName = "$Dir/index.html"; 3425744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 34323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek open(OUT, ">$FName") or DieDiag("Cannot create file '$FName'\n"); 3445744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3456e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the header. 3466e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3475744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT; 3485744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html> 3495744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head> 3507f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<style type="text/css"> 3517f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek body { color:#000000; background-color:#ffffff } 35222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek body { font-family: Helvetica, sans-serif; font-size:9pt } 3537f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek h1 { font-size:12pt } 35422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable thead { 35522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek background-color:#eee; color:#666666; 35622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek font-weight: bold; cursor: default; 357bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek text-align:center; 358bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek border-top: 2px solid #000000; 359bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek border-bottom: 2px solid #000000; 360bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek font-weight: bold; font-family: Verdana 361bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek } 36222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border: 1px #000000 solid } 36322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border-collapse: collapse; border-spacing: 0px } 3647f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek td { border-bottom: 1px #000000 dotted } 36522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td { padding:5px; padding-left:8px; padding-right:8px } 366d8c6d0c8a5f970240cc4cbf8eddeae037d1b29eaTed Kremenek td { text-align:left; font-size:9pt } 36722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td.View { padding-left: 10px } 3687f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</style> 36922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script> 3706e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript"> 3716e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal) 3726e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{ 3736e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek var Rows = document.getElementsByTagName("tr"); 3746e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for ( var i = 0 ; i < Rows.length; ++i ) { 3756e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (Rows[i].className == RowClass) { 3766e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek Rows[i].style.display = DisplayVal; 3776e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3786e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3796e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 3806e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3816e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) { 3826e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (CheckButton.checked) { 3836e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, ""); 3846e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3856e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek else { 3866e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, "none"); 3876e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3886e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 3896e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script> 3906e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head> 3916e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body> 3926e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 3936e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3946e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the summary table. 3956e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3966e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek my %Totals; 3976e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3986e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for my $row ( @Index ) { 3996e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 400432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek #my $bug_type = lc($row->[1]); 401432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek my $bug_type = ($row->[1]); 4026e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4036e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (!defined($Totals{$bug_type})) { 4046e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek $Totals{$bug_type} = 1; 4056e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4066e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek else { 4076e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek $Totals{$bug_type}++; 4086e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4096e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 410f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 411f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print OUT "<h3>Summary</h3>"; 412f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 413f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek if (defined($BuildName)) { 414f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n" 415f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek } 416f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 4176e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 4186e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<table class="sortable"> 4196e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<tr> 4206e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td>Bug Type</td> 4216e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td>Quantity</td> 4226e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td "sorttable_nosort">Display?</td> 4236e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</tr> 4246e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 4256e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4266e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for my $key ( sort { $a cmp $b } keys %Totals ) { 427bdf66c7373159aa80403d313629330fd11d4c48aTed Kremenek my $x = lc($key); 428bdf66c7373159aa80403d313629330fd11d4c48aTed Kremenek $x =~ s/\s[,]/_/g; 4296e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek print OUT "<tr><td>$key</td><td>$Totals{$key}</td><td><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></td></tr>\n"; 4306e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4316e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4326e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the table of errors. 4336e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4346e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 4356e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table> 4366e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<h3>Reports</h3> 43722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<table class="sortable"> 4387f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<tr> 439bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Bug Type</td> 440bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>File</td> 441bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Line</td> 442bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Path Length</td> 443bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td "sorttable_nosort"></td> 4447f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</tr> 4455744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT 4469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4477a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $prefix = GetPrefix(); 4487a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $regex; 4497a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $InFileRegex; 4507a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $InFilePrefix = "File:</td><td>"; 4517a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 4527a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek if (defined($prefix)) { 4537a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $regex = qr/^\Q$prefix\E/is; 4547a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is; 4557a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 4567a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 4575744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek for my $row ( sort { $a->[1] cmp $b->[1] } @Index ) { 4585744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4596e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek my $x = lc($row->[1]); 460bdf66c7373159aa80403d313629330fd11d4c48aTed Kremenek $x =~ s/\s[,]/_/g; 4616e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4626e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek print OUT "<tr class=\"bt_$x\">\n"; 4635744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4645744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $ReportFile = $row->[0]; 4659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 46622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT " <td class=\"DESC\">"; 467432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek #print OUT lc($row->[1]); 468432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek print OUT $row->[1]; 46922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT "</td>\n"; 4705744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4717a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek # Update the file prefix. 4727a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 4737a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $fname = $row->[2]; 4747a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek if (defined($regex)) { 4757a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $fname =~ s/$regex//; 4767a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix) 4777a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 4783e56e0b8b285e86eed4d191b1da93ded7382a847Ted Kremenek 4797a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek print OUT "<td>$fname</td>\n"; 4807a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 4817a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek # Print the rest of the columns. 4827a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 4837a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek for my $j ( 3 .. $#{$row} ) { 4845744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "<td>$row->[$j]</td>\n" 4855744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 4867f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 4877f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # Emit the "View" link. 4887f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 48922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT " <td class=\"View\"><a href=\"$ReportFile#EndPath\">View</a></td>\n"; 4905744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4917f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # End the row. 4925744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "</tr>\n"; 4935744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 4945744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4955744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "</table>\n</body></html>\n"; 4965744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(OUT); 49722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 49822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek CopyJS($Dir); 499684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek 500684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek # Make sure $Dir and $BaseDir is world readable/executable. 501684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek `chmod 755 $Dir`; 502684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek `chmod 755 $BaseDir`; 50323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 50423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek my $Num = scalar(@Index); 50523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("$Num bugs found.\n") 5069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 5079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 509dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command. 510dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 511dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 5126b6289848e215ff12d4d54fe0602d3371db52788Ted Kremeneksub AddIfNotPresent { 5136b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $Args = shift; 5146b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $Arg = shift; 5156b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $found = 0; 5166b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 5176b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek foreach my $k (@$Args) { 5186b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($k eq $Arg) { 5196b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek $found = 1; 5206b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek last; 5216b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 5226b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 5236b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 5246b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($found == 0) { 5256b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek push @$Args, $Arg; 5266b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 5276b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek} 5286b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 529dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremeneksub RunBuildCommand { 530dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 531dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Args = shift; 5327442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek my $IgnoreErrors = shift; 533dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Cmd = $Args->[0]; 5346195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek my $CCAnalyzer = shift; 535dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 5366a43ba9cd247811b6d48ffbd4ee3c911c8c4b458Ted Kremenek if ($Cmd eq "gcc" or $Cmd eq "cc" or $Cmd eq "llvm-gcc") { 537dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek shift @$Args; 5386195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek unshift @$Args, $CCAnalyzer; 539dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek } 5407442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($IgnoreErrors) { 5417442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek if ($Cmd eq "make" or $Cmd eq "gmake") { 5426b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-k"); 5438912b5427a22d9032cad959c5c22cd9d28d4a66cTed Kremenek AddIfNotPresent($Args,"-i"); 5447442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 5457442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($Cmd eq "xcodebuild") { 5466b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES"); 5477442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 5486b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 5496b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 5506b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($Cmd eq "xcodebuild") { 551cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek # Disable distributed builds for xcodebuild. 5526b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-nodistribute"); 553cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek 554cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek # Disable PCH files until clang supports them. 555cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO"); 556915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek 557915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # When 'CC' is set, xcodebuild uses it to do all linking, even if we are 558915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # linking C++ object files. Set 'LDPLUSPLUS' so that xcodebuild uses 'g++' 559915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # when linking such files. 560915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek my $LDPLUSPLUS = `which g++`; 561915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek $LDPLUSPLUS =~ s/\015?\012//; # strip newlines 562915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS; 5636b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 564dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 565dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek system(@$Args); 566dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek} 567dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 568dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 5699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options. 5709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 5719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 572a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp { 5739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5745744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT; 575a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options] 5762b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 577f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted KremenekENDTEXT 578f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 579f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek if (defined($BuildName)) { 580f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n"; 581f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek } 582f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 583f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekprint <<ENDTEXT; 5842b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS: 5852b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 5861262fc4d66584224234691d30d779f8ff004585cTed Kremenek -a - The analysis to run. The default is 'checker-cfref'. 5871262fc4d66584224234691d30d779f8ff004585cTed Kremenek Valid options are: 'checker-cfref', 'fsyntax-only' 5881262fc4d66584224234691d30d779f8ff004585cTed Kremenek 5892b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek -o - Target directory for HTML report files. Subdirectories 590a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop will be created as needed to represent separate "runs" of 5912b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek the analyzer. If this option is not specified, a directory 5922b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek is created in /tmp to store the reports. 5931262fc4d66584224234691d30d779f8ff004585cTed Kremenek 59410f883fe7ef74139f8778e49acacf0ce408e7088Ted Kremenek -h - Display this message. 5952b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek --help 5961262fc4d66584224234691d30d779f8ff004585cTed Kremenek 597af08f64abc38af5914d96106aeb014a2e06eb865Ted Kremenek -k - Add a "keep on going" option to the specified build command. 598f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek --keep-going This option currently supports make and xcodebuild. 599f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek This is a convenience option; one can specify this 600f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek behavior directly using build options. 6012b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 602dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek -v - Verbose output from $Prog and the analyzer. 603dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek A second "-v" increases verbosity. 6042b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 6057f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek -V - View analysis results in a web browser when the build 6067f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek --view completes. 6077f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 6082b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS 6092b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 61039eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek You can specify any build option acceptable to the build command. 61139eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek 6125744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE 6132b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 6145744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek $Prog -o /tmp/myhtmldir make -j4 6152b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 61639eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek The above example causes analysis reports to be deposited into 61739eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option. 61839eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek A different subdirectory is created each time $Prog analyzes a project. 61939eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek The analyzer should support most parallel builds, but not distributed builds. 6202b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 6212b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT 6229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 6239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 6259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments. 6269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 6279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir; # Parent directory to store HTML files. 6299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0; # Ignore build errors. 6307f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults = 0; # View results when the build terminates. 6311262fc4d66584224234691d30d779f8ff004585cTed Kremenekmy $Analysis = "checker-cfref"; 6329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 6349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 635a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 6369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 6379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) { 6399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Scan for options we recognize. 6419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $arg = $ARGV[0]; 6439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6442f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop if ($arg eq "-h" or $arg eq "--help") { 6459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 646a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 0; 6479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6491262fc4d66584224234691d30d779f8ff004585cTed Kremenek if ($arg eq "-a") { 6501262fc4d66584224234691d30d779f8ff004585cTed Kremenek shift @ARGV; 6511262fc4d66584224234691d30d779f8ff004585cTed Kremenek 6521262fc4d66584224234691d30d779f8ff004585cTed Kremenek if (!@ARGV) { 65323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("'-a' option requires an analysis type.\n"); 6541262fc4d66584224234691d30d779f8ff004585cTed Kremenek } 6551262fc4d66584224234691d30d779f8ff004585cTed Kremenek 6561262fc4d66584224234691d30d779f8ff004585cTed Kremenek $Analysis = shift @ARGV; 6571262fc4d66584224234691d30d779f8ff004585cTed Kremenek 6581262fc4d66584224234691d30d779f8ff004585cTed Kremenek if (!($Analysis eq "checker-cfref" or $Analysis eq "fsyntax-only")) { 65923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Invalid argument '$Analysis' to -a.\n"); 6601262fc4d66584224234691d30d779f8ff004585cTed Kremenek } 6611262fc4d66584224234691d30d779f8ff004585cTed Kremenek 6621262fc4d66584224234691d30d779f8ff004585cTed Kremenek next; 6631262fc4d66584224234691d30d779f8ff004585cTed Kremenek } 6641262fc4d66584224234691d30d779f8ff004585cTed Kremenek 6659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-o") { 6669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 6679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!@ARGV) { 66923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("'-o' option requires a target directory name.\n"); 6709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $HtmlDir = shift @ARGV; 6739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 6749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6762b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek if ($arg eq "-k" or $arg eq "--keep-going") { 6779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 6789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $IgnoreErrors = 1; 6799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 6809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-v") { 6839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 6849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $Verbose++; 6859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 6869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 6879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6887f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek if ($arg eq "-V" or $arg eq "--view") { 6897f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek shift @ARGV; 6907f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek $ViewResults = 1; 6917f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek next; 6927f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek } 6937f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 69423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/); 6950062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek 6969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek last; 6979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 6989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 70023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("No build command specified.\n\n"); 7019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 702a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 7039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 7049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports. 7069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!defined($HtmlDir)) { 7089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 709a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop $HtmlDir = mkdtemp("/tmp/$Prog-XXXXXX"); 7109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!defined($HtmlDir)) { 71223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Cannot create HTML directory in /tmp.\n"); 7139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 7149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!$Verbose) { 71623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("Using '$HtmlDir' as base HTML report directory.\n"); 7179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 7189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 7199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 720684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir; 721a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir); 7229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Set the appropriate environment variables. 7249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 725a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopSetHtmlEnv(\@ARGV, $HtmlDir); 7269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7270b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekmy $Cmd = "$RealBin/ccc-analyzer"; 7280b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 72923cfca3760c482f8543daab62051f5eaa1f98fb4Ted KremenekDieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n") 7300b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek if (! -x $Cmd); 731f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek 732f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenekmy $Clang = "$RealBin/clang"; 733f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek 734f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenekif (! -x $Clang) { 73523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("'clang' executable not found in '$RealBin'. Using 'clang' from path.\n"); 736f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek $Clang = "clang"; 737f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek} 7380b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 7394f4b17da43d3be87a248e1e10bf0b7d8b5891efdTed Kremenek$ENV{'CC'} = $Cmd; 740f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek$ENV{'CLANG'} = $Clang; 7419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif ($Verbose >= 2) { 7439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_VERBOSE'} = 1; 7449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 7459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 746a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenekif ($Verbose >= 3) { 747a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek $ENV{'CCC_ANALYZER_LOG'} = 1; 748a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek} 749a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek 7501262fc4d66584224234691d30d779f8ff004585cTed Kremenek$ENV{'CCC_ANALYZER_ANALYSIS'} = $Analysis; 7511262fc4d66584224234691d30d779f8ff004585cTed Kremenek 7529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build. 7539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7546195c373b86963b029a2d1d2501f899789d74ba8Ted KremenekRunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd); 7559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess the HTML directory. 7579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 758684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted KremenekPostprocess($HtmlDir, $BaseDir); 7597f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 7607f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekif ($ViewResults and -r "$HtmlDir/index.html") { 7617f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # Only works on Mac OS X (for now). 7627f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek print "Viewing analysis results: '$HtmlDir/index.html'\n"; 7637f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek `open $HtmlDir/index.html` 7647f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek} 765