scan-build revision fc1d340169265375704404a8eec1d8acf1c2038d
19cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek#!/usr/bin/env perl 29cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 39cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# The LLVM Compiler Infrastructure 49cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 59cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# This file is distributed under the University of Illinois Open Source 69cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# License. See LICENSE.TXT for details. 79cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 89cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##===----------------------------------------------------------------------===## 99cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# A script designed to wrap a build so that all calls to gcc are intercepted 119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# and piped to the static analyzer. 129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##===----------------------------------------------------------------------===## 149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse strict; 169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse warnings; 179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse File::Temp qw/ :mktemp /; 1822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenekuse FindBin qw($RealBin); 19a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenekuse Digest::MD5; 207a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekuse File::Basename; 2123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenekuse Term::ANSIColor; 2223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenekuse Term::ANSIColor qw(:constants); 239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Verbose = 0; # Verbose output from this script. 259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Prog = "scan-build"; 26f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildName; 27f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildDate; 289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 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 4623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub DieDiag { 4723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek if ($UseColor) { 4823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print BOLD, RED "$Prog: "; 4923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET, RED @_; 5023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET; 5123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 5223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek else { 5323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print "$Prog: ", @_; 5423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 5523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek exit(0); 5623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek} 5723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 59b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Some initial preprocessing of Clang options. 60b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------## 61b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 62b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $ClangSB = "$RealBin/clang"; 63b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $Clang = $ClangSB; 64b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 65b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekif (! -x $ClangSB) { 66b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek $Clang = "clang"; 67b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek} 68b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 69b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy %AvailableAnalyses; 70b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 71b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Query clang for analysis options. 7263c2017737530a7009f709f2fe822f20f63930b1Ted Kremenekopen(PIPE, "-|", $Clang, "--help") or 73b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek DieDiag("Cannot execute '$Clang'"); 7463c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 75b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $FoundAnalysis = 0; 76b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 77b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekwhile(<PIPE>) { 78b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek if ($FoundAnalysis == 0) { 79b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek if (/Available Source Code Analyses/) { 80b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek $FoundAnalysis = 1; 81b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 82b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 83b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek next; 84b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 85b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 86b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek if (/^\s\s\s\s([^\s]+)\s(.+)$/) { 87b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek next if ($1 =~ /-dump/ or $1 =~ /-view/ 88b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek or $1 =~ /-checker-simple/ or $1 =~ /-warn-uninit/); 89b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 90b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek $AvailableAnalyses{$1} = $2; 91b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek next; 92b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 93b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 94b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek last; 95b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek} 96b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 97b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekclose (PIPE); 98b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 99b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy %AnalysesDefaultEnabled = ( 100b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek '-warn-dead-stores' => 1, 101b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek '-checker-cfref' => 1, 1029012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek '-warn-objc-methodsigs' => 1, 103bde3a051933b6829ed79d6db0118231c2c01b105Ted Kremenek '-warn-objc-missing-dealloc' => 1, 104bde3a051933b6829ed79d6db0118231c2c01b105Ted Kremenek '-warn-objc-unused-ivars' => 1 105b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek); 106b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 107b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------## 108fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current sub-run. 1099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 1109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 111a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir { 1129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 113fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek die "Not enough arguments." if (@_ == 0); 1149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift @_; 115fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 116fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek my $TmpMode = 0; 117fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (!defined $Dir) { 118fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek $Dir = "/tmp"; 119fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek $TmpMode = 1; 120fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 121fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Get current date and time. 1239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @CurrentTime = localtime(); 1259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $year = $CurrentTime[5] + 1900; 1279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $day = $CurrentTime[3]; 1289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $month = $CurrentTime[4] + 1; 1299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1309d7405fafd5bc08d38bc75579927bf414570bd61Ted Kremenek my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day); 1319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Determine the run number. 1339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $RunNumber; 1359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-d $Dir) { 1379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -r $Dir) { 13923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("directory '$Dir' exists but is not readable.\n"); 1409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Iterate over all files in the specified directory. 1439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $max = 0; 1459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 1479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @FILES= readdir(DIR); 1489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 1499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek foreach my $f (@FILES) { 1519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 152fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek # Strip the prefix '$Prog-' if we are dumping files to /tmp. 153fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if ($TmpMode) { 154fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek next if (!($f =~ /^$Prog-(.+)/)); 155fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek $f = $1; 156fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 157fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @x = split/-/, $f; 159fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if (scalar(@x) != 4); 1619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[0] != $year); 1629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[1] != $month); 1639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[2] != $day); 1649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($x[3] > $max) { 1669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $max = $x[3]; 1679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = $max + 1; 1719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek else { 1739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-x $Dir) { 17523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("'$Dir' exists but is not a directory.\n"); 1769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 177fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 178fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if ($TmpMode) { 179fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek DieDiag("The directory '/tmp' does not exist or cannot be accessed."); 180fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 181fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # $Dir does not exist. It will be automatically created by the 1839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # clang driver. Set the run number to 1. 184fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = 1; 1869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 188fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek die "RunNumber must be defined!" if (!defined $RunNumber); 1899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Append the run number. 191fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if ($TmpMode) { 192fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek my $NewDir = "$Dir/$Prog-$DateString-$RunNumber"; 193fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek mkdir $NewDir; 194fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek return $NewDir; 195fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 196fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek else { 197fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek return "$Dir/$DateString-$RunNumber"; 198fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 1999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 2009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 201a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv { 2029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "Wrong number of arguments." if (scalar(@_) != 2); 2049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Args = shift; 2069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 2079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "No build command." if (scalar(@$Args) == 0); 2099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Cmd = $$Args[0]; 2119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Cmd =~ /configure/) { 2139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 2149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 2159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Verbose) { 21723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("Emitting reports for this run to '$Dir'.\n"); 2189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 2199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_HTML'} = $Dir; 2219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 2229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 22457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file. 22557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 22657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 22757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest { 22857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $FName = shift; 22923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName); 230a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 231a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek # Use Digest::MD5. We don't have to be cryptographically secure. We're 2327ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek # just looking for duplicate files that come from a non-malicious source. 2337ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek # We use Digest::MD5 because it is a standard Perl module that should 23463c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek # come bundled on most systems. 23523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n"); 236a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek binmode FILE; 237a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest; 238a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek close(FILE); 239a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 24063c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek # Return the digest. 241a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek return $Result; 24257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek} 24357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 24457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 2457a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek# UpdatePrefix - Compute the common prefix of files. 2467a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2477a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2487a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekmy $Prefix; 2497a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2507a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdatePrefix { 2517a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $x = shift; 2527a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $y = basename($x); 2537a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $x =~ s/\Q$y\E$//; 2547a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2557a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek # Ignore /usr, /Library, /System, /Developer 2567a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return if ( $x =~ /^\/usr/ or $x =~ /^\/Library/ 2577a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek or $x =~ /^\/System/ or $x =~ /^\/Developer/); 2587a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2597a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek if (!defined $Prefix) { 2607a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $Prefix = $x; 2617a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return; 2627a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 2637a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2647a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek chop $Prefix while (!($x =~ /^$Prefix/)); 2657a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 2667a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2677a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub GetPrefix { 2687a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return $Prefix; 2697a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 2707a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2717a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2727a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek# UpdateInFilePath - Update the path in the report file. 2737a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2747a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2757a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdateInFilePath { 2767a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $fname = shift; 2777a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $regex = shift; 2787a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $newtext = shift; 27963c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 2807a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek open (RIN, $fname) or die "cannot open $fname"; 28163c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp"; 28263c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 2837a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek while (<RIN>) { 2847a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek s/$regex/$newtext/; 2857a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek print ROUT $_; 2867a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 28763c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 2887a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek close (ROUT); 2897a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek close (RIN); 29020161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system("mv", "$fname.tmp", $fname); 2917a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 2927a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2937a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2945744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes. 2955744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 2965744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 29757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces 29857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports. We use a cache to solve this problem. 29957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 30057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned; 30157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 3025744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile { 3035744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3045744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Index = shift; 3055744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Dir = shift; 3065744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $FName = shift; 3075744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 30857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Compute a digest for the report file. Determine if we have already 30957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # scanned a file that looks just like it. 31057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 31157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $digest = ComputeDigest("$Dir/$FName"); 31257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 313fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $AlreadyScanned{$digest}) { 31457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Redundant file. Remove it. 31520161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system ("rm", "-f", "$Dir/$FName"); 31657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek return; 31757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek } 31857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 31957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek $AlreadyScanned{$digest} = 1; 32057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 321809709f46f2516b4054681f0b76284055a84a50fTed Kremenek # At this point the report file is not world readable. Make it happen. 32220161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system ("chmod", "644", "$Dir/$FName"); 323684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek 324684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek # Scan the report file for tags. 32523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n"); 3265744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3275744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $BugDesc = ""; 32822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugFile = ""; 32922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugPathLength = 1; 33022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $BugLine = 0; 3315744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3325744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek while (<IN>) { 3335744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3345744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek if (/<!-- BUGDESC (.*) -->$/) { 3355744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek $BugDesc = $1; 3365744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 33722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGFILE (.*) -->$/) { 33822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugFile = $1; 3397a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek UpdatePrefix($BugFile); 34022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 34122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGPATHLENGTH (.*) -->$/) { 34222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugPathLength = $1; 34322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 34422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGLINE (.*) -->$/) { 34522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugLine = $1; 34622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 3475744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 3485744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3495744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(IN); 3505744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 35122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek push @$Index,[ $FName, $BugDesc, $BugFile, $BugLine, $BugPathLength ]; 35222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek} 35322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 35422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 35522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek# CopyJS - Copy JavaScript code to target directory. 35622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 35722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 35822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremeneksub CopyJS { 35922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 36022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $Dir = shift; 36122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 36223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Cannot find 'sorttable.js'.\n") 36322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$RealBin/sorttable.js"); 36422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 36520161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system ("cp", "$RealBin/sorttable.js", "$Dir"); 36622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 36723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n") 36822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$Dir/sorttable.js"); 3695744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek} 3705744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3715744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 3729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan. 3739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 3749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 375a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess { 3769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 378684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek my $BaseDir = shift; 3799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 380fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek die "No directory specified." if (!defined $Dir); 3819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -d $Dir) { 38323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("No bugs found.\n"); 384363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek return 0; 3859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 3869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 3889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @files = grep(/^report-.*\.html$/,readdir(DIR)); 3899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 3909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 3919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (scalar(@files) == 0) { 39223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("Removing directory '$Dir' because it contains no reports.\n"); 39320161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system ("rm", "-fR", $Dir); 39423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 39523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek # Remove the base directory if it contains no files (don't use '-R'). 396fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $BaseDir) { system ("rm", "-f", $BaseDir); } 39723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 39823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("No bugs found.\n"); 399363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek return 0; 4009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 4015744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4025744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek # Scan each report file and build an index. 4035744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4045744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my @Index; 4055744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4065744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); } 4075744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 40863c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek # Generate an index.html file. 40963c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek my $FName = "$Dir/index.html"; 41063c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n"); 4115744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4126e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the header. 4136e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4145744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT; 4155744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html> 4165744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head> 4177f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<style type="text/css"> 4187f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek body { color:#000000; background-color:#ffffff } 41922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek body { font-family: Helvetica, sans-serif; font-size:9pt } 4207f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek h1 { font-size:12pt } 42122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable thead { 42222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek background-color:#eee; color:#666666; 42322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek font-weight: bold; cursor: default; 424bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek text-align:center; 425bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek border-top: 2px solid #000000; 426bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek border-bottom: 2px solid #000000; 427bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek font-weight: bold; font-family: Verdana 428bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek } 42922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border: 1px #000000 solid } 43022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border-collapse: collapse; border-spacing: 0px } 4317f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek td { border-bottom: 1px #000000 dotted } 43222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td { padding:5px; padding-left:8px; padding-right:8px } 433d8c6d0c8a5f970240cc4cbf8eddeae037d1b29eaTed Kremenek td { text-align:left; font-size:9pt } 43422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td.View { padding-left: 10px } 4357f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</style> 43622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script> 4376e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript"> 4386e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal) 4396e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{ 4406e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek var Rows = document.getElementsByTagName("tr"); 4416e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for ( var i = 0 ; i < Rows.length; ++i ) { 4426e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (Rows[i].className == RowClass) { 4436e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek Rows[i].style.display = DisplayVal; 4446e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4456e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4466e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 4476e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4486e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) { 4496e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (CheckButton.checked) { 4506e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, ""); 4516e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4526e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek else { 4536e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, "none"); 4546e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4556e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 4566e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script> 4576e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head> 4586e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body> 4596e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 4606e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4616e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the summary table. 4626e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4636e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek my %Totals; 4646e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4656e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for my $row ( @Index ) { 4666e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 467432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek #my $bug_type = lc($row->[1]); 468432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek my $bug_type = ($row->[1]); 4696e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 470fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (!defined $Totals{$bug_type}) { 4716e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek $Totals{$bug_type} = 1; 4726e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4736e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek else { 4746e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek $Totals{$bug_type}++; 4756e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4766e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 477f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 478f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print OUT "<h3>Summary</h3>"; 479f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 480fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $BuildName) { 481f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n" 482f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek } 483f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 4846e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 4856e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<table class="sortable"> 4866e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<tr> 4876e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td>Bug Type</td> 4886e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek <td>Quantity</td> 4892645c77072d45fabb2bdc0a3621908035c7113dcTed Kremenek <td class="sorttable_nosort">Display?</td> 4906e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</tr> 4916e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 4926e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4936e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for my $key ( sort { $a cmp $b } keys %Totals ) { 494bdf66c7373159aa80403d313629330fd11d4c48aTed Kremenek my $x = lc($key); 4953cea9ee6b77ac797ebb910bdf45d1d7f8f68e37bTed Kremenek $x =~ s/[ ,'"]+/_/g; 4966e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek print OUT "<tr><td>$key</td><td>$Totals{$key}</td><td><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></td></tr>\n"; 4976e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 4986e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 4996e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the table of errors. 5006e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 5016e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 5026e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table> 5036e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<h3>Reports</h3> 50422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<table class="sortable"> 5057f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<tr> 50688a96d6c3fe2b1b9d80b39c21cf7aca4aa9fcf08Ted Kremenek <td class="sorttable_sorted">Bug Type<span id="sorttable_sortfwdind"> ▾</span> 507bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>File</td> 508bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Line</td> 509bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>Path Length</td> 5102645c77072d45fabb2bdc0a3621908035c7113dcTed Kremenek <td class="sorttable_nosort"></td> 5117f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</tr> 5125744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT 5139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5147a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $prefix = GetPrefix(); 5157a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $regex; 5167a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $InFileRegex; 5177a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $InFilePrefix = "File:</td><td>"; 5187a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 519fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $prefix) { 5207a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $regex = qr/^\Q$prefix\E/is; 5217a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is; 5227a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 5237a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 5245744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek for my $row ( sort { $a->[1] cmp $b->[1] } @Index ) { 5255744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 5266e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek my $x = lc($row->[1]); 5273cea9ee6b77ac797ebb910bdf45d1d7f8f68e37bTed Kremenek $x =~ s/[ ,'"]+/_/g; 5286e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 5296e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek print OUT "<tr class=\"bt_$x\">\n"; 5305744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 5315744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $ReportFile = $row->[0]; 5329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 53322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT " <td class=\"DESC\">"; 534432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek #print OUT lc($row->[1]); 535432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek print OUT $row->[1]; 53622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT "</td>\n"; 5375744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 5387a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek # Update the file prefix. 5397a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 5407a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $fname = $row->[2]; 541fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $regex) { 5427a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $fname =~ s/$regex//; 5437a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix) 5447a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 5453e56e0b8b285e86eed4d191b1da93ded7382a847Ted Kremenek 5467a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek print OUT "<td>$fname</td>\n"; 5477a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 5487a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek # Print the rest of the columns. 5497a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek for my $j ( 3 .. $#{$row} ) { 5505744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "<td>$row->[$j]</td>\n" 5515744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 5527f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 5537f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # Emit the "View" link. 55422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek print OUT " <td class=\"View\"><a href=\"$ReportFile#EndPath\">View</a></td>\n"; 5553cea9ee6b77ac797ebb910bdf45d1d7f8f68e37bTed Kremenek 5567f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # End the row. 5575744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "</tr>\n"; 5585744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 5595744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 5605744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek print OUT "</table>\n</body></html>\n"; 5615744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(OUT); 56220161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek 56322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek CopyJS($Dir); 56420161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek 56520161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek # Make sure $Dir and $BaseDir are world readable/executable. 56620161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system("chmod", "755", $Dir); 567fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $BaseDir) { system("chmod", "755", $BaseDir); } 56820161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek 56923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek my $Num = scalar(@Index); 570150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek Diag("$Num bugs found.\n"); 571150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek if ($Num > 0 && -r "$Dir/index.html") { 572150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek Diag("Open '$Dir/index.html' to examine bug reports.\n"); 573150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek } 574363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 575363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek return $Num; 5769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 5779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 579dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command. 580dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 581dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 5826b6289848e215ff12d4d54fe0602d3371db52788Ted Kremeneksub AddIfNotPresent { 5836b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $Args = shift; 5846b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $Arg = shift; 5856b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $found = 0; 5866b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 5876b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek foreach my $k (@$Args) { 5886b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($k eq $Arg) { 5896b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek $found = 1; 5906b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek last; 5916b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 5926b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 5936b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 5946b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($found == 0) { 5956b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek push @$Args, $Arg; 5966b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 5976b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek} 5986b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 599dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremeneksub RunBuildCommand { 600dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 601dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Args = shift; 6027442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek my $IgnoreErrors = shift; 603dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Cmd = $Args->[0]; 6046195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek my $CCAnalyzer = shift; 605dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 6063301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek # Get only the part of the command after the last '/'. 6073301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek if ($Cmd =~ /\/([^\/]+)$/) { 6083301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek $Cmd = $1; 6093301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek } 6103301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek 61163c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek if ($Cmd eq "gcc" or $Cmd eq "cc" or $Cmd eq "llvm-gcc" 61263c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek or $Cmd eq "ccc-analyzer") { 613dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek shift @$Args; 6146195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek unshift @$Args, $CCAnalyzer; 615dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek } 6167442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($IgnoreErrors) { 6177442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek if ($Cmd eq "make" or $Cmd eq "gmake") { 6186b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-k"); 6198912b5427a22d9032cad959c5c22cd9d28d4a66cTed Kremenek AddIfNotPresent($Args,"-i"); 6207442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 6217442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($Cmd eq "xcodebuild") { 6226b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES"); 6237442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 6246b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 6256b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 6266b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($Cmd eq "xcodebuild") { 627cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek # Disable distributed builds for xcodebuild. 6286b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-nodistribute"); 629cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek 630cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek # Disable PCH files until clang supports them. 631cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO"); 632915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek 633915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # When 'CC' is set, xcodebuild uses it to do all linking, even if we are 634915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # linking C++ object files. Set 'LDPLUSPLUS' so that xcodebuild uses 'g++' 635915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek # when linking such files. 636915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek my $LDPLUSPLUS = `which g++`; 637915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek $LDPLUSPLUS =~ s/\015?\012//; # strip newlines 638915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS; 6396b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 640dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 6415656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek return system(@$Args); 642dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek} 643dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 644dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 6459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options. 6469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 6479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 648a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp { 6499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 6505744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT; 651a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options] 6522b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 653f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted KremenekENDTEXT 654f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 655fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $BuildName) { 656f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n"; 657f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek } 658f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 659f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekprint <<ENDTEXT; 6602b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS: 6612b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 662363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -o - Target directory for HTML report files. Subdirectories 663a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop will be created as needed to represent separate "runs" of 6642b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek the analyzer. If this option is not specified, a directory 6652b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek is created in /tmp to store the reports. 6661262fc4d66584224234691d30d779f8ff004585cTed Kremenek 667363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -h - Display this message. 668363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --help 6691262fc4d66584224234691d30d779f8ff004585cTed Kremenek 670363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -k - Add a "keep on going" option to the specified build command. 671363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --keep-going This option currently supports make and xcodebuild. 672f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek This is a convenience option; one can specify this 673f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek behavior directly using build options. 6742b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 675363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --status-bugs - By default, the exit status of $Prog is the same as the 676363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek executed build command. Specifying this option causes the 677363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek exit status of $Prog to be 1 if it found potential bugs 678363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek and 0 otherwise. 6792b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 680363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -v - Verbose output from $Prog and the analyzer. 681363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek A second and third "-v" increases verbosity. 682363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 683363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -V - View analysis results in a web browser when the build 684363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --view completes. 6857f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 686b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted KremenekENDTEXT 687b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 688363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek print " Available Source Code Analyses (multiple analyses may be specified):\n\n"; 689b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 690b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek foreach my $Analysis (sort keys %AvailableAnalyses) { 691fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $AnalysesDefaultEnabled{$Analysis}) { 692363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek print " (+)"; 693b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 694b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek else { 695363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek print " "; 696b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 697b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 698b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek print " $Analysis $AvailableAnalyses{$Analysis}\n"; 699b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek } 700b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 701b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekprint <<ENDTEXT 702b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 703363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek NOTE: "(+)" indicates that an analysis is enabled by default unless one 704363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek or more analysis options are specified 705b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 7062b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS 7072b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 708363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek You can specify any build option acceptable to the build command. 70939eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek 7105744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE 7112b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 712363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek $Prog -o /tmp/myhtmldir make -j4 7132b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 714363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek The above example causes analysis reports to be deposited into 715363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option. 716363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek A different subdirectory is created each time $Prog analyzes a project. 717363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek The analyzer should support most parallel builds, but not distributed builds. 7182b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 7192b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT 7209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 7219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 7239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments. 7249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 7259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir; # Parent directory to store HTML files. 7279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0; # Ignore build errors. 7287f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults = 0; # View results when the build terminates. 729363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekmy $ExitStatusFoundBugs = 0; # Exit status reflects whether bugs were found 730b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy @AnalysesToRun; 7319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 732363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 7339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 7349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 735a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 7369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 7379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) { 7399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Scan for options we recognize. 7419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $arg = $ARGV[0]; 7439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7442f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop if ($arg eq "-h" or $arg eq "--help") { 7459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 746a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 0; 7479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 7489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 749fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $AvailableAnalyses{$arg}) { 7501262fc4d66584224234691d30d779f8ff004585cTed Kremenek shift @ARGV; 751b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek push @AnalysesToRun, $arg; 7521262fc4d66584224234691d30d779f8ff004585cTed Kremenek next; 7531262fc4d66584224234691d30d779f8ff004585cTed Kremenek } 7541262fc4d66584224234691d30d779f8ff004585cTed Kremenek 7559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-o") { 7569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 7579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!@ARGV) { 75923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("'-o' option requires a target directory name.\n"); 7609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 7619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $HtmlDir = shift @ARGV; 7639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 7649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 7659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7662b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek if ($arg eq "-k" or $arg eq "--keep-going") { 7679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 7689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $IgnoreErrors = 1; 7699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 7709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 7719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-v") { 7739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 7749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $Verbose++; 7759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 7769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 7779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7787f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek if ($arg eq "-V" or $arg eq "--view") { 7797f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek shift @ARGV; 7807f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek $ViewResults = 1; 7817f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek next; 7827f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek } 7837f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 784363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek if ($arg eq "--status-bugs") { 785363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek shift @ARGV; 786363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek $ExitStatusFoundBugs = 1; 787363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek next; 788363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek } 789363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 79023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/); 7910062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek 7929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek last; 7939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 7949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 7959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 79623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("No build command specified.\n\n"); 7979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 798a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 7999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 8009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports. 802684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir; 803a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir); 8049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Set the appropriate environment variables. 806a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopSetHtmlEnv(\@ARGV, $HtmlDir); 8079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8080b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekmy $Cmd = "$RealBin/ccc-analyzer"; 8090b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 81023cfca3760c482f8543daab62051f5eaa1f98fb4Ted KremenekDieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n") 8110b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek if (! -x $Cmd); 812f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek 813b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekif (! -x $ClangSB) { 814b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek Diag("'clang' executable not found in '$RealBin'.\n"); 815b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek Diag("Using 'clang' from path.\n"); 816f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek} 8170b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 8184f4b17da43d3be87a248e1e10bf0b7d8b5891efdTed Kremenek$ENV{'CC'} = $Cmd; 819f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek$ENV{'CLANG'} = $Clang; 8209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif ($Verbose >= 2) { 8229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_VERBOSE'} = 1; 8239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 8249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 825a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenekif ($Verbose >= 3) { 826a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek $ENV{'CCC_ANALYZER_LOG'} = 1; 827a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek} 828a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek 8299012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenekif (scalar(@AnalysesToRun) == 0) { 8309012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek foreach my $key (keys %AnalysesDefaultEnabled) { 8319012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek push @AnalysesToRun,$key; 8329012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek } 83301006786e3760cc48c5e94d731b468b811b976d2Ted Kremenek} 8341262fc4d66584224234691d30d779f8ff004585cTed Kremenek 8359012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek$ENV{'CCC_ANALYZER_ANALYSIS'} = join ' ',@AnalysesToRun; 8369012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek 8379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build. 8385656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekmy $ExitStatus = RunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd); 8399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess the HTML directory. 841363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekmy $NumBugs = Postprocess($HtmlDir, $BaseDir); 8427f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 8437f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekif ($ViewResults and -r "$HtmlDir/index.html") { 8447f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek # Only works on Mac OS X (for now). 8457f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek print "Viewing analysis results: '$HtmlDir/index.html'\n"; 84620161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system("open", "$HtmlDir/index.html"); 8477f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek} 8485656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek 849363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekif ($ExitStatusFoundBugs) { 850363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek exit 1 if ($NumBugs > 0); 851363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek exit 0; 852363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek} 853363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 8545656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekexit $ExitStatus; 8555656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek 856