scan-build revision 87f8de72a3c5d61736a14dca271504aaa5020d6f
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;
249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Verbose = 0;       # Verbose output from this script.
269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Prog = "scan-build";
27f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildName;
28f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildDate;
2995aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenekmy $CXX;  # Leave undefined initially.
309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
310e6893840fdd69a8a4d6561663a5a29af237ae08Ted Kremenekmy $TERM = $ENV{'TERM'};
320e6893840fdd69a8a4d6561663a5a29af237ae08Ted Kremenekmy $UseColor = (defined $TERM and $TERM eq 'xterm-color' and -t STDOUT
330e6893840fdd69a8a4d6561663a5a29af237ae08Ted Kremenek                and defined $ENV{'SCAN_BUILD_COLOR'});
3423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek
357cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $UserName = HtmlEscape(getpwuid($<) || 'unknown');
367cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $HostName = HtmlEscape(hostname() || 'unknown');
377cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $CurrentDir = HtmlEscape(getcwd());
387cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $CurrentDirSuffix = basename($CurrentDir);
397cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
407cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $CmdArgs;
417cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
427cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $HtmlTitle;
437cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
447cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $Date = localtime();
457cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
46b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------##
47b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Diagnostics
48b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------##
49b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
5023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub Diag {
5123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  if ($UseColor) {
5223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print BOLD, MAGENTA "$Prog: @_";
5323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print RESET;
5423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  }
5523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  else {
5623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print "$Prog: @_";
5723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  }  
5823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek}
5923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek
60991c54b9b7409656e5593364e065878b5210d556Ted Kremeneksub DiagCrashes {
61991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  my $Dir = shift;
62991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  Diag ("The analyzer crashed on some source files.\n");
63386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek  Diag ("Preprocessed versions of crashed files were deposited in '$Dir/crashes'.\n");
64991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  Diag ("Please consider submitting a bug report using these files:\n");
65991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  Diag ("  http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\n")
66991c54b9b7409656e5593364e065878b5210d556Ted Kremenek}
67991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
6823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub DieDiag {
6923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  if ($UseColor) {
7023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print BOLD, RED "$Prog: ";
7123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print RESET, RED @_;
7223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print RESET;
7323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  }
7423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  else {
7523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    print "$Prog: ", @_;
7623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  }
7723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  exit(0);
7823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek}
7923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek
809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
81b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Some initial preprocessing of Clang options.
82b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------##
83b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
84e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenekmy $ClangSB = Cwd::realpath("$RealBin/clang");
85b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $Clang = $ClangSB;
86b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
87b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekif (! -x $ClangSB) {
88b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  $Clang = "clang";
89b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek}
90b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
91b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy %AvailableAnalyses;
92b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
93b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Query clang for analysis options.
9463c2017737530a7009f709f2fe822f20f63930b1Ted Kremenekopen(PIPE, "-|", $Clang, "--help") or
95445fa776d2bc9207c33a9b9ab4afb9513f6b81b0Ted Kremenek  DieDiag("Cannot execute '$Clang'\n");
9663c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
97b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $FoundAnalysis = 0;
98b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
99b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekwhile(<PIPE>) {
100b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  if ($FoundAnalysis == 0) {
101ce1448bbbdc9366f9bb58e74da0f7a75b3e185ccTed Kremenek    if (/SCA Checks\/Analyses/) {
102b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek      $FoundAnalysis = 1;
103b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    }
104991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
105b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    next;
106b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  }
107b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    
108b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  if (/^\s\s\s\s([^\s]+)\s(.+)$/) {
109b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    next if ($1 =~ /-dump/ or $1 =~ /-view/ 
110b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek             or $1 =~ /-checker-simple/ or $1 =~ /-warn-uninit/);
111b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek             
112b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    $AvailableAnalyses{$1} = $2;
113b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    next;
114b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  }
115b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  
116b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  last;
117b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek}
118b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
119b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekclose (PIPE);
120b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
121b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy %AnalysesDefaultEnabled = (
122b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  '-warn-dead-stores' => 1,
123b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  '-checker-cfref' => 1,
1249012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek  '-warn-objc-methodsigs' => 1,
125bde3a051933b6829ed79d6db0118231c2c01b105Ted Kremenek  '-warn-objc-missing-dealloc' => 1,
1265d443490cd6fb8c772957b7df728f71189d9c55bTed Kremenek  '-warn-objc-unused-ivars' => 1,
127b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek);
128b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
129b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------##
130fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current sub-run.
1319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
1329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
133a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir {  
1349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
135fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  die "Not enough arguments." if (@_ == 0);  
1369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift @_;
137fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    
138fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  my $TmpMode = 0;
139fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (!defined $Dir) {
140ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek    if (`uname` =~ /Darwin/) {
141ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek      $Dir = $ENV{'TMPDIR'};
142ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek      if (!defined $Dir) { $Dir = "/tmp"; }
143ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek    }
144ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek    else {
145ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek      $Dir = "/tmp";
146ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek    }
147ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek    
148fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    $TmpMode = 1;
149fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  }
150fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
1519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Get current date and time.
1529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my @CurrentTime = localtime();
1549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $year  = $CurrentTime[5] + 1900;
1569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $day   = $CurrentTime[3];
1579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $month = $CurrentTime[4] + 1;
1589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1599d7405fafd5bc08d38bc75579927bf414570bd61Ted Kremenek  my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day);
1609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Determine the run number.
1629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $RunNumber;
1649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (-d $Dir) {
1669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (! -r $Dir) {
16823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek      DieDiag("directory '$Dir' exists but is not readable.\n");
1699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
1709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # Iterate over all files in the specified directory.
1729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    my $max = 0;
1749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    opendir(DIR, $Dir);
17629da6c59df7ca994e75139303a9230b24e2abaadTed Kremenek    my @FILES = grep { -d "$Dir/$_" } readdir(DIR);
1779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    closedir(DIR);
1789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    foreach my $f (@FILES) {
1809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
181fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek      # Strip the prefix '$Prog-' if we are dumping files to /tmp.
182fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek      if ($TmpMode) {
183fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek        next if (!($f =~ /^$Prog-(.+)/));
184fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek        $f = $1;
185fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek      }
186fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
187ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
1889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      my @x = split/-/, $f;
1899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if (scalar(@x) != 4);
1909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[0] != $year);
1919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[1] != $month);
1929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[2] != $day);
1939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      
1949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      if ($x[3] > $max) {
1959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek        $max = $x[3];
1969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      }      
1979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
1989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $RunNumber = $max + 1;
2009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  else {
2029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
2039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (-x $Dir) {
20423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek      DieDiag("'$Dir' exists but is not a directory.\n");
2059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
206fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
207fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    if ($TmpMode) {
208445fa776d2bc9207c33a9b9ab4afb9513f6b81b0Ted Kremenek      DieDiag("The directory '/tmp' does not exist or cannot be accessed.\n");
209fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    }
210fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
2119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # $Dir does not exist.  It will be automatically created by the 
2129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # clang driver.  Set the run number to 1.  
213fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
2149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $RunNumber = 1;
2159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
217fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  die "RunNumber must be defined!" if (!defined $RunNumber);
2189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Append the run number.
220fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek  my $NewDir;
221fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if ($TmpMode) {
222fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek    $NewDir = "$Dir/$Prog-$DateString-$RunNumber";
223fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  }
224fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  else {
225fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek    $NewDir = "$Dir/$DateString-$RunNumber";
226fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  }
227fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek  system 'mkdir','-p',$NewDir;
228fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek  return $NewDir;
2299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
2309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
231a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv {
2329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "Wrong number of arguments." if (scalar(@_) != 2);
2349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Args = shift;
2369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift;
2379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "No build command." if (scalar(@$Args) == 0);
2399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Cmd = $$Args[0];
2419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($Cmd =~ /configure/) {
2439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    return;
2449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($Verbose) {
24723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    Diag("Emitting reports for this run to '$Dir'.\n");
2489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  $ENV{'CCC_ANALYZER_HTML'} = $Dir;
2519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
2529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
2539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
25457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file.
25557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------##
25657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
25757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest {
25857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $FName = shift;
25923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName);  
260a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  
261a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  # Use Digest::MD5.  We don't have to be cryptographically secure.  We're
2627ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek  # just looking for duplicate files that come from a non-malicious source.
2637ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek  # We use Digest::MD5 because it is a standard Perl module that should
26463c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  # come bundled on most systems.  
26523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n");
266a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  binmode FILE;
267a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest;
268a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  close(FILE);
269a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  
27063c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  # Return the digest.  
271a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  return $Result;
27257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek}
27357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
27457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------##
2757a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek#  UpdatePrefix - Compute the common prefix of files.
2767a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
2777a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
2787a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekmy $Prefix;
2797a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
2807a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdatePrefix {
2817a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $x = shift;
2827a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $y = basename($x);
2837a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  $x =~ s/\Q$y\E$//;
2847a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
2857a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  # Ignore /usr, /Library, /System, /Developer
2867a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  return if ( $x =~ /^\/usr/ or $x =~ /^\/Library/
2877a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek              or $x =~ /^\/System/ or $x =~ /^\/Developer/);
2887a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
2897a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  if (!defined $Prefix) {
2907a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    $Prefix = $x;
2917a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    return;
2927a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  }
2937a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
29420b2bae90c102f405ba70f602c45660ce1cd0c4eTed Kremenek  chop $Prefix while (!($x =~ /^\Q$Prefix/));
2957a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
2967a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
2977a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub GetPrefix {
2987a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  return $Prefix;
2997a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
3007a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3017a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
3027a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek#  UpdateInFilePath - Update the path in the report file.
3037a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
3047a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3057a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdateInFilePath {
3067a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $fname = shift;
3077a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $regex = shift;
3087a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $newtext = shift;
30963c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
3107a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  open (RIN, $fname) or die "cannot open $fname";
31163c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp";
31263c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
3137a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  while (<RIN>) {
3147a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    s/$regex/$newtext/;
3157a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    print ROUT $_;
3167a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  }
31763c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
3187a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  close (ROUT);
3197a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  close (RIN);
32020161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  system("mv", "$fname.tmp", $fname);
3217a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
3227a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3237a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
3245744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes.
3255744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------##
3265744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
32757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces
32857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports.  We use a cache to solve this problem.
32957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
33057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned;
33157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
3325744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile {
3335744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
3345744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $Index = shift;
3355744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $Dir = shift;
3365744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $FName = shift;
3375744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
33857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  # Compute a digest for the report file.  Determine if we have already
33957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  # scanned a file that looks just like it.
34057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
34157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $digest = ComputeDigest("$Dir/$FName");
34257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
343fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $AlreadyScanned{$digest}) {
34457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    # Redundant file.  Remove it.
34520161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek    system ("rm", "-f", "$Dir/$FName");
34657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    return;
34757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  }
34857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
34957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  $AlreadyScanned{$digest} = 1;
35057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
351809709f46f2516b4054681f0b76284055a84a50fTed Kremenek  # At this point the report file is not world readable.  Make it happen.
35220161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  system ("chmod", "644", "$Dir/$FName");
353684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  
354684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  # Scan the report file for tags.
35523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n");
3565744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
3575744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $BugDesc = "";
35822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugFile = "";
359ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  my $BugCategory;
36022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugPathLength = 1;
36122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugLine = 0;
362ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  my $found = 0;
363ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
3645744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  while (<IN>) {
365ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
366ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    last if ($found == 5);
367ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
3685744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    if (/<!-- BUGDESC (.*) -->$/) {
3695744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek      $BugDesc = $1;
370ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
3715744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    }
37222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGFILE (.*) -->$/) {
37322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugFile = $1;
3747a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek      UpdatePrefix($BugFile);
375ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
37622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
37722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGPATHLENGTH (.*) -->$/) {
37822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugPathLength = $1;
379ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
38022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
38122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGLINE (.*) -->$/) {
38222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugLine = $1;    
383ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
384ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    }
385ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    elsif (/<!-- BUGCATEGORY (.*) -->$/) {
386ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $BugCategory = $1;
387ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
38822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
3895744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  }
3905744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
3915744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  close(IN);
392ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  
393ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  if (!defined $BugCategory) {
394ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    $BugCategory = "Other";
395ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  }
3965744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
39781983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek  push @$Index,[ $FName, $BugCategory, $BugDesc, $BugFile, $BugLine,
39881983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek                 $BugPathLength ];
39922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek}
40022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
40122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------##
4023ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek# CopyFiles - Copy resource files to target directory.
40322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------##
40422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
4053ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremeneksub CopyFiles {
40622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
40722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $Dir = shift;
408e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek
409e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  my $JS = Cwd::realpath("$RealBin/sorttable.js");
41022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  
41123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("Cannot find 'sorttable.js'.\n")
412e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    if (! -r $JS);  
41322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
414e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  system ("cp", $JS, "$Dir");
41522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
41623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n")
41722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    if (! -r "$Dir/sorttable.js");
4183ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek    
419e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  my $CSS = Cwd::realpath("$RealBin/scanview.css");
420e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  
4213ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek  DieDiag("Cannot find 'scanview.css'.\n")
422e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    if (! -r $CSS);
4233ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek
424e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  system ("cp", $CSS, "$Dir");
4253ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek
4263ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek  DieDiag("Could not copy 'scanview.css' to '$Dir'.\n")
427e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    if (! -r $CSS);
4285744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek}
4295744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
4305744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------##
4319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan.
4329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
4339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
434a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess {
4359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift;
437684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  my $BaseDir = shift;
4389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
439fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  die "No directory specified." if (!defined $Dir);
4409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (! -d $Dir) {
44223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    Diag("No bugs found.\n");
443363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    return 0;
4449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
4459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  opendir(DIR, $Dir);
447991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  my $Crashes = 0;
448991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  my @files = grep { if ($_ eq "crashes") { $Crashes++; }
449991c54b9b7409656e5593364e065878b5210d556Ted Kremenek                     /^report-.*\.html$/; } readdir(DIR);
4509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  closedir(DIR);
4519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
452991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  if (scalar(@files) == 0 and $Crashes == 0) {
45323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    Diag("Removing directory '$Dir' because it contains no reports.\n");
45420161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek    system ("rm", "-fR", $Dir);
455363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    return 0;
4569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
4575744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
458991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  # Scan each report file and build an index.  
459991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  my @Index;    
4605744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); }
4615744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
462d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  # Scan the crashes directory and use the information in the .info files
463d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  # to update the common prefix directory.
464d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  if (-d "$Dir/crashes") {
465d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek    opendir(DIR, "$Dir/crashes");
46682a1253077cd0832e4d347062b911cd305ab62d1Ted Kremenek    my @files = grep { /[.]info.txt$/; } readdir(DIR);
467d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek    closedir(DIR);
468d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek    foreach my $file (@files) {
469d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      open IN, "$Dir/crashes/$file" or DieDiag("cannot open $file\n");
470d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      my $Path = <IN>;
471d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      if (defined $Path) { UpdatePrefix($Path); }
472d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      close IN;
473d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek    }    
474d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  }
475d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  
47663c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  # Generate an index.html file.  
47763c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  my $FName = "$Dir/index.html";  
47863c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n");
4795744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
4806e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the header.
4816e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
4825744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT;
4835744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html>
4845744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head>
4857cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<title>${HtmlTitle}</title>
486f143545ce5ce125e7c1aa6fca9df372bfb604e9cTed Kremenek<link type="text/css" rel="stylesheet" href="scanview.css"/>
48722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script>
4886e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript">
4896e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal)
4906e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{
4916e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  var Rows = document.getElementsByTagName("tr");
4926e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  for ( var i = 0 ; i < Rows.length; ++i ) {
4936e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    if (Rows[i].className == RowClass) {
4946e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek      Rows[i].style.display = DisplayVal;
4956e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
4966e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
4976e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek}
498ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
4992350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenekfunction CopyCheckedStateToCheckButtons(SummaryCheckButton) {
5002350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek  var Inputs = document.getElementsByTagName("input");
5012350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek  for ( var i = 0 ; i < Inputs.length; ++i ) {
5022350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek    if (Inputs[i].type == "checkbox") {
5032350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek      if(Inputs[i] != SummaryCheckButton) {
5042350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek        Inputs[i].checked = SummaryCheckButton.checked;
5052350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek        Inputs[i].onclick();
5062350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek	  }
5072350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek    }
5082350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek  }
5092350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek}
5102350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek
511999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenekfunction returnObjById( id ) {
512999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    if (document.getElementById) 
513999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek        var returnVar = document.getElementById(id);
514999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    else if (document.all)
515999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek        var returnVar = document.all[id];
516999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    else if (document.layers) 
517999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek        var returnVar = document.layers[id];
518999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    return returnVar; 
519999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek}
520999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek
521999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenekvar NumUnchecked = 0;
522999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek
5236e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) {
5246e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  if (CheckButton.checked) {
5256e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    SetDisplay(ClassName, "");
526999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    if (--NumUnchecked == 0) {
527999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek      returnObjById("AllBugsCheck").checked = true;
528999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    }
5296e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
5306e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  else {
5316e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    SetDisplay(ClassName, "none");
532999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    NumUnchecked++;
533999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    returnObjById("AllBugsCheck").checked = false;
5346e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
5356e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek}
5366e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script>
5371d1abb1dec3d0b7609809d876a16a64a021e96e7Ted Kremenek<!-- SUMMARYENDHEAD -->
5386e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head>
5396e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body>
5407cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<h1>${HtmlTitle}</h1>
5417cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
5427cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<table>
5437cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>User:</th><td>${UserName}\@${HostName}</td></tr>
5447cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Working Directory:</th><td>${CurrentDir}</td></tr>
5457cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Command Line:</th><td>${CmdArgs}</td></tr>
5467cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Date:</th><td>${Date}</td></tr>
5477cba11262458df05951432b54997eb40a35dbf9eTed KremenekENDTEXT
5487cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
5497cba11262458df05951432b54997eb40a35dbf9eTed Kremenekprint OUT "<tr><th>Version:</th><td>${BuildName} (${BuildDate})</td></tr>\n"
5507cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  if (defined($BuildName) && defined($BuildDate));
5517cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
5527cba11262458df05951432b54997eb40a35dbf9eTed Kremenekprint OUT <<ENDTEXT;
5537cba11262458df05951432b54997eb40a35dbf9eTed Kremenek</table>
5546e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT
5556e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
556991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  if (scalar(@files)) {
557991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    # Print out the summary table.
558991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my %Totals;
559ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
560991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    for my $row ( @Index ) {
561ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $bug_type = ($row->[2]);
562ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $bug_category = ($row->[1]);
563ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $key = "$bug_category:$bug_type";
564ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
565ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      if (!defined $Totals{$key}) { $Totals{$key} = [1,$bug_category,$bug_type]; }
566ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      else { $Totals{$key}->[0]++; }
5676e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
568991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
5697cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    print OUT "<h2>Bug Summary</h2>";
570991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
571991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    if (defined $BuildName) {
572991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n"
5736e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
574f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  
5752350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek  
5762350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek  my $TotalBugs = scalar(@Index);
5776e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT;
578ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<table>
579ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<thead><tr><td>Bug Type</td><td>Quantity</td><td class="sorttable_nosort">Display?</td></tr></thead>
580999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek<tr style="font-weight:bold"><td class="SUMM_DESC">All Bugs</td><td class="Q">$TotalBugs</td><td><center><input type="checkbox" id="AllBugsCheck" onClick="CopyCheckedStateToCheckButtons(this);" checked/></center></td></tr>
5816e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT
5826e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
583ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    my $last_category;
584ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
585ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    for my $key (
586ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      sort {
587ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        my $x = $Totals{$a};
588ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        my $y = $Totals{$b};
589ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        my $res = $x->[1] cmp $y->[1];
590ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        $res = $x->[2] cmp $y->[2] if ($res == 0);
591ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        $res
592ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      } keys %Totals ) 
593ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    {
594ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $val = $Totals{$key};
595ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $category = $val->[1];
596ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      if (!defined $last_category or $last_category ne $category) {
597ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        $last_category = $category;
598ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT "<tr><th>$category</th><th colspan=2></th></tr>\n";
599ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      }      
600ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $x = lc $key;
601ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $x =~ s/[ ,'":\/()]+/_/g;
602ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<tr><td class=\"SUMM_DESC\">";
603ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT $val->[2];
6042350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek      print OUT "</td><td class=\"Q\">";
605ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT $val->[0];
606ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td><td><center><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></center></td></tr>\n";
607991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }
6086e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
6096e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the table of errors.
6106e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
6116e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT;
6126e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table>
6137cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<h2>Reports</h2>
614ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
615ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<table class="sortable" style="table-layout:automatic">
616ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<thead><tr>
617ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <td>Bug Group</td>
618ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <td class="sorttable_sorted">Bug Type<span id="sorttable_sortfwdind">&nbsp;&#x25BE;</span></td>
619bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>File</td>
620ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <td class="Q">Line</td>
62181983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek  <td class="Q">Path Length</td>
6222645c77072d45fabb2bdc0a3621908035c7113dcTed Kremenek  <td class="sorttable_nosort"></td>
623ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <!-- REPORTBUGCOL -->
624ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek</tr></thead>
625ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<tbody>
6265744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT
6279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
628991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $prefix = GetPrefix();
629991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $regex;
630991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $InFileRegex;
631991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $InFilePrefix = "File:</td><td>";
6327a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
633991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    if (defined $prefix) { 
634991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      $regex = qr/^\Q$prefix\E/is;    
635991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is;
636991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }    
6377a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
638ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    for my $row ( sort { $a->[2] cmp $b->[2] } @Index ) {
639ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $x = "$row->[1]:$row->[2]";
640ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $x = lc $x;
641ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $x =~ s/[ ,'":\/()]+/_/g;
6426e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    
643991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      my $ReportFile = $row->[0];
644ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          
645ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<tr class=\"bt_$x\">";
646ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<td class=\"DESC\">";
647991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT $row->[1];
648ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td>";
649ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<td class=\"DESC\">";
650ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT $row->[2];
651ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td>";
652ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
653ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      # Update the file prefix.      
654ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $fname = $row->[3];
655ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
656991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      if (defined $regex) {
657991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        $fname =~ s/$regex//;
658991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix)
659991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      }
660ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
66191639ef5aa2bd94c14ae872cf747c58174ffe9b8Ted Kremenek      print OUT "<td>";      
662ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my @fname = split /\//,$fname;
663ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      if ($#fname > 0) {
664ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        while ($#fname >= 0) {
665ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          my $x = shift @fname;
666ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          print OUT $x;
667ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          if ($#fname >= 0) {
668ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek            print OUT "<span class=\"W\"> </span>/";
669ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          }
670ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        }
671ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      }
672ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      else {
673ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT $fname;
67491639ef5aa2bd94c14ae872cf747c58174ffe9b8Ted Kremenek      }      
675ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td>";
676ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
677ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      # Print out the quantities.
67881983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek      for my $j ( 4 .. 5 ) {
679ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT "<td class=\"Q\">$row->[$j]</td>";        
680ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      }
681ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
682991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      # Print the rest of the columns.
68381983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek      for (my $j = 6; $j <= $#{$row}; ++$j) {
684ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT "<td>$row->[$j]</td>"
685991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      }
6867f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
687991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      # Emit the "View" link.
68868005ddb49b88c2f6cdd88185d72d8b411d2dbc9Ted Kremenek      print OUT "<td><a href=\"$ReportFile#EndPath\">View Report</a></td>";
6893cea9ee6b77ac797ebb910bdf45d1d7f8f68e37bTed Kremenek        
690e43038ec3d0ef187fcdddf101ef653bbbdb1069aDaniel Dunbar      # Emit REPORTBUG markers.
691ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "\n<!-- REPORTBUG id=\"$ReportFile\" -->\n";
692e43038ec3d0ef187fcdddf101ef653bbbdb1069aDaniel Dunbar        
693991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      # End the row.
694991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT "</tr>\n";
695991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }
696991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  
697ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    print OUT "</tbody>\n</table>\n\n";
698991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  }
699991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
700991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  if ($Crashes) {
701991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    # Read the crash directory for files.
702991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    opendir(DIR, "$Dir/crashes");
70382a1253077cd0832e4d347062b911cd305ab62d1Ted Kremenek    my @files = grep { /[.]info.txt$/ } readdir(DIR);
704991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    closedir(DIR);
705991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
706991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    if (scalar(@files)) {
707991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT <<ENDTEXT;
7087cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<h2>Analyzer Failures</h2>
709991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
7105d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek<p>The analyzer had problems processing the following files:</p>
711991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
712991c54b9b7409656e5593364e065878b5210d556Ted Kremenek<table>
7139f9b1fded49acff77e61b3ed1afc8bbaaefe6f34Ted Kremenek<thead><tr><td>Problem</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>
714991c54b9b7409656e5593364e065878b5210d556Ted KremenekENDTEXT
715991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  
716991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      foreach my $file (sort @files) {
71782a1253077cd0832e4d347062b911cd305ab62d1Ted Kremenek        $file =~ /(.+).info.txt$/;
718991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        # Get the preprocessed file.
719991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        my $ppfile = $1;
720991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        # Open the info file and get the name of the source file.
721991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        open (INFO, "$Dir/crashes/$file") or
722991c54b9b7409656e5593364e065878b5210d556Ted Kremenek          die "Cannot open $Dir/crashes/$file\n";
723991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        my $srcfile = <INFO>;
7245d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek        chomp $srcfile;
7255d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek        my $problem = <INFO>;
7265d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek        chomp $problem;
727991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        close (INFO);
728991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        # Print the information in the table.
729d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek        my $prefix = GetPrefix();
7309f9b1fded49acff77e61b3ed1afc8bbaaefe6f34Ted Kremenek        if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; }
7319f9b1fded49acff77e61b3ed1afc8bbaaefe6f34Ted 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";
732ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar        my $ppfile_clang = $ppfile;
733ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar        $ppfile_clang =~ s/[.](.+)$/.clang.$1/;
7347ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        print OUT "  <!-- REPORTPROBLEM src=\"$srcfile\" file=\"crashes/$ppfile\" clangfile=\"crashes/$ppfile_clang\" stderr=\"crashes/$ppfile.stderr.txt\" info=\"crashes/$ppfile.info.txt\" -->\n";
735991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      }
736991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
737991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT <<ENDTEXT;
738991c54b9b7409656e5593364e065878b5210d556Ted Kremenek</table>
739ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar<p>Please consider submitting preprocessed files as <a href="http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs">bug reports</a>. <!-- REPORTCRASHES --> </p>
740991c54b9b7409656e5593364e065878b5210d556Ted KremenekENDTEXT
741991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }
7425744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  }
7435744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
744991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  print OUT "</body></html>\n";  
7455744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  close(OUT);
7463ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek  CopyFiles($Dir);
74720161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek
74820161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  # Make sure $Dir and $BaseDir are world readable/executable.
74920161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  system("chmod", "755", $Dir);
750fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $BaseDir) { system("chmod", "755", $BaseDir); }
75120161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek
75223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  my $Num = scalar(@Index);
753150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek  Diag("$Num bugs found.\n");
754150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek  if ($Num > 0 && -r "$Dir/index.html") {
7555950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek    Diag("Run 'scan-view $Dir' to examine bug reports.\n");
756150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek  }
757363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  
758991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  DiagCrashes($Dir) if ($Crashes);
759991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  
760363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  return $Num;
7619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
7629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
7639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
764dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command.
765dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------##
766dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek
7676b6289848e215ff12d4d54fe0602d3371db52788Ted Kremeneksub AddIfNotPresent {
7686b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $Args = shift;
7696b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $Arg = shift;  
7706b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $found = 0;
7716b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
7726b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  foreach my $k (@$Args) {
7736b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    if ($k eq $Arg) {
7746b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      $found = 1;
7756b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      last;
7766b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    }
7776b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
7786b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
7796b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  if ($found == 0) {
7806b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    push @$Args, $Arg;
7816b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
7826b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek}
7836b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek
784dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremeneksub RunBuildCommand {
785dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
786dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  my $Args = shift;
7877442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek  my $IgnoreErrors = shift;
788dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  my $Cmd = $Args->[0];
7896195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek  my $CCAnalyzer = shift;
790dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
7913301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  # Get only the part of the command after the last '/'.
7923301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  if ($Cmd =~ /\/([^\/]+)$/) {
7933301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek    $Cmd = $1;
7943301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  }
7953301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  
79663c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  if ($Cmd eq "gcc" or $Cmd eq "cc" or $Cmd eq "llvm-gcc" 
79763c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek   or $Cmd eq "ccc-analyzer") {
798dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek    shift @$Args;
7996195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek    unshift @$Args, $CCAnalyzer;
800dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  }
8017442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek  elsif ($IgnoreErrors) {
8027442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    if ($Cmd eq "make" or $Cmd eq "gmake") {
8036b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      AddIfNotPresent($Args,"-k");
8048912b5427a22d9032cad959c5c22cd9d28d4a66cTed Kremenek      AddIfNotPresent($Args,"-i");
8057442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    }
8067442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    elsif ($Cmd eq "xcodebuild") {
8076b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES");
8087442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    }
8096b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  } 
8106b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
8116b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  if ($Cmd eq "xcodebuild") {
812cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    # Disable distributed builds for xcodebuild.
8136b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    AddIfNotPresent($Args,"-nodistribute");
814cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek
815cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    # Disable PCH files until clang supports them.
816cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO");
817915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    
818915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # When 'CC' is set, xcodebuild uses it to do all linking, even if we are
819915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # linking C++ object files.  Set 'LDPLUSPLUS' so that xcodebuild uses 'g++'
820915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # when linking such files.
82195aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek    die if (!defined $CXX);
82295aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek    my $LDPLUSPLUS = `which $CXX`;
823915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    $LDPLUSPLUS =~ s/\015?\012//;  # strip newlines
824915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS;    
8256b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
826dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
8275a4ddaf39a26f9c7e30d3aeca17c702213a29d9fTed Kremenek  return (system(@$Args) >> 8);
828dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek}
829dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek
830dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------##
8319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options.
8329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
8339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
834a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp {
8359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
8365744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT;
837a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options]
8382b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
839f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted KremenekENDTEXT
840f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek
841fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $BuildName) {
842f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek    print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n";
843f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  }
844f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek
845f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekprint <<ENDTEXT;
8462b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS:
8472b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
848e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek -analyze-headers - Also analyze functions in #included files.
849e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek
85007c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu -store [model] - Specify the store model used by the analyzer. By default,
85107c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu                  the 'basic' store model is used. 'region' specifies a field-
85207c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu                  sensitive store model. Be warned that the 'region' model
85307c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu                  is still in very early testing phase and may often crash.
85407c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu
855363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -o             - Target directory for HTML report files.  Subdirectories
856a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop                  will be created as needed to represent separate "runs" of
8572b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek                  the analyzer.  If this option is not specified, a directory
858ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek                  is created in /tmp (TMPDIR on Mac OS X) to store the reports.
8591262fc4d66584224234691d30d779f8ff004585cTed Kremenek
860363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -h             - Display this message.
861363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --help
8621262fc4d66584224234691d30d779f8ff004585cTed Kremenek
863363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -k             - Add a "keep on going" option to the specified build command.
864363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --keep-going     This option currently supports make and xcodebuild.
865f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek                  This is a convenience option; one can specify this
866f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek                  behavior directly using build options.
8672b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
8687cba11262458df05951432b54997eb40a35dbf9eTed Kremenek --html-title [title]       - Specify the title used on generated HTML pages.
8697cba11262458df05951432b54997eb40a35dbf9eTed Kremenek --html-title=[title]         If not specified, a default title will be used.
8707cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
871363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --status-bugs  - By default, the exit status of $Prog is the same as the
872363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek                  executed build command.  Specifying this option causes the
873363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek                  exit status of $Prog to be 1 if it found potential bugs
874363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek                  and 0 otherwise.
8752b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
876386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-cc [compiler path]   - By default, $Prog uses 'gcc' to compile and link
877386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-cc=[compiler path]     your C and Objective-C code. Use this option
878386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek                              to specify an alternate compiler.
879386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek
880386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-c++ [compiler path]  - By default, $Prog uses 'g++' to compile and link
881386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-c++=[compiler path]    your C++ and Objective-C++ code. Use this option
882386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek                              to specify an alternate compiler.
883f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek
884363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -v             - Verbose output from $Prog and the analyzer.
885386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek                  A second and third '-v' increases verbosity.
886363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek
887363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -V             - View analysis results in a web browser when the build
888363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --view           completes.
8897f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
890b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
891386c69316668b9ea8c2591af56f994be16e3ff62Ted KremenekAVAILABLE ANALYSES (multiple analyses may be specified):
892d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek
893d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed KremenekENDTEXT
894b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
895b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  foreach my $Analysis (sort keys %AvailableAnalyses) {
896fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    if (defined $AnalysesDefaultEnabled{$Analysis}) {
897363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek      print " (+)";
898b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    }
899b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    else {
900363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek      print "    ";
901b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    }
902b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    
903b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    print " $Analysis  $AvailableAnalyses{$Analysis}\n";
904b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  }
905b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  
906b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekprint <<ENDTEXT
907b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
908363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek NOTE: "(+)" indicates that an analysis is enabled by default unless one
909363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek       or more analysis options are specified
910b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
9112b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS
9122b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
913363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek You can specify any build option acceptable to the build command.
91439eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek
9155744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE
9162b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
917363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek $Prog -o /tmp/myhtmldir make -j4
9182b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek     
919363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek The above example causes analysis reports to be deposited into
920363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option.
921363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek A different subdirectory is created each time $Prog analyzes a project.
922363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek The analyzer should support most parallel builds, but not distributed builds.
9232b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
9242b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT
9259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
9269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
9279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
9287cba11262458df05951432b54997eb40a35dbf9eTed Kremenek# HtmlEscape - HTML entity encode characters that are special in HTML
9297cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
9307cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9317cba11262458df05951432b54997eb40a35dbf9eTed Kremeneksub HtmlEscape {
9327cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  # copy argument to new variable so we don't clobber the original
9337cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  my $arg = shift || '';
9347cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  my $tmp = $arg;
93587f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek  $tmp =~ s/&/&amp;/g;
93687f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek  $tmp =~ s/</&lt;/g;
93787f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek  $tmp =~ s/>/&gt;/g;
9387cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  return $tmp;
9397cba11262458df05951432b54997eb40a35dbf9eTed Kremenek}
9407cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9417cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
9427cba11262458df05951432b54997eb40a35dbf9eTed Kremenek# ShellEscape - backslash escape characters that are special to the shell
9437cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
9447cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9457cba11262458df05951432b54997eb40a35dbf9eTed Kremeneksub ShellEscape {
9467cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  # copy argument to new variable so we don't clobber the original
9477cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  my $arg = shift || '';
94887f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek  if ($arg =~ /["\s]/) { return "'" . $arg . "'"; }
94987f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek  return $arg;
9507cba11262458df05951432b54997eb40a35dbf9eTed Kremenek}
9517cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9527cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
9539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments.
9549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
9559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
956e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenekmy $AnalyzeHeaders = 0;
9579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir;           # Parent directory to store HTML files.
9589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0;  # Ignore build errors.
9597f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults  = 0;  # View results when the build terminates.
960363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekmy $ExitStatusFoundBugs = 0; # Exit status reflects whether bugs were found
961b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy @AnalysesToRun;
96207c3767be59472e19183c7b51fae76481465cb51Zhongxing Xumy $StoreModel;
9639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
9649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) {
9659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  DisplayHelp();
966a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  exit 1;
9679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
9689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
9699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) {
9709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
9719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Scan for options we recognize.
9729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
9739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $arg = $ARGV[0];
9749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
9752f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop  if ($arg eq "-h" or $arg eq "--help") {
9769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    DisplayHelp();
977a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop    exit 0;
9789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
9799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
980e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  if ($arg eq '-analyze-headers') {
981e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    shift @ARGV;    
982e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    $AnalyzeHeaders = 1;
983e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    next;
984e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  }
985e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  
986fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $AvailableAnalyses{$arg}) {
9871262fc4d66584224234691d30d779f8ff004585cTed Kremenek    shift @ARGV;
988b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    push @AnalysesToRun, $arg;
9891262fc4d66584224234691d30d779f8ff004585cTed Kremenek    next;
9901262fc4d66584224234691d30d779f8ff004585cTed Kremenek  }
9911262fc4d66584224234691d30d779f8ff004585cTed Kremenek  
9929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($arg eq "-o") {
9939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
9949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek        
9959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (!@ARGV) {
99623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek      DieDiag("'-o' option requires a target directory name.\n");
9979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
9989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
9999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $HtmlDir = shift @ARGV;
10009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
10019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
10027cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10037cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  if ($arg =~ /^--html-title(=(.+))?$/) {
10047cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    shift @ARGV;
10057cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10067cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    if ($2 eq '') {
10077cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      if (!@ARGV) {
10087cba11262458df05951432b54997eb40a35dbf9eTed Kremenek        DieDiag("'--html-title' option requires a string.\n");
10097cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      }
10107cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10117cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      $HtmlTitle = shift @ARGV;
10127cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    } else {
10137cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      $HtmlTitle = $2;
10147cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    }
10157cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10167cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    next;
10177cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  }
10189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
10192b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek  if ($arg eq "-k" or $arg eq "--keep-going") {
10209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
10219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $IgnoreErrors = 1;
10229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
10239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
10249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1025f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek  if ($arg =~ /^--use-cc(=(.+))?$/) {
1026f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    shift @ARGV;
1027f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    my $cc;
1028f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    
1029f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    if ($2 eq "") {
1030f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      if (!@ARGV) {
1031f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek        DieDiag("'--use-cc' option requires a compiler executable name.\n");
1032f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      }
1033f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      $cc = shift @ARGV;
1034f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    }
1035f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    else {
1036f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      $cc = $2;
1037f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    }
1038f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    
1039f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    $ENV{"CCC_CC"} = $cc;
1040f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    next;
1041f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek  }
1042f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek  
10437cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  if ($arg =~ /^--use-c\+\+(=(.+))?$/) {
1044386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    shift @ARGV;
1045386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    
1046386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    if ($2 eq "") {
1047386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      if (!@ARGV) {
1048386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek        DieDiag("'--use-c++' option requires a compiler executable name.\n");
1049386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      }
1050386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      $CXX = shift @ARGV;
1051386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    }
1052386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    else {
1053386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      $CXX = $2;
1054386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    }
1055386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    next;
1056386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek  }
1057386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek  
10589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($arg eq "-v") {
10599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
10609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $Verbose++;
10619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
10629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
10639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
10647f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  if ($arg eq "-V" or $arg eq "--view") {
10657f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    shift @ARGV;
10667f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    $ViewResults = 1;    
10677f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    next;
10687f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  }
10697f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  
1070363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  if ($arg eq "--status-bugs") {
1071363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    shift @ARGV;
1072363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    $ExitStatusFoundBugs = 1;
1073363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    next;
1074363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  }
107507c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu
107607c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu  if ($arg eq "-store") {
107707c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu    shift @ARGV;
107807c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu    $StoreModel = '-analyzer-store-' . shift @ARGV;
107907c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu    next;
108007c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu  }
1081363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  
108223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/);
10830062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek  
10849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  last;
10859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
10869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) {
108823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  Diag("No build command specified.\n\n");
10899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  DisplayHelp();
1090a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  exit 1;
10919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
10929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10937cba11262458df05951432b54997eb40a35dbf9eTed Kremenek$CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV)));
10947cba11262458df05951432b54997eb40a35dbf9eTed Kremenek$HtmlTitle = "${CurrentDirSuffix} - scan-build results"
10957cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  unless (defined($HtmlTitle));
1096386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek
10979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports.
1098684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir;
1099a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir);
11009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
11019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Set the appropriate environment variables.
1102a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopSetHtmlEnv(\@ARGV, $HtmlDir);
11039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
1104e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenekmy $Cmd = Cwd::realpath("$RealBin/ccc-analyzer");
11050b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek
110623cfca3760c482f8543daab62051f5eaa1f98fb4Ted KremenekDieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n")
11070b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek  if (! -x $Cmd);
1108f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek
1109b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekif (! -x $ClangSB) {
1110b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  Diag("'clang' executable not found in '$RealBin'.\n");
1111b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  Diag("Using 'clang' from path.\n");
1112f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek}
11130b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek
111495aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenekif (defined $CXX) {
111595aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek  $ENV{'CXX'} = $CXX;
111695aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek}
111795aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenekelse {
111895aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek  $CXX = 'g++';  # This variable is used by other parts of scan-build
111995aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek                 # that need to know a default C++ compiler to fall back to.
112095aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek}
112195aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek  
11224f4b17da43d3be87a248e1e10bf0b7d8b5891efdTed Kremenek$ENV{'CC'} = $Cmd;
1123f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek$ENV{'CLANG'} = $Clang;
11249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
11259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif ($Verbose >= 2) {
11269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  $ENV{'CCC_ANALYZER_VERBOSE'} = 1;
11279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
11289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
1129a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenekif ($Verbose >= 3) {
1130a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek  $ENV{'CCC_ANALYZER_LOG'} = 1;
1131a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek}
1132a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek
11339012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenekif (scalar(@AnalysesToRun) == 0) {
11349012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek  foreach my $key (keys %AnalysesDefaultEnabled) {
11359012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek    push @AnalysesToRun,$key;
11369012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek  }
113701006786e3760cc48c5e94d731b468b811b976d2Ted Kremenek}
11381262fc4d66584224234691d30d779f8ff004585cTed Kremenek
1139e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenekif ($AnalyzeHeaders) {
1140e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  push @AnalysesToRun,"-analyzer-opt-analyze-headers";  
1141e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek}
1142e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek
11439012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek$ENV{'CCC_ANALYZER_ANALYSIS'} = join ' ',@AnalysesToRun;
11449012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek
11453cab2b1c3798f2a6aa3526875801a02aebf6fc1dZhongxing Xuif (defined $StoreModel) {
114607c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu  $ENV{'CCC_ANALYZER_STORE_MODEL'} = $StoreModel;
114707c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu}
114807c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu
11499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build.
11505656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekmy $ExitStatus = RunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd);
11519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
11529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess the HTML directory.
1153363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekmy $NumBugs = Postprocess($HtmlDir, $BaseDir);
11547f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
11557f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekif ($ViewResults and -r "$HtmlDir/index.html") {
115650534dc3ab0737224f9ce739821e1486219c686bTed Kremenek  Diag "Analysis run complete.\n";
11575950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek  Diag "Viewing analysis results in '$HtmlDir' using scan-view.\n";
1158e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  my $ScanView = Cwd::realpath("$RealBin/scan-view");
11595950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek  if (! -x $ScanView) { $ScanView = "scan-view"; }
11605950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek  exec $ScanView, "$HtmlDir";
11617f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek}
11625656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek
1163363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekif ($ExitStatusFoundBugs) {
1164363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  exit 1 if ($NumBugs > 0);
1165363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  exit 0;
1166363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek}
1167363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek
11685656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekexit $ExitStatus;
11695656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek
1170