scan-build revision fd9df0eddd7d2b190f740f33a3d08f611c0be3f0
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);
22cd25c13ade3afa829c87ca1ed0ed0d379f426251Ted Kremenekuse Cwd qw/ getcwd abs_path /;
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;
62938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  Diag ("The analyzer encountered problems on some source files.\n");
63938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  Diag ("Preprocessed versions of these sources were deposited in '$Dir/failures'.\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
84833da0235676a111d6192b0b182a8c16c27cceeeTed Kremenek# First, look for 'clang-cc' in libexec.
85fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenekmy $ClangCCSB = Cwd::realpath("$RealBin/libexec/clang-cc");
86833da0235676a111d6192b0b182a8c16c27cceeeTed Kremenek# Second, look for 'clang-cc' in the same directory as scan-build.
87fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenekif (!defined $ClangCCSB || ! -x $ClangCCSB) {
88fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek  $ClangCCSB = Cwd::realpath("$RealBin/clang-cc");
8943b7bd31f906f4020090ffb4f64a09d35fb13680Ted Kremenek}
90833da0235676a111d6192b0b182a8c16c27cceeeTed Kremenek# Third, look for 'clang-cc' in ../libexec
91fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenekif (!defined $ClangCCSB || ! -x $ClangCCSB) {
92fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek  $ClangCCSB = Cwd::realpath("$RealBin/../libexec/clang-cc");
93fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek}
94fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek# Finally, default to looking for 'clang-cc' in the path.
95fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenekif (!defined $ClangCCSB || ! -x $ClangCCSB) {
96fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek  $ClangCCSB = "clang-cc";
97fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek}
98fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenekmy $ClangCC = $ClangCCSB;
99fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek
100fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek# Now find 'clang'
101fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenekmy $ClangSB = Cwd::realpath("$RealBin/bin/clang");
1028d10cdd9aa1d58f1898adf7752a7026f151ebc04Ted Kremenekif (!defined $ClangSB || ! -x $ClangSB) {
103fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek  $ClangSB = Cwd::realpath("$RealBin/clang");
104fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek}
105fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek# Third, look for 'clang' in ../bin
106fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenekif (!defined $ClangSB || ! -x $ClangSB) {
107fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek  $ClangSB = Cwd::realpath("$RealBin/../bin/clang");
108b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek}
109833da0235676a111d6192b0b182a8c16c27cceeeTed Kremenek# Finally, default to looking for 'clang-cc' in the path.
110833da0235676a111d6192b0b182a8c16c27cceeeTed Kremenekif (!defined $ClangSB || ! -x $ClangSB) {
111fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek  $ClangSB = "clang";
112833da0235676a111d6192b0b182a8c16c27cceeeTed Kremenek}
113833da0235676a111d6192b0b182a8c16c27cceeeTed Kremenekmy $Clang = $ClangSB;
114b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
115fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek
116b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy %AvailableAnalyses;
117b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
118b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Query clang for analysis options.
119fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenekopen(PIPE, "-|", $ClangCC, "--help") or
120fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek  DieDiag("Cannot execute '$ClangCC'\n");
12163c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
122b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy $FoundAnalysis = 0;
123b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
124b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekwhile(<PIPE>) {
125b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  if ($FoundAnalysis == 0) {
126938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    if (/Checks and Analyses/) {
127b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek      $FoundAnalysis = 1;
128b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    }
129b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    next;
130b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  }
131b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    
132b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  if (/^\s\s\s\s([^\s]+)\s(.+)$/) {
133b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    next if ($1 =~ /-dump/ or $1 =~ /-view/ 
134b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek             or $1 =~ /-checker-simple/ or $1 =~ /-warn-uninit/);
135b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek             
136b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    $AvailableAnalyses{$1} = $2;
137b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    next;
138938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  }  
139b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  last;
140b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek}
141b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
142b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekclose (PIPE);
143b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
144b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy %AnalysesDefaultEnabled = (
145b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  '-warn-dead-stores' => 1,
146b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  '-checker-cfref' => 1,
1479012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek  '-warn-objc-methodsigs' => 1,
148d76c6a38b8080b3255c37f787bcaf4a4724f330cTed Kremenek  # Do not enable the missing -dealloc check by default.
149d76c6a38b8080b3255c37f787bcaf4a4724f330cTed Kremenek  #  '-warn-objc-missing-dealloc' => 1,
1505d443490cd6fb8c772957b7df728f71189d9c55bTed Kremenek  '-warn-objc-unused-ivars' => 1,
151b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek);
152b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
153b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------##
154fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current sub-run.
1559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
1569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
157a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir {  
1589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
159fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  die "Not enough arguments." if (@_ == 0);  
1609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift @_;
161fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    
162fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  my $TmpMode = 0;
163fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (!defined $Dir) {
164ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek    if (`uname` =~ /Darwin/) {
165ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek      $Dir = $ENV{'TMPDIR'};
166ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek      if (!defined $Dir) { $Dir = "/tmp"; }
167ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek    }
168ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek    else {
169ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek      $Dir = "/tmp";
170ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek    }
171ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek    
172fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    $TmpMode = 1;
173fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  }
174bf762c9b48673e9686a97fe6ca144d891316164eTed Kremenek  
175bf762c9b48673e9686a97fe6ca144d891316164eTed Kremenek  # Chop off any trailing '/' characters.
176bf762c9b48673e9686a97fe6ca144d891316164eTed Kremenek  while ($Dir =~ /\/$/) { chop $Dir; }
177fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
1789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Get current date and time.
1799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my @CurrentTime = localtime();
1819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $year  = $CurrentTime[5] + 1900;
1839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $day   = $CurrentTime[3];
1849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $month = $CurrentTime[4] + 1;
1859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1869d7405fafd5bc08d38bc75579927bf414570bd61Ted Kremenek  my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day);
1879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Determine the run number.
1899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $RunNumber;
1919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (-d $Dir) {
1939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (! -r $Dir) {
19523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek      DieDiag("directory '$Dir' exists but is not readable.\n");
1969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
1979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # Iterate over all files in the specified directory.
1999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
2009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    my $max = 0;
2019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
2029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    opendir(DIR, $Dir);
20329da6c59df7ca994e75139303a9230b24e2abaadTed Kremenek    my @FILES = grep { -d "$Dir/$_" } readdir(DIR);
2049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    closedir(DIR);
2059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
2069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    foreach my $f (@FILES) {
2079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
208fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek      # Strip the prefix '$Prog-' if we are dumping files to /tmp.
209fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek      if ($TmpMode) {
210fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek        next if (!($f =~ /^$Prog-(.+)/));
211fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek        $f = $1;
212fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek      }
213fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
214ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
2159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      my @x = split/-/, $f;
2169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if (scalar(@x) != 4);
2179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[0] != $year);
2189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[1] != $month);
2199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[2] != $day);
2209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      
2219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      if ($x[3] > $max) {
2229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek        $max = $x[3];
2239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      }      
2249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
2259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
2269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $RunNumber = $max + 1;
2279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  else {
2299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
2309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (-x $Dir) {
23123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek      DieDiag("'$Dir' exists but is not a directory.\n");
2329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
233fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
234fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    if ($TmpMode) {
235445fa776d2bc9207c33a9b9ab4afb9513f6b81b0Ted Kremenek      DieDiag("The directory '/tmp' does not exist or cannot be accessed.\n");
236fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    }
237fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
2389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # $Dir does not exist.  It will be automatically created by the 
2399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # clang driver.  Set the run number to 1.  
240fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek
2419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $RunNumber = 1;
2429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
244fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  die "RunNumber must be defined!" if (!defined $RunNumber);
2459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Append the run number.
247fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek  my $NewDir;
248fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if ($TmpMode) {
249fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek    $NewDir = "$Dir/$Prog-$DateString-$RunNumber";
250fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  }
251fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  else {
252fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek    $NewDir = "$Dir/$DateString-$RunNumber";
253fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  }
254fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek  system 'mkdir','-p',$NewDir;
255fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek  return $NewDir;
2569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
2579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
258a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv {
2599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "Wrong number of arguments." if (scalar(@_) != 2);
2619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Args = shift;
2639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift;
2649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "No build command." if (scalar(@$Args) == 0);
2669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Cmd = $$Args[0];
2689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($Cmd =~ /configure/) {
2709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    return;
2719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($Verbose) {
27423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    Diag("Emitting reports for this run to '$Dir'.\n");
2759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  $ENV{'CCC_ANALYZER_HTML'} = $Dir;
2789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
2799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
2809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
28157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file.
28257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------##
28357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
28457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest {
28557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $FName = shift;
28623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName);  
287a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  
288a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  # Use Digest::MD5.  We don't have to be cryptographically secure.  We're
2897ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek  # just looking for duplicate files that come from a non-malicious source.
2907ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek  # We use Digest::MD5 because it is a standard Perl module that should
29163c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  # come bundled on most systems.  
29223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n");
293a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  binmode FILE;
294a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest;
295a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  close(FILE);
296a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  
29763c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  # Return the digest.  
298a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  return $Result;
29957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek}
30057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
30157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------##
3027a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek#  UpdatePrefix - Compute the common prefix of files.
3037a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
3047a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3057a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekmy $Prefix;
3067a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3077a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdatePrefix {
3087a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $x = shift;
3097a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $y = basename($x);
3107a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  $x =~ s/\Q$y\E$//;
3117a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3127a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  if (!defined $Prefix) {
3137a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    $Prefix = $x;
3147a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    return;
3157a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  }
3167a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
31720b2bae90c102f405ba70f602c45660ce1cd0c4eTed Kremenek  chop $Prefix while (!($x =~ /^\Q$Prefix/));
3187a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
3197a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3207a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub GetPrefix {
3217a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  return $Prefix;
3227a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
3237a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3247a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
3257a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek#  UpdateInFilePath - Update the path in the report file.
3267a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
3277a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3287a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdateInFilePath {
3297a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $fname = shift;
3307a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $regex = shift;
3317a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $newtext = shift;
33263c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
3337a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  open (RIN, $fname) or die "cannot open $fname";
33463c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp";
33563c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
3367a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  while (<RIN>) {
3377a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    s/$regex/$newtext/;
3387a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    print ROUT $_;
3397a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  }
34063c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek
3417a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  close (ROUT);
3427a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  close (RIN);
34320161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  system("mv", "$fname.tmp", $fname);
3447a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
3457a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
3467a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
3475744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes.
3485744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------##
3495744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
35057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces
35157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports.  We use a cache to solve this problem.
35257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
35357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned;
35457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
3555744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile {
3565744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
3575744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $Index = shift;
3585744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $Dir = shift;
3595744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $FName = shift;
3605744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
36157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  # Compute a digest for the report file.  Determine if we have already
36257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  # scanned a file that looks just like it.
36357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
36457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $digest = ComputeDigest("$Dir/$FName");
36557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
366fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $AlreadyScanned{$digest}) {
36757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    # Redundant file.  Remove it.
36820161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek    system ("rm", "-f", "$Dir/$FName");
36957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    return;
37057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  }
37157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
37257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  $AlreadyScanned{$digest} = 1;
37357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
374809709f46f2516b4054681f0b76284055a84a50fTed Kremenek  # At this point the report file is not world readable.  Make it happen.
37520161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  system ("chmod", "644", "$Dir/$FName");
376684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  
377684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  # Scan the report file for tags.
37823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n");
3795744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
380a26ddabc0eb8cf8ea4de1878f84d3b920fc2349fTed Kremenek  my $BugType = "";
38122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugFile = "";
382ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  my $BugCategory;
38322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugPathLength = 1;
38422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugLine = 0;
385ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  my $found = 0;
386ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
3875744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  while (<IN>) {
388ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
389ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    last if ($found == 5);
390ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
391a26ddabc0eb8cf8ea4de1878f84d3b920fc2349fTed Kremenek    if (/<!-- BUGTYPE (.*) -->$/) {
392a26ddabc0eb8cf8ea4de1878f84d3b920fc2349fTed Kremenek      $BugType = $1;
393ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
3945744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    }
39522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGFILE (.*) -->$/) {
396990c2f45e566d8ff097fa90176ba90036892b3cdTed Kremenek      $BugFile = abs_path($1);
3977a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek      UpdatePrefix($BugFile);
398ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
39922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
40022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGPATHLENGTH (.*) -->$/) {
40122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugPathLength = $1;
402ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
40322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
40422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGLINE (.*) -->$/) {
40522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugLine = $1;    
406ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
407ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    }
408ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    elsif (/<!-- BUGCATEGORY (.*) -->$/) {
409ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $BugCategory = $1;
410ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      ++$found;
41122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
4125744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  }
4135744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
4145744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  close(IN);
415ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  
416ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  if (!defined $BugCategory) {
417ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    $BugCategory = "Other";
418ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  }
4195744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
420a26ddabc0eb8cf8ea4de1878f84d3b920fc2349fTed Kremenek  push @$Index,[ $FName, $BugCategory, $BugType, $BugFile, $BugLine,
42181983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek                 $BugPathLength ];
42222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek}
42322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
42422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------##
4253ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek# CopyFiles - Copy resource files to target directory.
42622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------##
42722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
4283ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremeneksub CopyFiles {
42922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
43022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $Dir = shift;
431e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek
432e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  my $JS = Cwd::realpath("$RealBin/sorttable.js");
43322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  
43423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("Cannot find 'sorttable.js'.\n")
435e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    if (! -r $JS);  
43622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
437e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  system ("cp", $JS, "$Dir");
43822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
43923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n")
44022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    if (! -r "$Dir/sorttable.js");
4413ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek    
442e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  my $CSS = Cwd::realpath("$RealBin/scanview.css");
443e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  
4443ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek  DieDiag("Cannot find 'scanview.css'.\n")
445e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    if (! -r $CSS);
4463ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek
447e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  system ("cp", $CSS, "$Dir");
4483ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek
4493ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek  DieDiag("Could not copy 'scanview.css' to '$Dir'.\n")
450e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    if (! -r $CSS);
4515744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek}
4525744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
4535744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------##
4549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan.
4559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
4569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
457a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess {
4589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift;
460684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  my $BaseDir = shift;
4619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
462fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  die "No directory specified." if (!defined $Dir);
4639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (! -d $Dir) {
46523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    Diag("No bugs found.\n");
466363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    return 0;
4679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
4689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  opendir(DIR, $Dir);
470938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  my @files = grep { /^report-.*\.html$/ } readdir(DIR);
4719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  closedir(DIR);
4729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
473938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  if (scalar(@files) == 0 and ! -e "$Dir/failures") {
47423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek    Diag("Removing directory '$Dir' because it contains no reports.\n");
47520161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek    system ("rm", "-fR", $Dir);
476363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    return 0;
4779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
4785744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
479991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  # Scan each report file and build an index.  
480991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  my @Index;    
4815744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); }
4825744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
483938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  # Scan the failures directory and use the information in the .info files
484d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  # to update the common prefix directory.
485938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  my @failures;
486938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  my @attributes_ignored;
487938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  if (-d "$Dir/failures") {
488938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    opendir(DIR, "$Dir/failures");
489938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    @failures = grep { /[.]info.txt$/ && !/attribute_ignored/; } readdir(DIR);
490d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek    closedir(DIR);
491938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    opendir(DIR, "$Dir/failures");        
492938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    @attributes_ignored = grep { /^attribute_ignored/; } readdir(DIR);
493938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    closedir(DIR);
494938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    foreach my $file (@failures) {
495938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      open IN, "$Dir/failures/$file" or DieDiag("cannot open $file\n");
496d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      my $Path = <IN>;
497d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      if (defined $Path) { UpdatePrefix($Path); }
498d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek      close IN;
499d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek    }    
500d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  }
501d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek  
50263c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  # Generate an index.html file.  
50363c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  my $FName = "$Dir/index.html";  
50463c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek  open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n");
5055744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
5066e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the header.
5076e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
5085744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT;
5095744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html>
5105744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head>
5117cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<title>${HtmlTitle}</title>
512f143545ce5ce125e7c1aa6fca9df372bfb604e9cTed Kremenek<link type="text/css" rel="stylesheet" href="scanview.css"/>
51322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script>
5146e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript">
5156e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal)
5166e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{
5176e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  var Rows = document.getElementsByTagName("tr");
5186e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  for ( var i = 0 ; i < Rows.length; ++i ) {
5196e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    if (Rows[i].className == RowClass) {
5206e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek      Rows[i].style.display = DisplayVal;
5216e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
5226e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
5236e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek}
524ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
5252350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenekfunction CopyCheckedStateToCheckButtons(SummaryCheckButton) {
5262350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek  var Inputs = document.getElementsByTagName("input");
5272350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek  for ( var i = 0 ; i < Inputs.length; ++i ) {
5282350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek    if (Inputs[i].type == "checkbox") {
5292350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek      if(Inputs[i] != SummaryCheckButton) {
5302350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek        Inputs[i].checked = SummaryCheckButton.checked;
5312350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek        Inputs[i].onclick();
5322350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek	  }
5332350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek    }
5342350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek  }
5352350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek}
5362350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek
537999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenekfunction returnObjById( id ) {
538999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    if (document.getElementById) 
539999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek        var returnVar = document.getElementById(id);
540999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    else if (document.all)
541999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek        var returnVar = document.all[id];
542999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    else if (document.layers) 
543999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek        var returnVar = document.layers[id];
544999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    return returnVar; 
545999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek}
546999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek
547999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenekvar NumUnchecked = 0;
548999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek
5496e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) {
5506e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  if (CheckButton.checked) {
5516e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    SetDisplay(ClassName, "");
552999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    if (--NumUnchecked == 0) {
553999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek      returnObjById("AllBugsCheck").checked = true;
554999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    }
5556e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
5566e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  else {
5576e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    SetDisplay(ClassName, "none");
558999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    NumUnchecked++;
559999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek    returnObjById("AllBugsCheck").checked = false;
5606e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
5616e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek}
5626e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script>
5631d1abb1dec3d0b7609809d876a16a64a021e96e7Ted Kremenek<!-- SUMMARYENDHEAD -->
5646e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head>
5656e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body>
5667cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<h1>${HtmlTitle}</h1>
5677cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
5687cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<table>
5697cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>User:</th><td>${UserName}\@${HostName}</td></tr>
5707cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Working Directory:</th><td>${CurrentDir}</td></tr>
5717cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Command Line:</th><td>${CmdArgs}</td></tr>
5727cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Date:</th><td>${Date}</td></tr>
5737cba11262458df05951432b54997eb40a35dbf9eTed KremenekENDTEXT
5747cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
5757cba11262458df05951432b54997eb40a35dbf9eTed Kremenekprint OUT "<tr><th>Version:</th><td>${BuildName} (${BuildDate})</td></tr>\n"
5767cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  if (defined($BuildName) && defined($BuildDate));
5777cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
5787cba11262458df05951432b54997eb40a35dbf9eTed Kremenekprint OUT <<ENDTEXT;
5797cba11262458df05951432b54997eb40a35dbf9eTed Kremenek</table>
5806e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT
5816e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
582991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  if (scalar(@files)) {
583991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    # Print out the summary table.
584991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my %Totals;
585ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
586991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    for my $row ( @Index ) {
587ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $bug_type = ($row->[2]);
588ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $bug_category = ($row->[1]);
589ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $key = "$bug_category:$bug_type";
590ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
591ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      if (!defined $Totals{$key}) { $Totals{$key} = [1,$bug_category,$bug_type]; }
592ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      else { $Totals{$key}->[0]++; }
5936e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
594991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
5957cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    print OUT "<h2>Bug Summary</h2>";
596991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
597991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    if (defined $BuildName) {
598991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n"
5996e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
600f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  
6012350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek  my $TotalBugs = scalar(@Index);
6026e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT;
603ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<table>
604ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<thead><tr><td>Bug Type</td><td>Quantity</td><td class="sorttable_nosort">Display?</td></tr></thead>
605999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed 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>
6066e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT
6076e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
608ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    my $last_category;
609ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
610ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    for my $key (
611ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      sort {
612ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        my $x = $Totals{$a};
613ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        my $y = $Totals{$b};
614ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        my $res = $x->[1] cmp $y->[1];
615ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        $res = $x->[2] cmp $y->[2] if ($res == 0);
616ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        $res
617ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      } keys %Totals ) 
618ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    {
619ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $val = $Totals{$key};
620ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $category = $val->[1];
621ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      if (!defined $last_category or $last_category ne $category) {
622ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        $last_category = $category;
623ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT "<tr><th>$category</th><th colspan=2></th></tr>\n";
624ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      }      
625ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $x = lc $key;
626ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $x =~ s/[ ,'":\/()]+/_/g;
627ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<tr><td class=\"SUMM_DESC\">";
628ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT $val->[2];
6292350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek      print OUT "</td><td class=\"Q\">";
630ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT $val->[0];
631ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td><td><center><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></center></td></tr>\n";
632991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }
6336e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
6346e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the table of errors.
6356e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
6366e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT;
6376e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table>
6387cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<h2>Reports</h2>
639ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
640ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<table class="sortable" style="table-layout:automatic">
641ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<thead><tr>
642ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <td>Bug Group</td>
643ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <td class="sorttable_sorted">Bug Type<span id="sorttable_sortfwdind">&nbsp;&#x25BE;</span></td>
644bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>File</td>
645ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <td class="Q">Line</td>
64681983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek  <td class="Q">Path Length</td>
6472645c77072d45fabb2bdc0a3621908035c7113dcTed Kremenek  <td class="sorttable_nosort"></td>
648ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek  <!-- REPORTBUGCOL -->
649ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek</tr></thead>
650ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<tbody>
6515744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT
6529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
653991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $prefix = GetPrefix();
654991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $regex;
655991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $InFileRegex;
656991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    my $InFilePrefix = "File:</td><td>";
6577a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
658991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    if (defined $prefix) { 
659991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      $regex = qr/^\Q$prefix\E/is;    
660991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is;
661991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }    
6627a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
663ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    for my $row ( sort { $a->[2] cmp $b->[2] } @Index ) {
664ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $x = "$row->[1]:$row->[2]";
665ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $x = lc $x;
666ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      $x =~ s/[ ,'":\/()]+/_/g;
6676e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    
668991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      my $ReportFile = $row->[0];
669ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          
670ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<tr class=\"bt_$x\">";
671ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<td class=\"DESC\">";
672991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT $row->[1];
673ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td>";
674ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "<td class=\"DESC\">";
675ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT $row->[2];
676ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td>";
677ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
678ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      # Update the file prefix.      
679ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my $fname = $row->[3];
680ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek
681991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      if (defined $regex) {
682991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        $fname =~ s/$regex//;
683991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix)
684991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      }
685ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
68691639ef5aa2bd94c14ae872cf747c58174ffe9b8Ted Kremenek      print OUT "<td>";      
687ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      my @fname = split /\//,$fname;
688ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      if ($#fname > 0) {
689ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        while ($#fname >= 0) {
690ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          my $x = shift @fname;
691ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          print OUT $x;
692ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          if ($#fname >= 0) {
693ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek            print OUT "<span class=\"W\"> </span>/";
694ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek          }
695ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        }
696ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      }
697ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      else {
698ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT $fname;
69991639ef5aa2bd94c14ae872cf747c58174ffe9b8Ted Kremenek      }      
700ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "</td>";
701ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
702ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      # Print out the quantities.
70381983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek      for my $j ( 4 .. 5 ) {
704ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT "<td class=\"Q\">$row->[$j]</td>";        
705ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      }
706ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      
707991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      # Print the rest of the columns.
70881983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek      for (my $j = 6; $j <= $#{$row}; ++$j) {
709ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek        print OUT "<td>$row->[$j]</td>"
710991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      }
7117f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
712991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      # Emit the "View" link.
71368005ddb49b88c2f6cdd88185d72d8b411d2dbc9Ted Kremenek      print OUT "<td><a href=\"$ReportFile#EndPath\">View Report</a></td>";
7143cea9ee6b77ac797ebb910bdf45d1d7f8f68e37bTed Kremenek        
715e43038ec3d0ef187fcdddf101ef653bbbdb1069aDaniel Dunbar      # Emit REPORTBUG markers.
716ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek      print OUT "\n<!-- REPORTBUG id=\"$ReportFile\" -->\n";
717e43038ec3d0ef187fcdddf101ef653bbbdb1069aDaniel Dunbar        
718991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      # End the row.
719991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      print OUT "</tr>\n";
720991c54b9b7409656e5593364e065878b5210d556Ted Kremenek    }
721991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  
722ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek    print OUT "</tbody>\n</table>\n\n";
723991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  }
724991c54b9b7409656e5593364e065878b5210d556Ted Kremenek
725938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  if (scalar (@failures) || scalar(@attributes_ignored)) {
726938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    print OUT "<h2>Analyzer Failures</h2>\n";
727938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    
728938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    if (scalar @attributes_ignored) {
729938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      print OUT "The analyzer's parser ignored the following attributes:<p>\n";
730938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      print OUT "<table>\n";
731938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      print OUT "<thead><tr><td>Attribute</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>\n";
732938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      foreach my $file (sort @attributes_ignored) {
733938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        die "cannot demangle attribute name\n" if (! ($file =~ /^attribute_ignored_(.+).txt/));
734938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        my $attribute = $1;
735938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        # Open the attribute file to get the first file that failed.
736938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        next if (!open (ATTR, "$Dir/failures/$file"));
737938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        my $ppfile = <ATTR>;
738938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        chomp $ppfile;
739938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        close ATTR;
740938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        next if (! -e "$Dir/failures/$ppfile");
741938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        # Open the info file and get the name of the source file.
742938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        open (INFO, "$Dir/failures/$ppfile.info.txt") or
743938eef139ad43345248235da31f78a759dd18f13Ted Kremenek          die "Cannot open $Dir/failures/$ppfile.info.txt\n";
744938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        my $srcfile = <INFO>;
745938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        chomp $srcfile;
746938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        close (INFO);
747938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        # Print the information in the table.
748938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        my $prefix = GetPrefix();
749938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; }
750938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        print OUT "<tr><td>$attribute</td><td>$srcfile</td><td><a href=\"failures/$ppfile\">$ppfile</a></td><td><a href=\"failures/$ppfile.stderr.txt\">$ppfile.stderr.txt</a></td></tr>\n";
751938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        my $ppfile_clang = $ppfile;
752938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        $ppfile_clang =~ s/[.](.+)$/.clang.$1/;
753938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        print OUT "  <!-- REPORTPROBLEM src=\"$srcfile\" file=\"failures/$ppfile\" clangfile=\"failures/$ppfile_clang\" stderr=\"failures/$ppfile.stderr.txt\" info=\"failures/$ppfile.info.txt\" -->\n";
754938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      }
755938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      print OUT "</table>\n";
756938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    }
757938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    
758938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    if (scalar @failures) {
759938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      print OUT "<p>The analyzer had problems processing the following files:</p>\n";
760938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      print OUT "<table>\n";
761938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      print OUT "<thead><tr><td>Problem</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>\n";
762938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      foreach my $file (sort @failures) {
76382a1253077cd0832e4d347062b911cd305ab62d1Ted Kremenek        $file =~ /(.+).info.txt$/;
764991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        # Get the preprocessed file.
765991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        my $ppfile = $1;
766991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        # Open the info file and get the name of the source file.
767938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        open (INFO, "$Dir/failures/$file") or
768938eef139ad43345248235da31f78a759dd18f13Ted Kremenek          die "Cannot open $Dir/failures/$file\n";
769991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        my $srcfile = <INFO>;
7705d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek        chomp $srcfile;
7715d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek        my $problem = <INFO>;
7725d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek        chomp $problem;
773991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        close (INFO);
774991c54b9b7409656e5593364e065878b5210d556Ted Kremenek        # Print the information in the table.
775d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek        my $prefix = GetPrefix();
7769f9b1fded49acff77e61b3ed1afc8bbaaefe6f34Ted Kremenek        if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; }
777938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        print OUT "<tr><td>$problem</td><td>$srcfile</td><td><a href=\"failures/$ppfile\">$ppfile</a></td><td><a href=\"failures/$ppfile.stderr.txt\">$ppfile.stderr.txt</a></td></tr>\n";
778ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar        my $ppfile_clang = $ppfile;
779ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar        $ppfile_clang =~ s/[.](.+)$/.clang.$1/;
780938eef139ad43345248235da31f78a759dd18f13Ted Kremenek        print OUT "  <!-- REPORTPROBLEM src=\"$srcfile\" file=\"failures/$ppfile\" clangfile=\"failures/$ppfile_clang\" stderr=\"failures/$ppfile.stderr.txt\" info=\"failures/$ppfile.info.txt\" -->\n";
781991c54b9b7409656e5593364e065878b5210d556Ted Kremenek      }
782938eef139ad43345248235da31f78a759dd18f13Ted Kremenek      print OUT "</table>\n";
783938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    }    
784938eef139ad43345248235da31f78a759dd18f13Ted Kremenek    print OUT "<p>Please consider submitting preprocessed files as <a href=\"http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\">bug reports</a>. <!-- REPORTCRASHES --> </p>\n";
7855744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  }
7865744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
787991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  print OUT "</body></html>\n";  
7885744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  close(OUT);
7893ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek  CopyFiles($Dir);
79020161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek
79120161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  # Make sure $Dir and $BaseDir are world readable/executable.
79220161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek  system("chmod", "755", $Dir);
793fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $BaseDir) { system("chmod", "755", $BaseDir); }
79420161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek
79523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  my $Num = scalar(@Index);
796150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek  Diag("$Num bugs found.\n");
797150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek  if ($Num > 0 && -r "$Dir/index.html") {
7985950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek    Diag("Run 'scan-view $Dir' to examine bug reports.\n");
799150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek  }
800363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  
801938eef139ad43345248235da31f78a759dd18f13Ted Kremenek  DiagCrashes($Dir) if (scalar @failures || scalar @attributes_ignored);
802991c54b9b7409656e5593364e065878b5210d556Ted Kremenek  
803363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  return $Num;
8049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
8059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
8069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
807dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command.
808dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------##
809dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek
8106b6289848e215ff12d4d54fe0602d3371db52788Ted Kremeneksub AddIfNotPresent {
8116b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $Args = shift;
8126b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $Arg = shift;  
8136b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $found = 0;
8146b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
8156b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  foreach my $k (@$Args) {
8166b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    if ($k eq $Arg) {
8176b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      $found = 1;
8186b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      last;
8196b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    }
8206b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
8216b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
8226b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  if ($found == 0) {
8236b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    push @$Args, $Arg;
8246b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
8256b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek}
8266b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek
827dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremeneksub RunBuildCommand {
828dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
829dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  my $Args = shift;
8307442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek  my $IgnoreErrors = shift;
831dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  my $Cmd = $Args->[0];
8326195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek  my $CCAnalyzer = shift;
833dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
8343301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  # Get only the part of the command after the last '/'.
8353301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  if ($Cmd =~ /\/([^\/]+)$/) {
8363301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek    $Cmd = $1;
8373301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  }
8383301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek  
83992548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek  if ($Cmd =~ /(.*\/?gcc[^\/]*$)/ or 
84092548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek      $Cmd =~ /(.*\/?cc[^\/]*$)/ or
84192548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek      $Cmd =~ /(.*\/?llvm-gcc[^\/]*$)/ or
84292548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek      $Cmd =~ /(.*\/?ccc-analyzer[^\/]*$)/) {
84392548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek
84492548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek    if (!($Cmd =~ /ccc-analyzer/) and !defined $ENV{"CCC_CC"}) {
84592548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek      $ENV{"CCC_CC"} = $1;
84692548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek    }
84792548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek        
848dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek    shift @$Args;
8496195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek    unshift @$Args, $CCAnalyzer;
850dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  }
8517442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek  elsif ($IgnoreErrors) {
8527442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    if ($Cmd eq "make" or $Cmd eq "gmake") {
8536b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      AddIfNotPresent($Args,"-k");
8548912b5427a22d9032cad959c5c22cd9d28d4a66cTed Kremenek      AddIfNotPresent($Args,"-i");
8557442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    }
8567442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    elsif ($Cmd eq "xcodebuild") {
8576b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES");
8587442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    }
8596b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  } 
8606b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
8616b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  if ($Cmd eq "xcodebuild") {
862cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    # Disable distributed builds for xcodebuild.
8636b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    AddIfNotPresent($Args,"-nodistribute");
864cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek
865cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    # Disable PCH files until clang supports them.
866cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO");
867915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    
868915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # When 'CC' is set, xcodebuild uses it to do all linking, even if we are
869915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # linking C++ object files.  Set 'LDPLUSPLUS' so that xcodebuild uses 'g++'
870915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # when linking such files.
87195aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek    die if (!defined $CXX);
87295aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek    my $LDPLUSPLUS = `which $CXX`;
873915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    $LDPLUSPLUS =~ s/\015?\012//;  # strip newlines
874915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS;    
8756b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
876dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
8775a4ddaf39a26f9c7e30d3aeca17c702213a29d9fTed Kremenek  return (system(@$Args) >> 8);
878dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek}
879dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek
880dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------##
8819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options.
8829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
8839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
884a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp {
8859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
8865744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT;
887a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options]
8882b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
889f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted KremenekENDTEXT
890f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek
891fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $BuildName) {
892f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek    print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n";
893f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  }
894f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek
895f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekprint <<ENDTEXT;
8962b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS:
8972b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
898e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek -analyze-headers - Also analyze functions in #included files.
899e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek
900363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -o             - Target directory for HTML report files.  Subdirectories
901a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop                  will be created as needed to represent separate "runs" of
9022b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek                  the analyzer.  If this option is not specified, a directory
903ffda0b44eb02ddf2f168df8e14ae98de790f2b05Ted Kremenek                  is created in /tmp (TMPDIR on Mac OS X) to store the reports.
904db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek                  
905363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -h             - Display this message.
906363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --help
9071262fc4d66584224234691d30d779f8ff004585cTed Kremenek
908363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -k             - Add a "keep on going" option to the specified build command.
909363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --keep-going     This option currently supports make and xcodebuild.
910f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek                  This is a convenience option; one can specify this
911f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek                  behavior directly using build options.
9122b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
9137cba11262458df05951432b54997eb40a35dbf9eTed Kremenek --html-title [title]       - Specify the title used on generated HTML pages.
9147cba11262458df05951432b54997eb40a35dbf9eTed Kremenek --html-title=[title]         If not specified, a default title will be used.
9157cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
916db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek -plist         - By default the output of scan-build is a set of HTML files.
917db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek                  This option outputs the results as a set of .plist files.
918db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek
919363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --status-bugs  - By default, the exit status of $Prog is the same as the
920363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek                  executed build command.  Specifying this option causes the
921363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek                  exit status of $Prog to be 1 if it found potential bugs
922363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek                  and 0 otherwise.
9232b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
924386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-cc [compiler path]   - By default, $Prog uses 'gcc' to compile and link
925386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-cc=[compiler path]     your C and Objective-C code. Use this option
926386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek                              to specify an alternate compiler.
927386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek
928386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-c++ [compiler path]  - By default, $Prog uses 'g++' to compile and link
929386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek --use-c++=[compiler path]    your C++ and Objective-C++ code. Use this option
930386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek                              to specify an alternate compiler.
931f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek
932363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -v             - Verbose output from $Prog and the analyzer.
933386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek                  A second and third '-v' increases verbosity.
934363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek
935363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek -V             - View analysis results in a web browser when the build
936363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --view           completes.
9377f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
938be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed KremenekADVANCED OPTIONS:
939be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek
9409f4ecb34d502f6aad7d635dd3aec24a373ef5c9bTed Kremenek -constraints [model] - Specify the contraint engine used by the analyzer.
9419f4ecb34d502f6aad7d635dd3aec24a373ef5c9bTed Kremenek                        By default the 'range' model is used.  Specifying 
9429f4ecb34d502f6aad7d635dd3aec24a373ef5c9bTed Kremenek                        'basic' uses a simpler, less powerful constraint model
943d4c7684f19703d75b989364da80727d635f99b53Ted Kremenek                        used by checker-0.160 and earlier.
944be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek
945be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek -store [model] - Specify the store model used by the analyzer. By default,
946be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek                  the 'basic' store model is used. 'region' specifies a field-
947be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek                  sensitive store model. Be warned that the 'region' model
948be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek                  is still in very early testing phase and may often crash.
949b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
950386c69316668b9ea8c2591af56f994be16e3ff62Ted KremenekAVAILABLE ANALYSES (multiple analyses may be specified):
951d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek
952d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed KremenekENDTEXT
953b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
954b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  foreach my $Analysis (sort keys %AvailableAnalyses) {
955fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek    if (defined $AnalysesDefaultEnabled{$Analysis}) {
956363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek      print " (+)";
957b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    }
958b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    else {
959363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek      print "    ";
960b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    }
961b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    
962b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    print " $Analysis  $AvailableAnalyses{$Analysis}\n";
963b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  }
964b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek  
965b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekprint <<ENDTEXT
966b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
967363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek NOTE: "(+)" indicates that an analysis is enabled by default unless one
968363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek       or more analysis options are specified
969b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek
9702b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS
9712b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
972363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek You can specify any build option acceptable to the build command.
97339eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek
9745744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE
9752b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
976363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek $Prog -o /tmp/myhtmldir make -j4
9772b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek     
978363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek The above example causes analysis reports to be deposited into
979363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option.
980363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek A different subdirectory is created each time $Prog analyzes a project.
981363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek The analyzer should support most parallel builds, but not distributed builds.
9822b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
9832b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT
9849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
9859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
9869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
9877cba11262458df05951432b54997eb40a35dbf9eTed Kremenek# HtmlEscape - HTML entity encode characters that are special in HTML
9887cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
9897cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
9907cba11262458df05951432b54997eb40a35dbf9eTed Kremeneksub HtmlEscape {
9917cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  # copy argument to new variable so we don't clobber the original
9927cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  my $arg = shift || '';
9937cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  my $tmp = $arg;
99487f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek  $tmp =~ s/&/&amp;/g;
99587f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek  $tmp =~ s/</&lt;/g;
99687f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek  $tmp =~ s/>/&gt;/g;
9977cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  return $tmp;
9987cba11262458df05951432b54997eb40a35dbf9eTed Kremenek}
9997cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10007cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
10017cba11262458df05951432b54997eb40a35dbf9eTed Kremenek# ShellEscape - backslash escape characters that are special to the shell
10027cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
10037cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10047cba11262458df05951432b54997eb40a35dbf9eTed Kremeneksub ShellEscape {
10057cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  # copy argument to new variable so we don't clobber the original
10067cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  my $arg = shift || '';
100787f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek  if ($arg =~ /["\s]/) { return "'" . $arg . "'"; }
100887f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek  return $arg;
10097cba11262458df05951432b54997eb40a35dbf9eTed Kremenek}
10107cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10117cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------##
10129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments.
10139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
10149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
1015e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenekmy $AnalyzeHeaders = 0;
10169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir;           # Parent directory to store HTML files.
10179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0;  # Ignore build errors.
10187f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults  = 0;  # View results when the build terminates.
1019363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekmy $ExitStatusFoundBugs = 0; # Exit status reflects whether bugs were found
1020b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy @AnalysesToRun;
102107c3767be59472e19183c7b51fae76481465cb51Zhongxing Xumy $StoreModel;
1022be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenekmy $ConstraintsModel;
1023db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenekmy $OutputFormat;
10249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) {
10269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  DisplayHelp();
1027a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  exit 1;
10289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
10299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) {
10319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
10329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Scan for options we recognize.
10339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
10349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $arg = $ARGV[0];
10359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
10362f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop  if ($arg eq "-h" or $arg eq "--help") {
10379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    DisplayHelp();
1038a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop    exit 0;
10399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
10409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1041e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  if ($arg eq '-analyze-headers') {
1042e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    shift @ARGV;    
1043e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    $AnalyzeHeaders = 1;
1044e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek    next;
1045e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  }
1046e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  
1047fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek  if (defined $AvailableAnalyses{$arg}) {
10481262fc4d66584224234691d30d779f8ff004585cTed Kremenek    shift @ARGV;
1049b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek    push @AnalysesToRun, $arg;
10501262fc4d66584224234691d30d779f8ff004585cTed Kremenek    next;
10511262fc4d66584224234691d30d779f8ff004585cTed Kremenek  }
10521262fc4d66584224234691d30d779f8ff004585cTed Kremenek  
10539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($arg eq "-o") {
10549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
10559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek        
10569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (!@ARGV) {
105723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek      DieDiag("'-o' option requires a target directory name.\n");
10589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
10599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
1060db51a55c4922b055a90a370ce9906455887a8564Ted Kremenek    # Construct an absolute path.  Uses the current working directory
1061db51a55c4922b055a90a370ce9906455887a8564Ted Kremenek    # as a base if the original path was not absolute.
1062db51a55c4922b055a90a370ce9906455887a8564Ted Kremenek    $HtmlDir = abs_path(shift @ARGV);
1063db51a55c4922b055a90a370ce9906455887a8564Ted Kremenek    
10649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
10659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
10667cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10677cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  if ($arg =~ /^--html-title(=(.+))?$/) {
10687cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    shift @ARGV;
10697cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10707cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    if ($2 eq '') {
10717cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      if (!@ARGV) {
10727cba11262458df05951432b54997eb40a35dbf9eTed Kremenek        DieDiag("'--html-title' option requires a string.\n");
10737cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      }
10747cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10757cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      $HtmlTitle = shift @ARGV;
10767cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    } else {
10777cba11262458df05951432b54997eb40a35dbf9eTed Kremenek      $HtmlTitle = $2;
10787cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    }
10797cba11262458df05951432b54997eb40a35dbf9eTed Kremenek
10807cba11262458df05951432b54997eb40a35dbf9eTed Kremenek    next;
10817cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  }
10829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
10832b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek  if ($arg eq "-k" or $arg eq "--keep-going") {
10849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
10859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $IgnoreErrors = 1;
10869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
10879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
10889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1089f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek  if ($arg =~ /^--use-cc(=(.+))?$/) {
1090f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    shift @ARGV;
1091f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    my $cc;
1092f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    
1093f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    if ($2 eq "") {
1094f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      if (!@ARGV) {
1095f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek        DieDiag("'--use-cc' option requires a compiler executable name.\n");
1096f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      }
1097f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      $cc = shift @ARGV;
1098f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    }
1099f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    else {
1100f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek      $cc = $2;
1101f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    }
1102f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    
1103f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    $ENV{"CCC_CC"} = $cc;
1104f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek    next;
1105f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek  }
1106f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek  
11077cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  if ($arg =~ /^--use-c\+\+(=(.+))?$/) {
1108386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    shift @ARGV;
1109386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    
1110386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    if ($2 eq "") {
1111386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      if (!@ARGV) {
1112386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek        DieDiag("'--use-c++' option requires a compiler executable name.\n");
1113386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      }
1114386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      $CXX = shift @ARGV;
1115386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    }
1116386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    else {
1117386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek      $CXX = $2;
1118386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    }
1119386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek    next;
1120386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek  }
1121386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek  
11229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($arg eq "-v") {
11239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
11249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $Verbose++;
11259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
11269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
11279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
11287f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  if ($arg eq "-V" or $arg eq "--view") {
11297f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    shift @ARGV;
11307f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    $ViewResults = 1;    
11317f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    next;
11327f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  }
11337f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  
1134363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  if ($arg eq "--status-bugs") {
1135363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    shift @ARGV;
1136363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    $ExitStatusFoundBugs = 1;
1137363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek    next;
1138363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  }
113907c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu
114007c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu  if ($arg eq "-store") {
114107c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu    shift @ARGV;
1142be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek    $StoreModel = shift @ARGV;
1143be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek    next;
1144be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek  }
1145be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek  
1146be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek  if ($arg eq "-constraints") {
1147be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek    shift @ARGV;
1148be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek    $ConstraintsModel = shift @ARGV;
114907c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu    next;
115007c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu  }
1151363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek  
1152db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  if ($arg eq "-plist") {
1153db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek    shift @ARGV;
1154db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek    $OutputFormat = "plist";
1155db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek    next;
1156db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  }
1157db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  
115823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/);
11590062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek  
11609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  last;
11619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
11629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
11639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) {
116423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek  Diag("No build command specified.\n\n");
11659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  DisplayHelp();
1166a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  exit 1;
11679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
11689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
11697cba11262458df05951432b54997eb40a35dbf9eTed Kremenek$CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV)));
11707cba11262458df05951432b54997eb40a35dbf9eTed Kremenek$HtmlTitle = "${CurrentDirSuffix} - scan-build results"
11717cba11262458df05951432b54997eb40a35dbf9eTed Kremenek  unless (defined($HtmlTitle));
1172386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek
11739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports.
1174684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir;
1175a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir);
11769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
11779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Set the appropriate environment variables.
1178a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopSetHtmlEnv(\@ARGV, $HtmlDir);
11799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
118091ea79dd3fdf0c3275cf2159c6a01c83e55bcdd3Ted Kremenekmy $Cmd = Cwd::realpath("$RealBin/libexec/ccc-analyzer");
1181ce87b929703cac0b3f236b0b0d1c7b78d8af38f2Ted Kremenekif (!defined $Cmd || ! -x $Cmd) {
1182ce87b929703cac0b3f236b0b0d1c7b78d8af38f2Ted Kremenek  $Cmd = Cwd::realpath("$RealBin/ccc-analyzer");
11836b89636db873142f562cf576df9bc195c5b8674bTed Kremenek  DieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n") if(! -x $Cmd);
1184ce87b929703cac0b3f236b0b0d1c7b78d8af38f2Ted Kremenek}
1185f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek
1186fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenekif (!defined $ClangCCSB || ! -x $ClangCCSB) {
118791ea79dd3fdf0c3275cf2159c6a01c83e55bcdd3Ted Kremenek  Diag("'clang-cc' executable not found in '$RealBin/libexec'.\n");
1188318e6a65ff6105b0121b49dfc9d47363843a1185Ted Kremenek  Diag("Using 'clang-cc' from path.\n");
1189f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek}
1190fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenekif (!defined $ClangSB || ! -x $ClangSB) {
1191fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek  Diag("'clang' executable not found in '$RealBin/bin'.\n");
1192fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek  Diag("Using 'clang' from path.\n");
1193fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek}
11940b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek
119595aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenekif (defined $CXX) {
119695aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek  $ENV{'CXX'} = $CXX;
119795aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek}
119895aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenekelse {
119995aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek  $CXX = 'g++';  # This variable is used by other parts of scan-build
120095aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek                 # that need to know a default C++ compiler to fall back to.
120195aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek}
120295aa1050cd170f9729ca66a1b2e2f0219458671eTed Kremenek  
12034f4b17da43d3be87a248e1e10bf0b7d8b5891efdTed Kremenek$ENV{'CC'} = $Cmd;
1204fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek$ENV{'CLANG_CC'} = $ClangCC;
1205f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek$ENV{'CLANG'} = $Clang;
12069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
12079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif ($Verbose >= 2) {
12089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  $ENV{'CCC_ANALYZER_VERBOSE'} = 1;
12099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
12109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
1211a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenekif ($Verbose >= 3) {
1212a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek  $ENV{'CCC_ANALYZER_LOG'} = 1;
1213a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek}
1214a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek
12159012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenekif (scalar(@AnalysesToRun) == 0) {
12169012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek  foreach my $key (keys %AnalysesDefaultEnabled) {
12179012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek    push @AnalysesToRun,$key;
12189012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek  }
121901006786e3760cc48c5e94d731b468b811b976d2Ted Kremenek}
12201262fc4d66584224234691d30d779f8ff004585cTed Kremenek
1221e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenekif ($AnalyzeHeaders) {
1222e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek  push @AnalysesToRun,"-analyzer-opt-analyze-headers";  
1223e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek}
1224e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek
12259012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek$ENV{'CCC_ANALYZER_ANALYSIS'} = join ' ',@AnalysesToRun;
12269012599f4ccfe066c093cf0885fd3994bdc256d1Ted Kremenek
12273cab2b1c3798f2a6aa3526875801a02aebf6fc1dZhongxing Xuif (defined $StoreModel) {
122807c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu  $ENV{'CCC_ANALYZER_STORE_MODEL'} = $StoreModel;
122907c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu}
123007c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu
1231be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenekif (defined $ConstraintsModel) {
1232be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek  $ENV{'CCC_ANALYZER_CONSTRAINTS_MODEL'} = $ConstraintsModel;
1233be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek}
1234be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek
1235db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenekif (defined $OutputFormat) {
1236db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  $ENV{'CCC_ANALYZER_OUTPUT_FORMAT'} = $OutputFormat;
1237db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek}
1238db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek
1239db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek
12409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build.
12415656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekmy $ExitStatus = RunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd);
12429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
1243655aba727e2a5f7f4e4952d35d35faa6ad4ec6e5Ted Kremenekif (defined $OutputFormat and $OutputFormat eq "plist") {
124450534dc3ab0737224f9ce739821e1486219c686bTed Kremenek  Diag "Analysis run complete.\n";
1245db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  Diag "Analysis results (plist files) deposited in '$HtmlDir'\n";
12467f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek}
1247db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenekelse {
1248db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  # Postprocess the HTML directory.
1249db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  my $NumBugs = Postprocess($HtmlDir, $BaseDir);
1250db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek
1251db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  if ($ViewResults and -r "$HtmlDir/index.html") {
1252db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek    Diag "Analysis run complete.\n";
1253db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek    Diag "Viewing analysis results in '$HtmlDir' using scan-view.\n";
1254db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek    my $ScanView = Cwd::realpath("$RealBin/scan-view");
1255db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek    if (! -x $ScanView) { $ScanView = "scan-view"; }
1256db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek    exec $ScanView, "$HtmlDir";
1257db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  }
12585656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek
1259db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  if ($ExitStatusFoundBugs) {
1260db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek    exit 1 if ($NumBugs > 0);
1261db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek    exit 0;
1262db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek  }
1263363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek}
1264363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek
12655656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekexit $ExitStatus;
12665656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek
1267