scan-build revision f22eacb11b50e647e7d08531ca5648d3c84c38c3
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); 199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Verbose = 0; # Verbose output from this script. 219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Prog = "scan-build"; 229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current run. 259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 27a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir { 289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "Not enough arguments." if (@_ == 0); 309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift @_; 329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Get current date and time. 349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @CurrentTime = localtime(); 369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $year = $CurrentTime[5] + 1900; 389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $day = $CurrentTime[3]; 399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $month = $CurrentTime[4] + 1; 409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $DateString = "$year-$month-$day"; 429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Determine the run number. 449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $RunNumber; 469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-d $Dir) { 489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -r $Dir) { 50a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop die "error: '$Dir' exists but is not readable.\n"; 519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Iterate over all files in the specified directory. 549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $max = 0; 569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @FILES= readdir(DIR); 599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek foreach my $f (@FILES) { 629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @x = split/-/, $f; 649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if (scalar(@x) != 4); 669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[0] != $year); 679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[1] != $month); 689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[2] != $day); 699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($x[3] > $max) { 719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $max = $x[3]; 729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = $max + 1; 769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek else { 789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-x $Dir) { 80a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop die "error: '$Dir' exists but is not a directory.\n"; 819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # $Dir does not exist. It will be automatically created by the 849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # clang driver. Set the run number to 1. 859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = 1; 879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "RunNumber must be defined!" if (!defined($RunNumber)); 909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Append the run number. 929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return "$Dir/$DateString-$RunNumber"; 949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 96a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv { 979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "Wrong number of arguments." if (scalar(@_) != 2); 999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Args = shift; 1019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 1029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "No build command." if (scalar(@$Args) == 0); 1049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Cmd = $$Args[0]; 1069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Cmd =~ /configure/) { 1089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 1099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Verbose) { 1129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek print "$Prog: Emitting reports for this run to '$Dir'.\n"; 1139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_HTML'} = $Dir; 1169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 1179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 11957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file. 12057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 12157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 12257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest { 12357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $FName = shift; 12457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek die "Cannot read $FName" if (! -r $FName); 12557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $Result = `sha1sum -b $FName`; 12657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my @Output = split /\s+/,$Result; 12757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek die "Bad output from sha1sum" if (scalar(@Output) != 2); 12857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek return $Output[0]; 12957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek} 13057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 13157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 1325744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes. 1335744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 1345744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 13557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces 13657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports. We use a cache to solve this problem. 13757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 13857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned; 13957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 1405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile { 1415744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 1425744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Index = shift; 1435744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Dir = shift; 1445744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $FName = shift; 1455744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 14657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Compute a digest for the report file. Determine if we have already 14757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # scanned a file that looks just like it. 14857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 14957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $digest = ComputeDigest("$Dir/$FName"); 15057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 15157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek if (defined($AlreadyScanned{$digest})) { 15257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Redundant file. Remove it. 15357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek `rm -f $Dir/$FName`; 15457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek return; 15557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek } 15657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 15757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek $AlreadyScanned{$digest} = 1; 15857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 159809709f46f2516b4054681f0b76284055a84a50fTed Kremenek # At this point the report file is not world readable. Make it happen. 160684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek `chmod 644 $Dir/$FName`; 161684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek 162684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek # Scan the report file for tags. 1635744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek open(IN, "$Dir/$FName") or die "$Prog: Cannot open '$Dir/$FName'\n"; 1645744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 1655744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $BugDesc = ""; 16622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugFile = ""; 16722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugPathLength = 1; 16822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugLine = 0; 1695744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 1705744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek while (<IN>) { 1715744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 1725744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek if (/<!-- BUGDESC (.*) -->$/) { 1735744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek $BugDesc = $1; 1745744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 17522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGFILE (.*) -->$/) { 17622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugFile = $1; 17722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 17822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGPATHLENGTH (.*) -->$/) { 17922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugPathLength = $1; 18022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 18122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGLINE (.*) -->$/) { 18222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugLine = $1; 18322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 1845744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 1855744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 1865744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(IN); 1875744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 18822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek push @$Index,[ $FName, $BugDesc, $BugFile, $BugLine, $BugPathLength ]; 18922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek} 19022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 19122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 19222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek# CopyJS - Copy JavaScript code to target directory. 19322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 19422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 19522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremeneksub CopyJS { 19622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 19722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $Dir = shift; 19822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 19922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek die "$Prog: Cannot find 'sorttable.js'.\n" 20022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$RealBin/sorttable.js"); 20122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 20222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek `cp $RealBin/sorttable.js $Dir`; 20322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 20422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek die "$Prog: Could not copy 'sorttable.js' to '$Dir'." 20522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$Dir/sorttable.js"); 2065744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek} 2075744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2085744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 2099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan. 2109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 2119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 212a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess { 2139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 215684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek my $BaseDir = shift; 2169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "No directory specified." if (!defined($Dir)); 218684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek die "No base directory specified." if (!defined($BaseDir)); 2199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -d $Dir) { 2219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 2229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 2239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 2259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @files = grep(/^report-.*\.html$/,readdir(DIR)); 2269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 2279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (scalar(@files) == 0) { 22902493782bd4620969041921f2a842528ffdfc940Ted Kremenek print "$Prog: Removing directory '$Dir' because it contains no reports.\n"; 2309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek `rm -fR $Dir`; 2319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 2329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 2335744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2345744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek # Scan each report file and build an index. 2355744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2365744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my @Index; 2375744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2385744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); } 2395744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek # Generate an index.html file. 2415744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2425744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $FName = "$Dir/index.html"; 2435744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2445744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek open(OUT, ">$FName") or die "$Prog: Cannot create file '$FName'\n"; 2455744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 2466e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the header. 2476e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 2485744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT; 2495744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html> 2505744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head> 2517f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<style type="text/css"> 2527f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek body { color:#000000; background-color:#ffffff } 25322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek body { font-family: Helvetica, sans-serif; font-size:9pt } 2547f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek h1 { font-size:12pt } 25522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable thead { 25622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek background-color:#eee; color:#666666; 25722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek font-weight: bold; cursor: default; 258bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek text-align:center; 259bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek border-top: 2px solid #000000; 260bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek border-bottom: 2px solid #000000; 261bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek font-weight: bold; font-family: Verdana 262bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek } 26322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border: 1px #000000 solid } 26422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border-collapse: collapse; border-spacing: 0px } 2657f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek td { border-bottom: 1px #000000 dotted } 26622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td { padding:5px; padding-left:8px; padding-right:8px } 267d8c6d0c8a5f970240cc4cbf8eddeae037d1b29eaTed Kremenek td { text-align:left; font-size:9pt } 26822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td.View { padding-left: 10px } 2697f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</style> 27022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script> 2716e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript"> 2726e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal) 2736e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{ 2746e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek var Rows = document.getElementsByTagName("tr"); 2756e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for ( var i = 0 ; i < Rows.length; ++i ) { 2766e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (Rows[i].className == RowClass) { 2776e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek Rows[i].style.display = DisplayVal; 2786e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 2796e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 2806e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 2816e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 2826e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) { 2836e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek window.console.log("writing"); 2846e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (CheckButton.checked) { 2856e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, ""); 2866e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 2876e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek else { 2886e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, "none"); 2896e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 2906e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 2916e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script> 2926e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head> 2936e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body> 2946e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 2956e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 2966e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the summary table. 2976e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 2986e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek my %Totals; 2996e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3006e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for my $row ( @Index ) { 3016e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3026e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek my $bug_type = lc($row->[1]); 3036e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3046e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (!defined($Totals{$bug_type})) { 3056e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek $Totals{$bug_type} = 1; 3066e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3076e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek else { 3086e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek $Totals{$bug_type}++; 3096e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3106e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3116e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3126e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 3136e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<h3>Summary</h3> 3146e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<table class="sortable"> 3156e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<tr> 3166e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td>Bug Type</td> 3176e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td>Quantity</td> 3186e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td "sorttable_nosort">Display?</td> 3196e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</tr> 3206e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 3216e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3226e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for my $key ( sort { $a cmp $b } keys %Totals ) { 3236e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek my $x = $key; 3246e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek $x =~ s/\s/_/g; 3256e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek print OUT "<tr><td>$key</td><td>$Totals{$key}</td><td><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></td></tr>\n"; 3266e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 3276e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3286e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the table of errors. 3296e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3306e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 3316e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table> 3326e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<h3>Reports</h3> 33322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<table class="sortable"> 3347f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<tr> 335bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Bug Type</td> 336bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>File</td> 337bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Line</td> 338bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Path Length</td> 339bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td "sorttable_nosort"></td> 3407f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</tr> 3415744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT 3429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3435744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek for my $row ( sort { $a->[1] cmp $b->[1] } @Index ) { 3445744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3456e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek my $x = lc($row->[1]); 3466e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek $x =~ s/\s/_/g; 3476e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 3486e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek print OUT "<tr class=\"bt_$x\">\n"; 3495744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3505744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $ReportFile = $row->[0]; 3519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 35222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT " <td class=\"DESC\">"; 35322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT lc($row->[1]); 35422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT "</td>\n"; 3555744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3565744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek for my $j ( 2 .. $#{$row} ) { 3575744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "<td>$row->[$j]</td>\n" 3585744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 3597f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 3607f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # Emit the "View" link. 3617f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 36222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT " <td class=\"View\"><a href=\"$ReportFile#EndPath\">View</a></td>\n"; 3635744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3647f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # End the row. 3655744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "</tr>\n"; 3665744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 3675744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3685744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "</table>\n</body></html>\n"; 3695744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(OUT); 37022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 37122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek CopyJS($Dir); 372684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek 373684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek # Make sure $Dir and $BaseDir is world readable/executable. 374684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek `chmod 755 $Dir`; 375684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek `chmod 755 $BaseDir`; 3769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 3779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 379dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command. 380dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 381dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 382dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremeneksub RunBuildCommand { 383dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 384dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Args = shift; 3857442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek my $IgnoreErrors = shift; 386dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Cmd = $Args->[0]; 387dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 3886a43ba9cd247811b6d48ffbd4ee3c911c8c4b458Ted Kremenek if ($Cmd eq "gcc" or $Cmd eq "cc" or $Cmd eq "llvm-gcc") { 389dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek shift @$Args; 390dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek unshift @$Args, "ccc-analyzer" 391dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek } 3927442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($IgnoreErrors) { 3937442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek if ($Cmd eq "make" or $Cmd eq "gmake") { 3947442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek push @$Args, "-k"; 3957442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 3967442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($Cmd eq "xcodebuild") { 3977442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek push @$Args, "-PBXBuildsContinueAfterErrors=YES"; 3987442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 39922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 400dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 401dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek system(@$Args); 402dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek} 403dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 404dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 4059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options. 4069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 4079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 408a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp { 4099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4105744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT; 411a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options] 4122b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 4132b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS: 4142b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 4152b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek -o - Target directory for HTML report files. Subdirectories 416a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop will be created as needed to represent separate "runs" of 4172b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek the analyzer. If this option is not specified, a directory 4182b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek is created in /tmp to store the reports. 4192b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 42010f883fe7ef74139f8778e49acacf0ce408e7088Ted Kremenek -h - Display this message. 4212b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek --help 4222b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 423af08f64abc38af5914d96106aeb014a2e06eb865Ted Kremenek -k - Add a "keep on going" option to the specified build command. 424f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek --keep-going This option currently supports make and xcodebuild. 425f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek This is a convenience option; one can specify this 426f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek behavior directly using build options. 4272b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 428dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek -v - Verbose output from $Prog and the analyzer. 429dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek A second "-v" increases verbosity. 4302b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 4317f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek -V - View analysis results in a web browser when the build 4327f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek --view completes. 4337f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 4342b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS 4352b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 43639eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek You can specify any build option acceptable to the build command. 43739eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek 4385744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE 4392b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 4405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek $Prog -o /tmp/myhtmldir make -j4 4412b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 44239eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek The above example causes analysis reports to be deposited into 44339eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option. 44439eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek A different subdirectory is created each time $Prog analyzes a project. 44539eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek The analyzer should support most parallel builds, but not distributed builds. 4462b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 4472b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT 4489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 4499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 4519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments. 4529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 4539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir; # Parent directory to store HTML files. 4559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0; # Ignore build errors. 4567f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults = 0; # View results when the build terminates. 4579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 4599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 460a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 4619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 4629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) { 4649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Scan for options we recognize. 4669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $arg = $ARGV[0]; 4689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4692f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop if ($arg eq "-h" or $arg eq "--help") { 4709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 471a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 0; 4729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 4739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-o") { 4759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 4769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!@ARGV) { 4780062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek die "$Prog: '-o' option requires a target directory name.\n"; 4799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 4809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $HtmlDir = shift @ARGV; 4829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 4839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 4849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4852b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek if ($arg eq "-k" or $arg eq "--keep-going") { 4869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 4879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $IgnoreErrors = 1; 4889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 4899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 4909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-v") { 4929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 4939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $Verbose++; 4949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 4959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 4969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4977f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek if ($arg eq "-V" or $arg eq "--view") { 4987f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek shift @ARGV; 4997f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek $ViewResults = 1; 5007f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek next; 5017f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek } 5027f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 5030062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek die "$Prog: unrecognized option '$arg'\n" if ($arg =~ /^-/); 5040062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek 5059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek last; 5069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 5079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 5099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek print STDERR "$Prog: No build command specified.\n\n"; 5109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 511a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 5129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 5139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports. 5159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!defined($HtmlDir)) { 5179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 518a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop $HtmlDir = mkdtemp("/tmp/$Prog-XXXXXX"); 5199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!defined($HtmlDir)) { 521a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop die "error: Cannot create HTML directory in /tmp.\n"; 5229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 5239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!$Verbose) { 5259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek print "$Prog: Using '$HtmlDir' as base HTML report directory.\n"; 5269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 5279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 5289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 529684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir; 530a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir); 5319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Set the appropriate environment variables. 5339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 534a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopSetHtmlEnv(\@ARGV, $HtmlDir); 5359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5360b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekmy $Cmd = "$RealBin/ccc-analyzer"; 5370b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 5380b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekdie "$Prog: Executable 'ccc-analyzer' does not exist at '$Cmd'\n" 5390b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek if (! -x $Cmd); 540f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek 541f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenekmy $Clang = "$RealBin/clang"; 542f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek 543f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenekif (! -x $Clang) { 544f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek print "$Prog: 'clang' executable not found in '$RealBin'. Using 'clang' from path.\n"; 545f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek $Clang = "clang"; 546f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek} 5470b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 5484f4b17da43d3be87a248e1e10bf0b7d8b5891efdTed Kremenek$ENV{'CC'} = $Cmd; 549f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek$ENV{'CLANG'} = $Clang; 5509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif ($Verbose >= 2) { 5529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_VERBOSE'} = 1; 5539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 5549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build. 5569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5577442ca6b274f1a935c31e34221fbd0a68077ddc5Ted KremenekRunBuildCommand(\@ARGV, $IgnoreErrors); 5589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess the HTML directory. 5609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 561684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted KremenekPostprocess($HtmlDir, $BaseDir); 5627f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 5637f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekif ($ViewResults and -r "$HtmlDir/index.html") { 5647f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # Only works on Mac OS X (for now). 5657f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek print "Viewing analysis results: '$HtmlDir/index.html'\n"; 5667f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek `open $HtmlDir/index.html` 5677f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek} 568