scan-build revision ce723ce2346fccb102d4dc93b80356824544d1af
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);
227cba11262458df05951432b54997eb40a35dbf9eTed Kremenekuse Cwd;
237cba11262458df05951432b54997eb40a35dbf9eTed Kremenekuse Sys::Hostname;
247cba11262458df05951432b54997eb40a35dbf9eTed Kremenekuse File::Basename;
259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Verbose = 0;       # Verbose output from this script.
279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Prog = "scan-build";
28f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildName;
29f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildDate;
3095aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenekmy $CXX;  # Leave undefined initially.
319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
320e6893840fdd69a8a4d6561663a5a29af237ae08Ted Kremenekmy $TERM = $ENV{'TERM'};
330e6893840fdd69a8a4d6561663a5a29af237ae08Ted Kremenekmy $UseColor = (defined $TERM and $TERM eq 'xterm-color' and -t STDOUT
340e6893840fdd69a8a4d6561663a5a29af237ae08Ted Kremenek                and defined $ENV{'SCAN_BUILD_COLOR'});
3523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek
367cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $UserName = HtmlEscape(getpwuid($<) || 'unknown');
377cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $HostName = HtmlEscape(hostname() || 'unknown');
387cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $CurrentDir = HtmlEscape(getcwd());
397cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $CurrentDirSuffix = basename($CurrentDir);
407cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
417cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $CmdArgs;
427cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
437cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $HtmlTitle;
447cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
457cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $Date = localtime();
467cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
47b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------##
48b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Diagnostics
49b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------##
50b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
5123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub Diag {
5223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  if ($UseColor) {
5323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print BOLD, MAGENTA "$Prog: @_";
5423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print RESET;
5523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  }
5623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  else {
5723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print "$Prog: @_";
5823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  }  
5923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek}
6023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek
61991c54b9b7409656e5593364e065878b5210d556Ted Kremeneksub DiagCrashes {
62991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  my $Dir = shift;
63991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  Diag ("The analyzer crashed on some source files.\n");
64386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek  Diag ("Preprocessed versions of crashed files were deposited in '$Dir/crashes'.\n");
65991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  Diag ("Please consider submitting a bug report using these files:\n");
66991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  Diag ("  http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\n")
67991c54b9b7409656e5593364e065878b5210d556Ted Kremenek}
68991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
6923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub DieDiag {
7023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  if ($UseColor) {
7123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print BOLD, RED "$Prog: ";
7223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print RESET, RED @_;
7323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print RESET;
7423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  }
7523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  else {
7623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print "$Prog: ", @_;
7723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  }
7823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  exit(0);
7923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek}
8023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek
819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
82b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Some initial preprocessing of Clang options.
83b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------##
84b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
85b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $ClangSB = "$RealBin/clang";
86b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $Clang = $ClangSB;
87b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
88b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekif (! -x $ClangSB) {
89b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  $Clang = "clang";
90b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek}
91b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
92b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy %AvailableAnalyses;
93b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
94b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Query clang for analysis options.
9563c2017737530a7009f709f2fe822f20f63930b1Ted Kremenekopen(PIPE, "-|", $Clang, "--help") or
96b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  DieDiag("Cannot execute '$Clang'");
9763c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
98b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $FoundAnalysis = 0;
99b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
100b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekwhile(<PIPE>) {
101b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  if ($FoundAnalysis == 0) {
102b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    if (/Available Source Code Analyses/) {
103b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek      $FoundAnalysis = 1;
104b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    }
105991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
106b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    next;
107b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  }
108b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    
109b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  if (/^\s\s\s\s([^\s]+)\s(.+)$/) {
110b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    next if ($1 =~ /-dump/ or $1 =~ /-view/ 
111b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek             or $1 =~ /-checker-simple/ or $1 =~ /-warn-uninit/);
112b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek             
113b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    $AvailableAnalyses{$1} = $2;
114b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    next;
115b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  }
116b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  
117b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  last;
118b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek}
119b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
120b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekclose (PIPE);
121b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
122b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy %AnalysesDefaultEnabled = (
123b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  '-warn-dead-stores' => 1,
124b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  '-checker-cfref' => 1,
1259012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek  '-warn-objc-methodsigs' => 1,
126bde3a051933b6829ed79d6db0118231c2c01b105Ted Kremenek  '-warn-objc-missing-dealloc' => 1,
1275d443490cd6fb8c772957b7df728f71189d9c55bTed Kremenek  '-warn-objc-unused-ivars' => 1,
128b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek);
129b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
130b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------##
131fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current sub-run.
1329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
1339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
134a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir {  
1359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
136fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  die "Not enough arguments." if (@_ == 0);  
1379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift @_;
138fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    
139fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  my $TmpMode = 0;
140fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (!defined $Dir) {
141fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    $Dir = "/tmp";
142fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    $TmpMode = 1;
143fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  }
144fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
1459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Get current date and time.
1469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my @CurrentTime = localtime();
1489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $year  = $CurrentTime[5] + 1900;
1509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $day   = $CurrentTime[3];
1519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $month = $CurrentTime[4] + 1;
1529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1539d7405fafd5bc08d38bc75579927bf414570bd61Ted Kremenek  my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day);
1549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Determine the run number.
1569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $RunNumber;
1589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (-d $Dir) {
1609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (! -r $Dir) {
16223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek      DieDiag("directory '$Dir' exists but is not readable.\n");
1639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
1649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # Iterate over all files in the specified directory.
1669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    my $max = 0;
1689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    opendir(DIR, $Dir);
17029da6c59df7ca994e75139303a9230b24e2abaadTed Kremenek    my @FILES = grep { -d "$Dir/$_" } readdir(DIR);
1719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    closedir(DIR);
1729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    foreach my $f (@FILES) {
1749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
175fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek      # Strip the prefix '$Prog-' if we are dumping files to /tmp.
176fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek      if ($TmpMode) {
177fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek        next if (!($f =~ /^$Prog-(.+)/));
178fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek        $f = $1;
179fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek      }
180fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
181ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
1829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      my @x = split/-/, $f;
1839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if (scalar(@x) != 4);
1849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[0] != $year);
1859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[1] != $month);
1869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[2] != $day);
1879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      
1889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      if ($x[3] > $max) {
1899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek        $max = $x[3];
1909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      }      
1919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
1929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $RunNumber = $max + 1;
1949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
1959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  else {
1969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (-x $Dir) {
19823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek      DieDiag("'$Dir' exists but is not a directory.\n");
1999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
200fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
201fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    if ($TmpMode) {
202fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek      DieDiag("The directory '/tmp' does not exist or cannot be accessed.");
203fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    }
204fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
2059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # $Dir does not exist.  It will be automatically created by the 
2069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # clang driver.  Set the run number to 1.  
207fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
2089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $RunNumber = 1;
2099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
211fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  die "RunNumber must be defined!" if (!defined $RunNumber);
2129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Append the run number.
214fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek  my $NewDir;
215fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if ($TmpMode) {
216fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek    $NewDir = "$Dir/$Prog-$DateString-$RunNumber";
217fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  }
218fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  else {
219fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek    $NewDir = "$Dir/$DateString-$RunNumber";
220fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  }
221fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek  system 'mkdir','-p',$NewDir;
222fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek  return $NewDir;
2239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
2249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
225a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv {
2269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "Wrong number of arguments." if (scalar(@_) != 2);
2289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Args = shift;
2309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift;
2319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "No build command." if (scalar(@$Args) == 0);
2339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Cmd = $$Args[0];
2359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($Cmd =~ /configure/) {
2379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    return;
2389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($Verbose) {
24123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    Diag("Emitting reports for this run to '$Dir'.\n");
2429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  $ENV{'CCC_ANALYZER_HTML'} = $Dir;
2459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
2469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
2479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
24857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file.
24957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------##
25057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
25157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest {
25257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $FName = shift;
25323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName);  
254a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  
255a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  # Use Digest::MD5.  We don't have to be cryptographically secure.  We're
2567ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek  # just looking for duplicate files that come from a non-malicious source.
2577ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek  # We use Digest::MD5 because it is a standard Perl module that should
25863c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  # come bundled on most systems.  
25923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n");
260a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  binmode FILE;
261a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest;
262a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  close(FILE);
263a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  
26463c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  # Return the digest.  
265a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  return $Result;
26657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek}
26757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
26857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------##
2697a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek#  UpdatePrefix - Compute the common prefix of files.
2707a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
2717a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
2727a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekmy $Prefix;
2737a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
2747a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdatePrefix {
2757a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $x = shift;
2767a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $y = basename($x);
2777a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  $x =~ s/\Q$y\E$//;
2787a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
2797a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  # Ignore /usr, /Library, /System, /Developer
2807a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  return if ( $x =~ /^\/usr/ or $x =~ /^\/Library/
2817a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek              or $x =~ /^\/System/ or $x =~ /^\/Developer/);
2827a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
2837a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  if (!defined $Prefix) {
2847a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    $Prefix = $x;
2857a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    return;
2867a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  }
2877a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
28820b2bae90c102f405ba70f602c45660ce1cd0c4eTed Kremenek  chop $Prefix while (!($x =~ /^\Q$Prefix/));
2897a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
2907a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
2917a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub GetPrefix {
2927a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  return $Prefix;
2937a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
2947a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
2957a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
2967a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek#  UpdateInFilePath - Update the path in the report file.
2977a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
2987a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
2997a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdateInFilePath {
3007a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $fname = shift;
3017a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $regex = shift;
3027a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $newtext = shift;
30363c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
3047a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  open (RIN, $fname) or die "cannot open $fname";
30563c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp";
30663c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
3077a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  while (<RIN>) {
3087a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    s/$regex/$newtext/;
3097a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    print ROUT $_;
3107a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  }
31163c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
3127a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  close (ROUT);
3137a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  close (RIN);
31420161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  system("mv", "$fname.tmp", $fname);
3157a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
3167a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3177a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
3185744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes.
3195744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------##
3205744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
32157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces
32257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports.  We use a cache to solve this problem.
32357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
32457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned;
32557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
3265744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile {
3275744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
3285744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $Index = shift;
3295744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $Dir = shift;
3305744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $FName = shift;
3315744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
33257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  # Compute a digest for the report file.  Determine if we have already
33357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  # scanned a file that looks just like it.
33457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
33557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $digest = ComputeDigest("$Dir/$FName");
33657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
337fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $AlreadyScanned{$digest}) {
33857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    # Redundant file.  Remove it.
33920161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek    system ("rm", "-f", "$Dir/$FName");
34057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    return;
34157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  }
34257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
34357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  $AlreadyScanned{$digest} = 1;
34457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
345809709f46f2516b4054681f0b76284055a84a50fTed Kremenek  # At this point the report file is not world readable.  Make it happen.
34620161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  system ("chmod", "644", "$Dir/$FName");
347684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  
348684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  # Scan the report file for tags.
34923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n");
3505744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
3515744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $BugDesc = "";
35222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugFile = "";
353ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  my $BugCategory;
35422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugPathLength = 1;
35522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugLine = 0;
356ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  my $found = 0;
357ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
3585744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  while (<IN>) {
359ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
360ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    last if ($found == 5);
361ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
3625744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    if (/<!-- BUGDESC (.*) -->$/) {
3635744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek      $BugDesc = $1;
364ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
3655744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    }
36622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGFILE (.*) -->$/) {
36722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugFile = $1;
3687a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek      UpdatePrefix($BugFile);
369ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
37022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
37122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGPATHLENGTH (.*) -->$/) {
37222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugPathLength = $1;
373ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
37422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
37522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGLINE (.*) -->$/) {
37622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugLine = $1;    
377ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
378ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    }
379ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    elsif (/<!-- BUGCATEGORY (.*) -->$/) {
380ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $BugCategory = $1;
381ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
38222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
3835744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  }
3845744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
3855744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  close(IN);
386ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  
387ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  if (!defined $BugCategory) {
388ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    $BugCategory = "Other";
389ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  }
3905744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
39150534dc3ab0737224f9ce739821e1486219c686bTed Kremenek  push @$Index,[ $FName, $BugCategory, $BugDesc, $BugFile, $BugLine ];
39222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek}
39322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
39422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------##
3953ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek# CopyFiles - Copy resource files to target directory.
39622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------##
39722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
3983ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremeneksub CopyFiles {
39922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
40022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $Dir = shift;
40122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  
40223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("Cannot find 'sorttable.js'.\n")
40322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    if (! -r "$RealBin/sorttable.js");  
40422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
40520161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  system ("cp", "$RealBin/sorttable.js", "$Dir");
40622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
40723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n")
40822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    if (! -r "$Dir/sorttable.js");
4093ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek    
4103ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek  DieDiag("Cannot find 'scanview.css'.\n")
4113ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek    if (! -r "$RealBin/scanview.css");  
4123ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek
4133ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek  system ("cp", "$RealBin/scanview.css", "$Dir");
4143ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek
4153ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek  DieDiag("Could not copy 'scanview.css' to '$Dir'.\n")
4163ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek    if (! -r "$Dir/scanview.css");
4175744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek}
4185744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
4195744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------##
4209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan.
4219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
4229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
423a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess {
4249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift;
426684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  my $BaseDir = shift;
4279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
428fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  die "No directory specified." if (!defined $Dir);
4299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (! -d $Dir) {
43123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    Diag("No bugs found.\n");
432363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    return 0;
4339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
4349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  opendir(DIR, $Dir);
436991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  my $Crashes = 0;
437991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  my @files = grep { if ($_ eq "crashes") { $Crashes++; }
438991c54b9b7409656e5593364e065878b5210d556Ted Kremenek                     /^report-.*\.html$/; } readdir(DIR);
4399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  closedir(DIR);
4409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
441991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  if (scalar(@files) == 0 and $Crashes == 0) {
44223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    Diag("Removing directory '$Dir' because it contains no reports.\n");
44320161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek    system ("rm", "-fR", $Dir);
444363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    return 0;
4459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
4465744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
447991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  # Scan each report file and build an index.  
448991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  my @Index;    
4495744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); }
4505744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
451d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  # Scan the crashes directory and use the information in the .info files
452d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  # to update the common prefix directory.
453d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  if (-d "$Dir/crashes") {
454d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek    opendir(DIR, "$Dir/crashes");
45582a1253077cd0832e4d347062b911cd305ab62d1Ted Kremenek    my @files = grep { /[.]info.txt$/; } readdir(DIR);
456d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek    closedir(DIR);
457d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek    foreach my $file (@files) {
458d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      open IN, "$Dir/crashes/$file" or DieDiag("cannot open $file\n");
459d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      my $Path = <IN>;
460d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      if (defined $Path) { UpdatePrefix($Path); }
461d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      close IN;
462d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek    }    
463d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  }
464d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  
46563c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  # Generate an index.html file.  
46663c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  my $FName = "$Dir/index.html";  
46763c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n");
4685744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
4696e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the header.
4706e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
4715744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT;
4725744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html>
4735744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head>
4747cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<title>${HtmlTitle}</title>
475f143545ce5ce125e7c1aa6fca9df372bfb604e9cTed Kremenek<link type="text/css" rel="stylesheet" href="scanview.css"/>
47622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script>
4776e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript">
4786e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal)
4796e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{
4806e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  var Rows = document.getElementsByTagName("tr");
4816e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  for ( var i = 0 ; i < Rows.length; ++i ) {
4826e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    if (Rows[i].className == RowClass) {
4836e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek      Rows[i].style.display = DisplayVal;
4846e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
4856e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
4866e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek}
487ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
4886e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) {
4896e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  if (CheckButton.checked) {
4906e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    SetDisplay(ClassName, "");
4916e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
4926e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  else {
4936e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    SetDisplay(ClassName, "none");
4946e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
4956e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek}
4966e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script>
4971d1abb1dec3d0b7609809d876a16a64a021e96e7Ted Kremenek<!-- SUMMARYENDHEAD -->
4986e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head>
4996e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body>
5007cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<h1>${HtmlTitle}</h1>
5017cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
5027cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<table>
5037cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>User:</th><td>${UserName}\@${HostName}</td></tr>
5047cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Working Directory:</th><td>${CurrentDir}</td></tr>
5057cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Command Line:</th><td>${CmdArgs}</td></tr>
5067cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Date:</th><td>${Date}</td></tr>
5077cba11262458df05951432b54997eb40a35dbf9eTed KremenekENDTEXT
5087cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
5097cba11262458df05951432b54997eb40a35dbf9eTed Kremenekprint OUT "<tr><th>Version:</th><td>${BuildName} (${BuildDate})</td></tr>\n"
5107cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  if (defined($BuildName) && defined($BuildDate));
5117cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
5127cba11262458df05951432b54997eb40a35dbf9eTed Kremenekprint OUT <<ENDTEXT;
5137cba11262458df05951432b54997eb40a35dbf9eTed Kremenek</table>
5146e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT
5156e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
516991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  if (scalar(@files)) {
517991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    # Print out the summary table.
518991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my %Totals;
519ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
520991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    for my $row ( @Index ) {
521ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $bug_type = ($row->[2]);
522ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $bug_category = ($row->[1]);
523ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $key = "$bug_category:$bug_type";
524ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
525ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      if (!defined $Totals{$key}) { $Totals{$key} = [1,$bug_category,$bug_type]; }
526ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      else { $Totals{$key}->[0]++; }
5276e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
528991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
5297cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    print OUT "<h2>Bug Summary</h2>";
530991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
531991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    if (defined $BuildName) {
532991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n"
5336e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
534f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  
5356e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT;
536ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<table>
537ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<thead><tr><td>Bug Type</td><td>Quantity</td><td class="sorttable_nosort">Display?</td></tr></thead>
5386e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT
5396e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
540ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    my $last_category;
541ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
542ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    for my $key (
543ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      sort {
544ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        my $x = $Totals{$a};
545ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        my $y = $Totals{$b};
546ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        my $res = $x->[1] cmp $y->[1];
547ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        $res = $x->[2] cmp $y->[2] if ($res == 0);
548ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        $res
549ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      } keys %Totals ) 
550ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    {
551ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $val = $Totals{$key};
552ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $category = $val->[1];
553ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      if (!defined $last_category or $last_category ne $category) {
554ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        $last_category = $category;
555ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT "<tr><th>$category</th><th colspan=2></th></tr>\n";
556ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      }      
557ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $x = lc $key;
558ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $x =~ s/[ ,'":\/()]+/_/g;
559ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<tr><td class=\"SUMM_DESC\">";
560ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT $val->[2];
561ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td><td>";
562ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT $val->[0];
563ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td><td><center><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></center></td></tr>\n";
564991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }
5656e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
5666e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the table of errors.
5676e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
5686e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT;
5696e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table>
5707cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<h2>Reports</h2>
571ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
572ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<table class="sortable" style="table-layout:automatic">
573ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<thead><tr>
574ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <td>Bug Group</td>
575ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <td class="sorttable_sorted">Bug Type<span id="sorttable_sortfwdind">&nbsp;&#x25BE;</span></td>
576bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>File</td>
577ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <td class="Q">Line</td>
5782645c77072d45fabb2bdc0a3621908035c7113dcTed Kremenek  <td class="sorttable_nosort"></td>
579ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <!-- REPORTBUGCOL -->
580ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek</tr></thead>
581ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<tbody>
5825744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT
5839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
584991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $prefix = GetPrefix();
585991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $regex;
586991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $InFileRegex;
587991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $InFilePrefix = "File:</td><td>";
5887a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
589991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    if (defined $prefix) { 
590991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      $regex = qr/^\Q$prefix\E/is;    
591991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is;
592991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }    
5937a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
594ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    for my $row ( sort { $a->[2] cmp $b->[2] } @Index ) {
595ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $x = "$row->[1]:$row->[2]";
596ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $x = lc $x;
597ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $x =~ s/[ ,'":\/()]+/_/g;
5986e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    
599991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      my $ReportFile = $row->[0];
600ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          
601ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<tr class=\"bt_$x\">";
602ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<td class=\"DESC\">";
603991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT $row->[1];
604ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td>";
605ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<td class=\"DESC\">";
606ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT $row->[2];
607ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td>";
608ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
609ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      # Update the file prefix.      
610ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $fname = $row->[3];
611ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
612991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      if (defined $regex) {
613991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        $fname =~ s/$regex//;
614991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix)
615991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      }
616ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
61791639ef5aa2bd94c14ae872cf747c58174ffe9b8Ted Kremenek      print OUT "<td>";      
618ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my @fname = split /\//,$fname;
619ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      if ($#fname > 0) {
620ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        while ($#fname >= 0) {
621ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          my $x = shift @fname;
622ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          print OUT $x;
623ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          if ($#fname >= 0) {
624ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek            print OUT "<span class=\"W\"> </span>/";
625ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          }
626ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        }
627ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      }
628ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      else {
629ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT $fname;
63091639ef5aa2bd94c14ae872cf747c58174ffe9b8Ted Kremenek      }      
631ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td>";
632ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
633ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      # Print out the quantities.
63450534dc3ab0737224f9ce739821e1486219c686bTed Kremenek      for my $j ( 4 .. 4 ) {
635ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT "<td class=\"Q\">$row->[$j]</td>";        
636ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      }
637ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
638991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      # Print the rest of the columns.
63950534dc3ab0737224f9ce739821e1486219c686bTed Kremenek      for (my $j = 5; $j <= $#{$row}; ++$j) {
640ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT "<td>$row->[$j]</td>"
641991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      }
6427f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
643991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      # Emit the "View" link.
64468005ddb49b88c2f6cdd88185d72d8b411d2dbc9Ted Kremenek      print OUT "<td><a href=\"$ReportFile#EndPath\">View Report</a></td>";
6453cea9ee6b77ac797ebb910bdf45d1d7f8f68e37bTed Kremenek        
646e43038ec3d0ef187fcdddf101ef653bbbdb1069aDaniel Dunbar      # Emit REPORTBUG markers.
647ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "\n<!-- REPORTBUG id=\"$ReportFile\" -->\n";
648e43038ec3d0ef187fcdddf101ef653bbbdb1069aDaniel Dunbar        
649991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      # End the row.
650991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT "</tr>\n";
651991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }
652991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  
653ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    print OUT "</tbody>\n</table>\n\n";
654991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  }
655991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
656991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  if ($Crashes) {
657991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    # Read the crash directory for files.
658991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    opendir(DIR, "$Dir/crashes");
65982a1253077cd0832e4d347062b911cd305ab62d1Ted Kremenek    my @files = grep { /[.]info.txt$/ } readdir(DIR);
660991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    closedir(DIR);
661991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
662991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    if (scalar(@files)) {
663991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT <<ENDTEXT;
6647cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<h2>Analyzer Failures</h2>
665991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
6665d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek<p>The analyzer had problems processing the following files:</p>
667991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
668991c54b9b7409656e5593364e065878b5210d556Ted Kremenek<table>
6699f9b1fded49acff77e61b3ed1afc8bbaaefe6f34Ted Kremenek<thead><tr><td>Problem</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>
670991c54b9b7409656e5593364e065878b5210d556Ted KremenekENDTEXT
671991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  
672991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      foreach my $file (sort @files) {
67382a1253077cd0832e4d347062b911cd305ab62d1Ted Kremenek        $file =~ /(.+).info.txt$/;
674991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        # Get the preprocessed file.
675991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        my $ppfile = $1;
676991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        # Open the info file and get the name of the source file.
677991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        open (INFO, "$Dir/crashes/$file") or
678991c54b9b7409656e5593364e065878b5210d556Ted Kremenek          die "Cannot open $Dir/crashes/$file\n";
679991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        my $srcfile = <INFO>;
6805d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek        chomp $srcfile;
6815d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek        my $problem = <INFO>;
6825d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek        chomp $problem;
683991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        close (INFO);
684991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        # Print the information in the table.
685d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek        my $prefix = GetPrefix();
6869f9b1fded49acff77e61b3ed1afc8bbaaefe6f34Ted Kremenek        if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; }
6879f9b1fded49acff77e61b3ed1afc8bbaaefe6f34Ted Kremenek        print OUT "<tr><td>$problem</td><td>$srcfile</td><td><a href=\"crashes/$ppfile\">$ppfile</a></td><td><a href=\"crashes/$ppfile.stderr.txt\">$ppfile.stderr.txt</a></td></tr>\n";
688ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar        my $ppfile_clang = $ppfile;
689ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar        $ppfile_clang =~ s/[.](.+)$/.clang.$1/;
690ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar        print OUT "  <!-- REPORTPROBLEM file=\"crashes/$ppfile\" clangfile=\"crashes/$ppfile_clang\" stderr=\"crashes/$ppfile.stderr.txt\" info=\"crashes/$ppfile.info\" -->\n";
691991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      }
692991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
693991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT <<ENDTEXT;
694991c54b9b7409656e5593364e065878b5210d556Ted Kremenek</table>
695ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar<p>Please consider submitting preprocessed files as <a href="http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs">bug reports</a>. <!-- REPORTCRASHES --> </p>
696991c54b9b7409656e5593364e065878b5210d556Ted KremenekENDTEXT
697991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }
6985744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  }
6995744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
700991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  print OUT "</body></html>\n";  
7015744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  close(OUT);
7023ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek  CopyFiles($Dir);
70320161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek
70420161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  # Make sure $Dir and $BaseDir are world readable/executable.
70520161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  system("chmod", "755", $Dir);
706fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $BaseDir) { system("chmod", "755", $BaseDir); }
70720161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek
70823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  my $Num = scalar(@Index);
709150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek  Diag("$Num bugs found.\n");
710150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek  if ($Num > 0 && -r "$Dir/index.html") {
7115950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek    Diag("Run 'scan-view $Dir' to examine bug reports.\n");
712150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek  }
713363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  
714991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  DiagCrashes($Dir) if ($Crashes);
715991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  
716363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  return $Num;
7179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
7189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
7199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
720dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command.
721dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------##
722dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek
7236b6289848e215ff12d4d54fe0602d3371db52788Ted Kremeneksub AddIfNotPresent {
7246b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $Args = shift;
7256b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $Arg = shift;  
7266b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $found = 0;
7276b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
7286b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  foreach my $k (@$Args) {
7296b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    if ($k eq $Arg) {
7306b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      $found = 1;
7316b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      last;
7326b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    }
7336b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
7346b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
7356b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  if ($found == 0) {
7366b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    push @$Args, $Arg;
7376b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
7386b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek}
7396b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek
740dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremeneksub RunBuildCommand {
741dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
742dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  my $Args = shift;
7437442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek  my $IgnoreErrors = shift;
744dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  my $Cmd = $Args->[0];
7456195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek  my $CCAnalyzer = shift;
746dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
7473301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  # Get only the part of the command after the last '/'.
7483301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  if ($Cmd =~ /\/([^\/]+)$/) {
7493301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek    $Cmd = $1;
7503301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  }
7513301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  
75263c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  if ($Cmd eq "gcc" or $Cmd eq "cc" or $Cmd eq "llvm-gcc" 
75363c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek   or $Cmd eq "ccc-analyzer") {
754dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek    shift @$Args;
7556195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek    unshift @$Args, $CCAnalyzer;
756dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  }
7577442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek  elsif ($IgnoreErrors) {
7587442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    if ($Cmd eq "make" or $Cmd eq "gmake") {
7596b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      AddIfNotPresent($Args,"-k");
7608912b5427a22d9032cad959c5c22cd9d28d4a66cTed Kremenek      AddIfNotPresent($Args,"-i");
7617442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    }
7627442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    elsif ($Cmd eq "xcodebuild") {
7636b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES");
7647442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    }
7656b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  } 
7666b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
7676b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  if ($Cmd eq "xcodebuild") {
768cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    # Disable distributed builds for xcodebuild.
7696b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    AddIfNotPresent($Args,"-nodistribute");
770cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek
771cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    # Disable PCH files until clang supports them.
772cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO");
773915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    
774915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # When 'CC' is set, xcodebuild uses it to do all linking, even if we are
775915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # linking C++ object files.  Set 'LDPLUSPLUS' so that xcodebuild uses 'g++'
776915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # when linking such files.
77795aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek    die if (!defined $CXX);
77895aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek    my $LDPLUSPLUS = `which $CXX`;
779915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    $LDPLUSPLUS =~ s/\015?\012//;  # strip newlines
780915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS;    
7816b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
782dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
7835a4ddaf39a26f9c7e30d3aeca17c702213a29d9fTed Kremenek  return (system(@$Args) >> 8);
784dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek}
785dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek
786dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------##
7879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options.
7889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
7899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
790a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp {
7919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
7925744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT;
793a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options]
7942b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
795f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted KremenekENDTEXT
796f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek
797fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $BuildName) {
798f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek    print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n";
799f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  }
800f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek
801f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekprint <<ENDTEXT;
8022b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS:
8032b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
804363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -o             - Target directory for HTML report files.  Subdirectories
805a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop                  will be created as needed to represent separate "runs" of
8062b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek                  the analyzer.  If this option is not specified, a directory
8072b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek                  is created in /tmp to store the reports.
8081262fc4d66584224234691d30d779f8ff004585cTed Kremenek
809363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -h             - Display this message.
810363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --help
8111262fc4d66584224234691d30d779f8ff004585cTed Kremenek
812363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -k             - Add a "keep on going" option to the specified build command.
813363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --keep-going     This option currently supports make and xcodebuild.
814f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek                  This is a convenience option; one can specify this
815f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek                  behavior directly using build options.
8162b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
8177cba11262458df05951432b54997eb40a35dbf9eTed Kremenek --html-title [title]       - Specify the title used on generated HTML pages.
8187cba11262458df05951432b54997eb40a35dbf9eTed Kremenek --html-title=[title]         If not specified, a default title will be used.
8197cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
820363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --status-bugs  - By default, the exit status of $Prog is the same as the
821363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek                  executed build command.  Specifying this option causes the
822363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek                  exit status of $Prog to be 1 if it found potential bugs
823363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek                  and 0 otherwise.
8242b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
825386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-cc [compiler path]   - By default, $Prog uses 'gcc' to compile and link
826386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-cc=[compiler path]     your C and Objective-C code. Use this option
827386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek                              to specify an alternate compiler.
828386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek
829386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-c++ [compiler path]  - By default, $Prog uses 'g++' to compile and link
830386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-c++=[compiler path]    your C++ and Objective-C++ code. Use this option
831386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek                              to specify an alternate compiler.
832f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek
833363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -v             - Verbose output from $Prog and the analyzer.
834386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek                  A second and third '-v' increases verbosity.
835363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek
836363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -V             - View analysis results in a web browser when the build
837363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --view           completes.
8387f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
839b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
840386c69316668b9ea8c2591af56f994be16e3ff62Ted KremenekAVAILABLE ANALYSES (multiple analyses may be specified):
841d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek
842d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed KremenekENDTEXT
843b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
844b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  foreach my $Analysis (sort keys %AvailableAnalyses) {
845fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    if (defined $AnalysesDefaultEnabled{$Analysis}) {
846363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek      print " (+)";
847b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    }
848b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    else {
849363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek      print "    ";
850b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    }
851b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    
852b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    print " $Analysis  $AvailableAnalyses{$Analysis}\n";
853b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  }
854b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  
855b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekprint <<ENDTEXT
856b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
857363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek NOTE: "(+)" indicates that an analysis is enabled by default unless one
858363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek       or more analysis options are specified
859b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
8602b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS
8612b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
862363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek You can specify any build option acceptable to the build command.
86339eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek
8645744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE
8652b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
866363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek $Prog -o /tmp/myhtmldir make -j4
8672b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek     
868363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek The above example causes analysis reports to be deposited into
869363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option.
870363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek A different subdirectory is created each time $Prog analyzes a project.
871363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek The analyzer should support most parallel builds, but not distributed builds.
8722b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
8732b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT
8749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
8759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
8769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
8777cba11262458df05951432b54997eb40a35dbf9eTed Kremenek# HtmlEscape - HTML entity encode characters that are special in HTML
8787cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
8797cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
8807cba11262458df05951432b54997eb40a35dbf9eTed Kremeneksub HtmlEscape {
8817cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  # copy argument to new variable so we don't clobber the original
8827cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  my $arg = shift || '';
8837cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  my $tmp = $arg;
8847cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
8857cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  $tmp =~ s/([\<\>\'\"])/sprintf("&#%02x;", chr($1))/ge;
8867cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
8877cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  return $tmp;
8887cba11262458df05951432b54997eb40a35dbf9eTed Kremenek}
8897cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
8907cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
8917cba11262458df05951432b54997eb40a35dbf9eTed Kremenek# ShellEscape - backslash escape characters that are special to the shell
8927cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
8937cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
8947cba11262458df05951432b54997eb40a35dbf9eTed Kremeneksub ShellEscape {
8957cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  # copy argument to new variable so we don't clobber the original
8967cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  my $arg = shift || '';
8977cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  my $tmp = $arg;
8987cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
8997cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  $tmp =~ s/([\!\;\\\'\"\`\<\>\|\s\(\)\[\]\?\#\$\^\&\*\=])/\\$1/g;
9007cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9017cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  return $tmp;
9027cba11262458df05951432b54997eb40a35dbf9eTed Kremenek}
9037cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9047cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
9059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments.
9069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
9079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
9089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir;           # Parent directory to store HTML files.
9099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0;  # Ignore build errors.
9107f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults  = 0;  # View results when the build terminates.
911363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekmy $ExitStatusFoundBugs = 0; # Exit status reflects whether bugs were found
912b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy @AnalysesToRun;
9139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
9149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) {
9159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  DisplayHelp();
916a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  exit 1;
9179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
9189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
9199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) {
9209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
9219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Scan for options we recognize.
9229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
9239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $arg = $ARGV[0];
9249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
9252f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop  if ($arg eq "-h" or $arg eq "--help") {
9269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    DisplayHelp();
927a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop    exit 0;
9289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
9299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
930fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $AvailableAnalyses{$arg}) {
9311262fc4d66584224234691d30d779f8ff004585cTed Kremenek    shift @ARGV;
932b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    push @AnalysesToRun, $arg;
9331262fc4d66584224234691d30d779f8ff004585cTed Kremenek    next;
9341262fc4d66584224234691d30d779f8ff004585cTed Kremenek  }
9351262fc4d66584224234691d30d779f8ff004585cTed Kremenek  
9369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($arg eq "-o") {
9379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
9389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek        
9399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (!@ARGV) {
94023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek      DieDiag("'-o' option requires a target directory name.\n");
9419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
9429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
9439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $HtmlDir = shift @ARGV;
9449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
9459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
9467cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9477cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  if ($arg =~ /^--html-title(=(.+))?$/) {
9487cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    shift @ARGV;
9497cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9507cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    if ($2 eq '') {
9517cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      if (!@ARGV) {
9527cba11262458df05951432b54997eb40a35dbf9eTed Kremenek        DieDiag("'--html-title' option requires a string.\n");
9537cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      }
9547cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9557cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      $HtmlTitle = shift @ARGV;
9567cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    } else {
9577cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      $HtmlTitle = $2;
9587cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    }
9597cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9607cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    next;
9617cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  }
9629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
9632b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek  if ($arg eq "-k" or $arg eq "--keep-going") {
9649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
9659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $IgnoreErrors = 1;
9669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
9679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
9689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
969f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek  if ($arg =~ /^--use-cc(=(.+))?$/) {
970f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    shift @ARGV;
971f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    my $cc;
972f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    
973f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    if ($2 eq "") {
974f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      if (!@ARGV) {
975f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek        DieDiag("'--use-cc' option requires a compiler executable name.\n");
976f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      }
977f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      $cc = shift @ARGV;
978f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    }
979f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    else {
980f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      $cc = $2;
981f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    }
982f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    
983f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    $ENV{"CCC_CC"} = $cc;
984f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    next;
985f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek  }
986f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek  
9877cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  if ($arg =~ /^--use-c\+\+(=(.+))?$/) {
988386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    shift @ARGV;
989386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    
990386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    if ($2 eq "") {
991386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      if (!@ARGV) {
992386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek        DieDiag("'--use-c++' option requires a compiler executable name.\n");
993386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      }
994386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      $CXX = shift @ARGV;
995386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    }
996386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    else {
997386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      $CXX = $2;
998386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    }
999386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    next;
1000386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek  }
1001386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek  
10029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($arg eq "-v") {
10039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
10049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $Verbose++;
10059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
10069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
10079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
10087f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  if ($arg eq "-V" or $arg eq "--view") {
10097f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    shift @ARGV;
10107f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    $ViewResults = 1;    
10117f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    next;
10127f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  }
10137f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  
1014363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  if ($arg eq "--status-bugs") {
1015363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    shift @ARGV;
1016363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    $ExitStatusFoundBugs = 1;
1017363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    next;
1018363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  }
1019363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  
102023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/);
10210062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek  
10229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  last;
10239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
10249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) {
102623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  Diag("No build command specified.\n\n");
10279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  DisplayHelp();
1028a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  exit 1;
10299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
10309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10317cba11262458df05951432b54997eb40a35dbf9eTed Kremenek$CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV)));
10327cba11262458df05951432b54997eb40a35dbf9eTed Kremenek$HtmlTitle = "${CurrentDirSuffix} - scan-build results"
10337cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  unless (defined($HtmlTitle));
1034386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek
10359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports.
1036684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir;
1037a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir);
10389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Set the appropriate environment variables.
1040a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopSetHtmlEnv(\@ARGV, $HtmlDir);
10419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10420b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekmy $Cmd = "$RealBin/ccc-analyzer";
10430b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek
104423cfca3760c482f8543daab62051f5eaa1f98fb4Ted KremenekDieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n")
10450b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek  if (! -x $Cmd);
1046f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek
1047b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekif (! -x $ClangSB) {
1048b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  Diag("'clang' executable not found in '$RealBin'.\n");
1049b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  Diag("Using 'clang' from path.\n");
1050f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek}
10510b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek
105295aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenekif (defined $CXX) {
105395aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek  $ENV{'CXX'} = $CXX;
105495aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek}
105595aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenekelse {
105695aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek  $CXX = 'g++';  # This variable is used by other parts of scan-build
105795aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek                 # that need to know a default C++ compiler to fall back to.
105895aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek}
105995aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek  
10604f4b17da43d3be87a248e1e10bf0b7d8b5891efdTed Kremenek$ENV{'CC'} = $Cmd;
1061f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek$ENV{'CLANG'} = $Clang;
10629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif ($Verbose >= 2) {
10649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  $ENV{'CCC_ANALYZER_VERBOSE'} = 1;
10659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
10669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
1067a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenekif ($Verbose >= 3) {
1068a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek  $ENV{'CCC_ANALYZER_LOG'} = 1;
1069a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek}
1070a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek
10719012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenekif (scalar(@AnalysesToRun) == 0) {
10729012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek  foreach my $key (keys %AnalysesDefaultEnabled) {
10739012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek    push @AnalysesToRun,$key;
10749012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek  }
107501006786e3760cc48c5e94d731b468b811b976d2Ted Kremenek}
10761262fc4d66584224234691d30d779f8ff004585cTed Kremenek
10779012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek$ENV{'CCC_ANALYZER_ANALYSIS'} = join ' ',@AnalysesToRun;
10789012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek
10799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build.
10805656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekmy $ExitStatus = RunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd);
10819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess the HTML directory.
1083363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekmy $NumBugs = Postprocess($HtmlDir, $BaseDir);
10847f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
10857f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekif ($ViewResults and -r "$HtmlDir/index.html") {
108650534dc3ab0737224f9ce739821e1486219c686bTed Kremenek  Diag "Analysis run complete.\n";
10875950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek  Diag "Viewing analysis results in '$HtmlDir' using scan-view.\n";
10885950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek  my $ScanView = "$RealBin/scan-view";
10895950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek  if (! -x $ScanView) { $ScanView = "scan-view"; }
10905950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek  exec $ScanView, "$HtmlDir";
10917f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek}
10925656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek
1093363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekif ($ExitStatusFoundBugs) {
1094363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  exit 1 if ($NumBugs > 0);
1095363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  exit 0;
1096363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek}
1097363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek
10985656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekexit $ExitStatus;
10995656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek
1100