scan-build revision 386c69316668b9ea8c2591af56f994be16e3ff62
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; 1722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenekuse FindBin qw($RealBin); 18a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenekuse Digest::MD5; 197a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekuse File::Basename; 2023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenekuse Term::ANSIColor; 2123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenekuse Term::ANSIColor qw(:constants); 229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Verbose = 0; # Verbose output from this script. 249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Prog = "scan-build"; 25f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildName; 26f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildDate; 27386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenekmy $CXX = 'g++'; 289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 29f2f8d6c4718564dab73df3b5aa2d0be21bc6a163Ted Kremenekmy $UseColor = ((($ENV{'TERM'} eq 'xterm-color') and -t STDOUT) 30f2f8d6c4718564dab73df3b5aa2d0be21bc6a163Ted Kremenek and defined($ENV{'SCAN_BUILD_COLOR'})); 3123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 32b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------## 33b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Diagnostics 34b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------## 35b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 3623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub Diag { 3723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek if ($UseColor) { 3823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print BOLD, MAGENTA "$Prog: @_"; 3923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET; 4023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 4123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek else { 4223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print "$Prog: @_"; 4323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 4423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek} 4523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 46991c54b9b7409656e5593364e065878b5210d556Ted Kremeneksub DiagCrashes { 47991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $Dir = shift; 48991c54b9b7409656e5593364e065878b5210d556Ted Kremenek Diag ("The analyzer crashed on some source files.\n"); 49386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek Diag ("Preprocessed versions of crashed files were deposited in '$Dir/crashes'.\n"); 50991c54b9b7409656e5593364e065878b5210d556Ted Kremenek Diag ("Please consider submitting a bug report using these files:\n"); 51991c54b9b7409656e5593364e065878b5210d556Ted Kremenek Diag (" http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\n") 52991c54b9b7409656e5593364e065878b5210d556Ted Kremenek} 53991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 5423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub DieDiag { 5523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek if ($UseColor) { 5623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print BOLD, RED "$Prog: "; 5723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET, RED @_; 5823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET; 5923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 6023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek else { 6123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print "$Prog: ", @_; 6223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 6323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek exit(0); 6423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek} 6523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 67b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Some initial preprocessing of Clang options. 68b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------## 69b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 70b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $ClangSB = "$RealBin/clang"; 71b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $Clang = $ClangSB; 72b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 73b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekif (! -x $ClangSB) { 74b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek $Clang = "clang"; 75b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek} 76b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 77b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy %AvailableAnalyses; 78b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 79b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Query clang for analysis options. 8063c2017737530a7009f709f2fe822f20f63930b1Ted Kremenekopen(PIPE, "-|", $Clang, "--help") or 81b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek DieDiag("Cannot execute '$Clang'"); 8263c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 83b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $FoundAnalysis = 0; 84b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 85b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekwhile(<PIPE>) { 86b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek if ($FoundAnalysis == 0) { 87b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek if (/Available Source Code Analyses/) { 88b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek $FoundAnalysis = 1; 89b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 90991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 91b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek next; 92b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 93b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 94b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek if (/^\s\s\s\s([^\s]+)\s(.+)$/) { 95b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek next if ($1 =~ /-dump/ or $1 =~ /-view/ 96b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek or $1 =~ /-checker-simple/ or $1 =~ /-warn-uninit/); 97b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 98b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek $AvailableAnalyses{$1} = $2; 99b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek next; 100b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 101b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 102b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek last; 103b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek} 104b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 105b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekclose (PIPE); 106b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 107b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy %AnalysesDefaultEnabled = ( 108b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek '-warn-dead-stores' => 1, 109b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek '-checker-cfref' => 1, 1109012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek '-warn-objc-methodsigs' => 1, 111bde3a051933b6829ed79d6db0118231c2c01b105Ted Kremenek '-warn-objc-missing-dealloc' => 1, 112bde3a051933b6829ed79d6db0118231c2c01b105Ted Kremenek '-warn-objc-unused-ivars' => 1 113b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek); 114b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 115b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------## 116fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current sub-run. 1179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 1189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 119a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir { 1209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 121fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek die "Not enough arguments." if (@_ == 0); 1229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift @_; 123fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 124fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek my $TmpMode = 0; 125fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (!defined $Dir) { 126fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek $Dir = "/tmp"; 127fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek $TmpMode = 1; 128fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 129fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Get current date and time. 1319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @CurrentTime = localtime(); 1339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $year = $CurrentTime[5] + 1900; 1359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $day = $CurrentTime[3]; 1369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $month = $CurrentTime[4] + 1; 1379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1389d7405fafd5bc08d38bc75579927bf414570bd61Ted Kremenek my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day); 1399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Determine the run number. 1419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $RunNumber; 1439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-d $Dir) { 1459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -r $Dir) { 14723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("directory '$Dir' exists but is not readable.\n"); 1489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Iterate over all files in the specified directory. 1519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $max = 0; 1539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 15529da6c59df7ca994e75139303a9230b24e2abaadTed Kremenek my @FILES = grep { -d "$Dir/$_" } readdir(DIR); 1569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 1579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek foreach my $f (@FILES) { 1599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 160fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek # Strip the prefix '$Prog-' if we are dumping files to /tmp. 161fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if ($TmpMode) { 162fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek next if (!($f =~ /^$Prog-(.+)/)); 163fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek $f = $1; 164fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 165fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @x = split/-/, $f; 167fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if (scalar(@x) != 4); 1699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[0] != $year); 1709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[1] != $month); 1719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[2] != $day); 1729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($x[3] > $max) { 1749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $max = $x[3]; 1759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = $max + 1; 1799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek else { 1819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-x $Dir) { 18323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("'$Dir' exists but is not a directory.\n"); 1849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 185fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 186fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if ($TmpMode) { 187fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek DieDiag("The directory '/tmp' does not exist or cannot be accessed."); 188fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 189fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # $Dir does not exist. It will be automatically created by the 1919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # clang driver. Set the run number to 1. 192fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = 1; 1949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 196fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek die "RunNumber must be defined!" if (!defined $RunNumber); 1979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Append the run number. 199fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if ($TmpMode) { 200fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek my $NewDir = "$Dir/$Prog-$DateString-$RunNumber"; 201fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek mkdir $NewDir; 202fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek return $NewDir; 203fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 204fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek else { 205fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek return "$Dir/$DateString-$RunNumber"; 206fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 2079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 2089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 209a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv { 2109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "Wrong number of arguments." if (scalar(@_) != 2); 2129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Args = shift; 2149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 2159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "No build command." if (scalar(@$Args) == 0); 2179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Cmd = $$Args[0]; 2199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Cmd =~ /configure/) { 2219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 2229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 2239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Verbose) { 22523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("Emitting reports for this run to '$Dir'.\n"); 2269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 2279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_HTML'} = $Dir; 2299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 2309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 23257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file. 23357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 23457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 23557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest { 23657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $FName = shift; 23723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName); 238a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 239a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek # Use Digest::MD5. We don't have to be cryptographically secure. We're 2407ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek # just looking for duplicate files that come from a non-malicious source. 2417ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek # We use Digest::MD5 because it is a standard Perl module that should 24263c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek # come bundled on most systems. 24323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n"); 244a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek binmode FILE; 245a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest; 246a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek close(FILE); 247a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 24863c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek # Return the digest. 249a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek return $Result; 25057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek} 25157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 25257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 2537a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek# UpdatePrefix - Compute the common prefix of files. 2547a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2557a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2567a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekmy $Prefix; 2577a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2587a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdatePrefix { 2597a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $x = shift; 2607a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $y = basename($x); 2617a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $x =~ s/\Q$y\E$//; 2627a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2637a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek # Ignore /usr, /Library, /System, /Developer 2647a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return if ( $x =~ /^\/usr/ or $x =~ /^\/Library/ 2657a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek or $x =~ /^\/System/ or $x =~ /^\/Developer/); 2667a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2677a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek if (!defined $Prefix) { 2687a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $Prefix = $x; 2697a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return; 2707a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 2717a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2727a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek chop $Prefix while (!($x =~ /^$Prefix/)); 2737a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 2747a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2757a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub GetPrefix { 2767a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return $Prefix; 2777a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 2787a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2797a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2807a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek# UpdateInFilePath - Update the path in the report file. 2817a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2827a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2837a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdateInFilePath { 2847a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $fname = shift; 2857a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $regex = shift; 2867a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $newtext = shift; 28763c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 2887a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek open (RIN, $fname) or die "cannot open $fname"; 28963c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp"; 29063c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 2917a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek while (<RIN>) { 2927a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek s/$regex/$newtext/; 2937a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek print ROUT $_; 2947a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 29563c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 2967a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek close (ROUT); 2977a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek close (RIN); 29820161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system("mv", "$fname.tmp", $fname); 2997a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 3007a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 3017a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 3025744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes. 3035744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 3045744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 30557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces 30657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports. We use a cache to solve this problem. 30757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 30857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned; 30957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 3105744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile { 3115744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3125744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Index = shift; 3135744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Dir = shift; 3145744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $FName = shift; 3155744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 31657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Compute a digest for the report file. Determine if we have already 31757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # scanned a file that looks just like it. 31857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 31957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $digest = ComputeDigest("$Dir/$FName"); 32057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 321fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $AlreadyScanned{$digest}) { 32257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Redundant file. Remove it. 32320161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system ("rm", "-f", "$Dir/$FName"); 32457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek return; 32557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek } 32657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 32757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek $AlreadyScanned{$digest} = 1; 32857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 329809709f46f2516b4054681f0b76284055a84a50fTed Kremenek # At this point the report file is not world readable. Make it happen. 33020161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system ("chmod", "644", "$Dir/$FName"); 331684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek 332684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek # Scan the report file for tags. 33323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n"); 3345744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3355744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $BugDesc = ""; 33622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugFile = ""; 33722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugPathLength = 1; 33822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugLine = 0; 3395744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek while (<IN>) { 3415744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3425744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek if (/<!-- BUGDESC (.*) -->$/) { 3435744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek $BugDesc = $1; 3445744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 34522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGFILE (.*) -->$/) { 34622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugFile = $1; 3477a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek UpdatePrefix($BugFile); 34822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 34922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGPATHLENGTH (.*) -->$/) { 35022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugPathLength = $1; 35122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 35222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGLINE (.*) -->$/) { 35322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugLine = $1; 35422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 3555744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 3565744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3575744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(IN); 3585744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 35922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek push @$Index,[ $FName, $BugDesc, $BugFile, $BugLine, $BugPathLength ]; 36022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek} 36122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 36222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 36322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek# CopyJS - Copy JavaScript code to target directory. 36422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 36522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 36622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremeneksub CopyJS { 36722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 36822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $Dir = shift; 36922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 37023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Cannot find 'sorttable.js'.\n") 37122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$RealBin/sorttable.js"); 37222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 37320161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system ("cp", "$RealBin/sorttable.js", "$Dir"); 37422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 37523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n") 37622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$Dir/sorttable.js"); 3775744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek} 3785744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3795744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 3809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan. 3819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 3829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 383a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess { 3849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 386684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek my $BaseDir = shift; 3879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 388fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek die "No directory specified." if (!defined $Dir); 3899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -d $Dir) { 39123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("No bugs found.\n"); 392363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek return 0; 3939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 3949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 396991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $Crashes = 0; 397991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my @files = grep { if ($_ eq "crashes") { $Crashes++; } 398991c54b9b7409656e5593364e065878b5210d556Ted Kremenek /^report-.*\.html$/; } readdir(DIR); 3999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 4009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 401991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if (scalar(@files) == 0 and $Crashes == 0) { 40223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("Removing directory '$Dir' because it contains no reports.\n"); 40320161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system ("rm", "-fR", $Dir); 40423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek # Remove the base directory if it contains no files (don't use '-R'). 405991c54b9b7409656e5593364e065878b5210d556Ted Kremenek system ("rm", "-f", $BaseDir) if (defined $BaseDir); 406363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek return 0; 4079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 4085744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 409991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Scan each report file and build an index. 410991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my @Index; 4115744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); } 4125744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 413d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek # Scan the crashes directory and use the information in the .info files 414d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek # to update the common prefix directory. 415d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek if (-d "$Dir/crashes") { 416d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek opendir(DIR, "$Dir/crashes"); 417d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek my @files = grep { /[.]info$/; } readdir(DIR); 418d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek closedir(DIR); 419d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek foreach my $file (@files) { 420d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek open IN, "$Dir/crashes/$file" or DieDiag("cannot open $file\n"); 421d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek my $Path = <IN>; 422d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek if (defined $Path) { UpdatePrefix($Path); } 423d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek close IN; 424d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek } 425d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek } 426d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek 42763c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek # Generate an index.html file. 42863c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek my $FName = "$Dir/index.html"; 42963c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n"); 4305744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4316e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the header. 4326e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4335744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT; 4345744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html> 4355744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head> 4367f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<style type="text/css"> 4377f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek body { color:#000000; background-color:#ffffff } 43822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek body { font-family: Helvetica, sans-serif; font-size:9pt } 4397f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek h1 { font-size:12pt } 440991c54b9b7409656e5593364e065878b5210d556Ted Kremenek table thead { 44122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek background-color:#eee; color:#666666; 44222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek font-weight: bold; cursor: default; 443bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek text-align:center; 444bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek border-top: 2px solid #000000; 445bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek border-bottom: 2px solid #000000; 446bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek font-weight: bold; font-family: Verdana 447bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek } 448991c54b9b7409656e5593364e065878b5210d556Ted Kremenek table { border: 1px #000000 solid } 449991c54b9b7409656e5593364e065878b5210d556Ted Kremenek table { border-collapse: collapse; border-spacing: 0px } 4507f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek td { border-bottom: 1px #000000 dotted } 45122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td { padding:5px; padding-left:8px; padding-right:8px } 452d8c6d0c8a5f970240cc4cbf8eddeae037d1b29eaTed Kremenek td { text-align:left; font-size:9pt } 45322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td.View { padding-left: 10px } 4547f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</style> 45522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script> 4566e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript"> 4576e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal) 4586e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{ 4596e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek var Rows = document.getElementsByTagName("tr"); 4606e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for ( var i = 0 ; i < Rows.length; ++i ) { 4616e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (Rows[i].className == RowClass) { 4626e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek Rows[i].style.display = DisplayVal; 4636e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4646e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4656e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 4666e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4676e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) { 4686e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (CheckButton.checked) { 4696e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, ""); 4706e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4716e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek else { 4726e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, "none"); 4736e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4746e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 4756e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script> 4766e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head> 4776e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body> 4786e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 4796e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 480991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if (scalar(@files)) { 481991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Print out the summary table. 482991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my %Totals; 4836e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 484991c54b9b7409656e5593364e065878b5210d556Ted Kremenek for my $row ( @Index ) { 485991c54b9b7409656e5593364e065878b5210d556Ted Kremenek #my $bug_type = lc($row->[1]); 486991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $bug_type = ($row->[1]); 4876e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 488991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if (!defined $Totals{$bug_type}) { $Totals{$bug_type} = 1; } 489991c54b9b7409656e5593364e065878b5210d556Ted Kremenek else { $Totals{$bug_type}++; } 4906e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 491991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 492991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "<h3>Bug Summary</h3>"; 493991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 494991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if (defined $BuildName) { 495991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n" 4966e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 497f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 4986e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 4996e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<table class="sortable"> 5006e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<tr> 5016e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td>Bug Type</td> 5026e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td>Quantity</td> 5032645c77072d45fabb2bdc0a3621908035c7113dcTed Kremenek <td class="sorttable_nosort">Display?</td> 5046e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</tr> 5056e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 5066e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 507991c54b9b7409656e5593364e065878b5210d556Ted Kremenek for my $key ( sort { $a cmp $b } keys %Totals ) { 508991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $x = lc($key); 509991c54b9b7409656e5593364e065878b5210d556Ted Kremenek $x =~ s/[ ,'"]+/_/g; 510991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "<tr><td>$key</td><td>$Totals{$key}</td><td><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></td></tr>\n"; 511991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 5126e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 5136e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the table of errors. 5146e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 5156e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 5166e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table> 5176e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<h3>Reports</h3> 51822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<table class="sortable"> 5197f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<tr> 52088a96d6c3fe2b1b9d80b39c21cf7aca4aa9fcf08Ted Kremenek <td class="sorttable_sorted">Bug Type<span id="sorttable_sortfwdind"> ▾</span> 521bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>File</td> 522bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Line</td> 523bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Path Length</td> 5242645c77072d45fabb2bdc0a3621908035c7113dcTed Kremenek <td class="sorttable_nosort"></td> 5257f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</tr> 5265744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT 5279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 528991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $prefix = GetPrefix(); 529991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $regex; 530991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $InFileRegex; 531991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $InFilePrefix = "File:</td><td>"; 5327a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 533991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if (defined $prefix) { 534991c54b9b7409656e5593364e065878b5210d556Ted Kremenek $regex = qr/^\Q$prefix\E/is; 535991c54b9b7409656e5593364e065878b5210d556Ted Kremenek $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is; 536991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 5377a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 538991c54b9b7409656e5593364e065878b5210d556Ted Kremenek for my $row ( sort { $a->[1] cmp $b->[1] } @Index ) { 5395744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 540991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $x = lc($row->[1]); 541991c54b9b7409656e5593364e065878b5210d556Ted Kremenek $x =~ s/[ ,'"]+/_/g; 5426e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 543991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "<tr class=\"bt_$x\">\n"; 5445744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 545991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $ReportFile = $row->[0]; 5469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 547991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT " <td class=\"DESC\">"; 548991c54b9b7409656e5593364e065878b5210d556Ted Kremenek #print OUT lc($row->[1]); 549991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT $row->[1]; 550991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "</td>\n"; 5515744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 552991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Update the file prefix. 5537a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 554991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $fname = $row->[2]; 555991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if (defined $regex) { 556991c54b9b7409656e5593364e065878b5210d556Ted Kremenek $fname =~ s/$regex//; 557991c54b9b7409656e5593364e065878b5210d556Ted Kremenek UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix) 558991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 5593e56e0b8b285e86eed4d191b1da93ded7382a847Ted Kremenek 560991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "<td>$fname</td>\n"; 5617a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 562991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Print the rest of the columns. 563991c54b9b7409656e5593364e065878b5210d556Ted Kremenek for my $j ( 3 .. $#{$row} ) { 564991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "<td>$row->[$j]</td>\n" 565991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 5667f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 567991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Emit the "View" link. 568991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT " <td class=\"View\"><a href=\"$ReportFile#EndPath\">View</a></td>\n"; 5693cea9ee6b77ac797ebb910bdf45d1d7f8f68e37bTed Kremenek 570991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # End the row. 571991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "</tr>\n"; 572991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 573991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 574991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "</table>\n"; 575991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 576991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 577991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if ($Crashes) { 578991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Read the crash directory for files. 579991c54b9b7409656e5593364e065878b5210d556Ted Kremenek opendir(DIR, "$Dir/crashes"); 580991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my @files = grep { /[.]info$/ } readdir(DIR); 581991c54b9b7409656e5593364e065878b5210d556Ted Kremenek closedir(DIR); 582991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 583991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if (scalar(@files)) { 584991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT <<ENDTEXT; 5855d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek<h3>Analyzer Failures</h3> 586991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 5875d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek<p>The analyzer had problems processing the following files:</p> 588991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 589991c54b9b7409656e5593364e065878b5210d556Ted Kremenek<table> 5905d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek<thead><tr><td>Problem</td><td>Source File</td><td>Preprocessed File</td></tr></thead> 591991c54b9b7409656e5593364e065878b5210d556Ted KremenekENDTEXT 592991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 593991c54b9b7409656e5593364e065878b5210d556Ted Kremenek foreach my $file (sort @files) { 594991c54b9b7409656e5593364e065878b5210d556Ted Kremenek $file =~ /(.+).info$/; 595991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Get the preprocessed file. 596991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $ppfile = $1; 597991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Open the info file and get the name of the source file. 598991c54b9b7409656e5593364e065878b5210d556Ted Kremenek open (INFO, "$Dir/crashes/$file") or 599991c54b9b7409656e5593364e065878b5210d556Ted Kremenek die "Cannot open $Dir/crashes/$file\n"; 600991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $srcfile = <INFO>; 6015d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek chomp $srcfile; 6025d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek my $problem = <INFO>; 6035d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek chomp $problem; 604991c54b9b7409656e5593364e065878b5210d556Ted Kremenek close (INFO); 605991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Print the information in the table. 606d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek my $prefix = GetPrefix(); 607d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek if (defined $prefix) { $srcfile =~ s/^$prefix//; } 6085d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek print OUT "<tr><td>$problem</td><td>$srcfile</td><td class=\"View\"><a href=\"crashes/$ppfile\">View</a></td></tr>\n"; 609991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 610991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 611991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT <<ENDTEXT; 612991c54b9b7409656e5593364e065878b5210d556Ted Kremenek</table> 613991c54b9b7409656e5593364e065878b5210d556Ted Kremenek<p>Please consider submitting preprocessed files as <a href="http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs">bug reports</a>.</p> 614991c54b9b7409656e5593364e065878b5210d556Ted KremenekENDTEXT 615991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 6165744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 6175744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 618991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "</body></html>\n"; 6195744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(OUT); 62022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek CopyJS($Dir); 62120161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek 62220161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek # Make sure $Dir and $BaseDir are world readable/executable. 62320161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system("chmod", "755", $Dir); 624fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $BaseDir) { system("chmod", "755", $BaseDir); } 62520161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek 62623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek my $Num = scalar(@Index); 627150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek Diag("$Num bugs found.\n"); 628150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek if ($Num > 0 && -r "$Dir/index.html") { 629150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek Diag("Open '$Dir/index.html' to examine bug reports.\n"); 630150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek } 631363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 632991c54b9b7409656e5593364e065878b5210d556Ted Kremenek DiagCrashes($Dir) if ($Crashes); 633991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 634363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek return $Num; 6359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 6369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 638dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command. 639dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 640dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 6416b6289848e215ff12d4d54fe0602d3371db52788Ted Kremeneksub AddIfNotPresent { 6426b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $Args = shift; 6436b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $Arg = shift; 6446b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $found = 0; 6456b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 6466b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek foreach my $k (@$Args) { 6476b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($k eq $Arg) { 6486b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek $found = 1; 6496b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek last; 6506b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 6516b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 6526b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 6536b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($found == 0) { 6546b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek push @$Args, $Arg; 6556b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 6566b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek} 6576b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 658dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremeneksub RunBuildCommand { 659dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 660dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Args = shift; 6617442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek my $IgnoreErrors = shift; 662dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Cmd = $Args->[0]; 6636195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek my $CCAnalyzer = shift; 664dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 6653301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek # Get only the part of the command after the last '/'. 6663301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek if ($Cmd =~ /\/([^\/]+)$/) { 6673301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek $Cmd = $1; 6683301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek } 6693301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek 67063c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek if ($Cmd eq "gcc" or $Cmd eq "cc" or $Cmd eq "llvm-gcc" 67163c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek or $Cmd eq "ccc-analyzer") { 672dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek shift @$Args; 6736195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek unshift @$Args, $CCAnalyzer; 674dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek } 6757442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($IgnoreErrors) { 6767442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek if ($Cmd eq "make" or $Cmd eq "gmake") { 6776b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-k"); 6788912b5427a22d9032cad959c5c22cd9d28d4a66cTed Kremenek AddIfNotPresent($Args,"-i"); 6797442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 6807442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($Cmd eq "xcodebuild") { 6816b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES"); 6827442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 6836b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 6846b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 6856b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($Cmd eq "xcodebuild") { 686cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek # Disable distributed builds for xcodebuild. 6876b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-nodistribute"); 688cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek 689cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek # Disable PCH files until clang supports them. 690cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO"); 691915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek 692915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # When 'CC' is set, xcodebuild uses it to do all linking, even if we are 693915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # linking C++ object files. Set 'LDPLUSPLUS' so that xcodebuild uses 'g++' 694915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # when linking such files. 695386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek my $LDPLUSPLUS = `$CXX`; 696915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek $LDPLUSPLUS =~ s/\015?\012//; # strip newlines 697915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS; 6986b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 699dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 7005a4ddaf39a26f9c7e30d3aeca17c702213a29d9fTed Kremenek return (system(@$Args) >> 8); 701dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek} 702dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 703dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 7049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options. 7059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 7069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 707a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp { 7089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7095744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT; 710a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options] 7112b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 712f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted KremenekENDTEXT 713f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 714fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $BuildName) { 715f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n"; 716f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek } 717f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 718f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekprint <<ENDTEXT; 7192b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS: 7202b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 721363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -o - Target directory for HTML report files. Subdirectories 722a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop will be created as needed to represent separate "runs" of 7232b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek the analyzer. If this option is not specified, a directory 7242b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek is created in /tmp to store the reports. 7251262fc4d66584224234691d30d779f8ff004585cTed Kremenek 726363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -h - Display this message. 727363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --help 7281262fc4d66584224234691d30d779f8ff004585cTed Kremenek 729363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -k - Add a "keep on going" option to the specified build command. 730363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --keep-going This option currently supports make and xcodebuild. 731f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek This is a convenience option; one can specify this 732f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek behavior directly using build options. 7332b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 734363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --status-bugs - By default, the exit status of $Prog is the same as the 735363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek executed build command. Specifying this option causes the 736363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek exit status of $Prog to be 1 if it found potential bugs 737363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek and 0 otherwise. 7382b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 739386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-cc [compiler path] - By default, $Prog uses 'gcc' to compile and link 740386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-cc=[compiler path] your C and Objective-C code. Use this option 741386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek to specify an alternate compiler. 742386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek 743386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-c++ [compiler path] - By default, $Prog uses 'g++' to compile and link 744386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-c++=[compiler path] your C++ and Objective-C++ code. Use this option 745386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek to specify an alternate compiler. 746f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek 747363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -v - Verbose output from $Prog and the analyzer. 748386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek A second and third '-v' increases verbosity. 749363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 750363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -V - View analysis results in a web browser when the build 751363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --view completes. 7527f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 753b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 754386c69316668b9ea8c2591af56f994be16e3ff62Ted KremenekAVAILABLE ANALYSES (multiple analyses may be specified): 755d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek 756d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed KremenekENDTEXT 757b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 758b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek foreach my $Analysis (sort keys %AvailableAnalyses) { 759fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $AnalysesDefaultEnabled{$Analysis}) { 760363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek print " (+)"; 761b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 762b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek else { 763363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek print " "; 764b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 765b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 766b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek print " $Analysis $AvailableAnalyses{$Analysis}\n"; 767b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 768b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 769b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekprint <<ENDTEXT 770b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 771363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek NOTE: "(+)" indicates that an analysis is enabled by default unless one 772363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek or more analysis options are specified 773b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 7742b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS 7752b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 776363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek You can specify any build option acceptable to the build command. 77739eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek 7785744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE 7792b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 780363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek $Prog -o /tmp/myhtmldir make -j4 7812b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 782363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek The above example causes analysis reports to be deposited into 783363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option. 784363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek A different subdirectory is created each time $Prog analyzes a project. 785363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek The analyzer should support most parallel builds, but not distributed builds. 7862b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 7872b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT 7889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 7899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 7919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments. 7929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 7939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir; # Parent directory to store HTML files. 7959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0; # Ignore build errors. 7967f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults = 0; # View results when the build terminates. 797363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekmy $ExitStatusFoundBugs = 0; # Exit status reflects whether bugs were found 798b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy @AnalysesToRun; 7999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 8019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 802a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 8039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 8049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) { 8069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Scan for options we recognize. 8089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $arg = $ARGV[0]; 8109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8112f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop if ($arg eq "-h" or $arg eq "--help") { 8129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 813a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 0; 8149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 8159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 816fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $AvailableAnalyses{$arg}) { 8171262fc4d66584224234691d30d779f8ff004585cTed Kremenek shift @ARGV; 818b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek push @AnalysesToRun, $arg; 8191262fc4d66584224234691d30d779f8ff004585cTed Kremenek next; 8201262fc4d66584224234691d30d779f8ff004585cTed Kremenek } 8211262fc4d66584224234691d30d779f8ff004585cTed Kremenek 8229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-o") { 8239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 8249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!@ARGV) { 82623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("'-o' option requires a target directory name.\n"); 8279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 8289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $HtmlDir = shift @ARGV; 8309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 8319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 8329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8332b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek if ($arg eq "-k" or $arg eq "--keep-going") { 8349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 8359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $IgnoreErrors = 1; 8369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 8379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 8389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 839f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek if ($arg =~ /^--use-cc(=(.+))?$/) { 840f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek shift @ARGV; 841f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek my $cc; 842f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek 843f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek if ($2 eq "") { 844f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek if (!@ARGV) { 845f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek DieDiag("'--use-cc' option requires a compiler executable name.\n"); 846f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek } 847f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek $cc = shift @ARGV; 848f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek } 849f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek else { 850f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek $cc = $2; 851f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek } 852f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek 853f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek $ENV{"CCC_CC"} = $cc; 854f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek next; 855f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek } 856f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek 857386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek if ($arg =~ /^--use-c[+][+](=(.+))?$/) { 858386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek shift @ARGV; 859386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek 860386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek if ($2 eq "") { 861386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek if (!@ARGV) { 862386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek DieDiag("'--use-c++' option requires a compiler executable name.\n"); 863386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek } 864386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek $CXX = shift @ARGV; 865386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek } 866386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek else { 867386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek $CXX = $2; 868386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek } 869386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek next; 870386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek } 871386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek 8729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-v") { 8739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 8749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $Verbose++; 8759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 8769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 8779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8787f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek if ($arg eq "-V" or $arg eq "--view") { 8797f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek shift @ARGV; 8807f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek $ViewResults = 1; 8817f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek next; 8827f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek } 8837f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 884363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek if ($arg eq "--status-bugs") { 885363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek shift @ARGV; 886363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek $ExitStatusFoundBugs = 1; 887363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek next; 888363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek } 889363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 89023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/); 8910062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek 8929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek last; 8939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 8949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 89623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("No build command specified.\n\n"); 8979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 898a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 8999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 9009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 901386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek 902386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek 9039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports. 904684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir; 905a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir); 9069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 9079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Set the appropriate environment variables. 908a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopSetHtmlEnv(\@ARGV, $HtmlDir); 9099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 9100b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekmy $Cmd = "$RealBin/ccc-analyzer"; 9110b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 91223cfca3760c482f8543daab62051f5eaa1f98fb4Ted KremenekDieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n") 9130b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek if (! -x $Cmd); 914f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek 915b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekif (! -x $ClangSB) { 916b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek Diag("'clang' executable not found in '$RealBin'.\n"); 917b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek Diag("Using 'clang' from path.\n"); 918f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek} 9190b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 920386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek$ENV{'CXX'} = $CXX; 9214f4b17da43d3be87a248e1e10bf0b7d8b5891efdTed Kremenek$ENV{'CC'} = $Cmd; 922f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek$ENV{'CLANG'} = $Clang; 9239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 9249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif ($Verbose >= 2) { 9259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_VERBOSE'} = 1; 9269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 9279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 928a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenekif ($Verbose >= 3) { 929a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek $ENV{'CCC_ANALYZER_LOG'} = 1; 930a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek} 931a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek 9329012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenekif (scalar(@AnalysesToRun) == 0) { 9339012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek foreach my $key (keys %AnalysesDefaultEnabled) { 9349012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek push @AnalysesToRun,$key; 9359012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek } 93601006786e3760cc48c5e94d731b468b811b976d2Ted Kremenek} 9371262fc4d66584224234691d30d779f8ff004585cTed Kremenek 9389012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek$ENV{'CCC_ANALYZER_ANALYSIS'} = join ' ',@AnalysesToRun; 9399012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek 9409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build. 9415656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekmy $ExitStatus = RunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd); 9429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 9439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess the HTML directory. 944363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekmy $NumBugs = Postprocess($HtmlDir, $BaseDir); 9457f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 9467f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekif ($ViewResults and -r "$HtmlDir/index.html") { 9477f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # Only works on Mac OS X (for now). 9487f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek print "Viewing analysis results: '$HtmlDir/index.html'\n"; 94920161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system("open", "$HtmlDir/index.html"); 9507f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek} 9515656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek 952363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekif ($ExitStatusFoundBugs) { 953363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek exit 1 if ($NumBugs > 0); 954363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek exit 0; 955363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek} 956363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 9575656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekexit $ExitStatus; 9585656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek 959