1e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh#!/usr/bin/env perl
2e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh#
3e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh#                     The LLVM Compiler Infrastructure
4e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh#
5e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# This file is distributed under the University of Illinois Open Source
6e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# License. See LICENSE.TXT for details.
7e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh#
8e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##===----------------------------------------------------------------------===##
9e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh#
10e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# A script designed to wrap a build so that all calls to gcc are intercepted
11e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# and piped to the static analyzer.
12e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh#
13e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##===----------------------------------------------------------------------===##
14e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
15e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehuse strict;
16e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehuse warnings;
17e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehuse FindBin qw($RealBin);
18e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehuse Digest::MD5;
19e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehuse File::Basename;
20e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehuse File::Find;
21e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehuse Term::ANSIColor;
22e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehuse Term::ANSIColor qw(:constants);
23e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehuse Cwd qw/ getcwd abs_path /;
24e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehuse Sys::Hostname;
25e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
26e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $Verbose = 0;       # Verbose output from this script.
27e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $Prog = "scan-build";
28e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $BuildName;
29e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $BuildDate;
30e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $Top;
31e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
32e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $TERM = $ENV{'TERM'};
33e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $UseColor = (defined $TERM and $TERM =~ 'xterm-.*color' and -t STDOUT
34e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh                and defined $ENV{'SCAN_BUILD_COLOR'});
35e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
36e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Portability: getpwuid is not implemented for Win32 (see Perl language 
37e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# reference, perlport), use getlogin instead.
38e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $UserName = HtmlEscape(getlogin() || getpwuid($<) || 'unknown');
39e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $HostName = HtmlEscape(hostname() || 'unknown');
40e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $CurrentDir = HtmlEscape(getcwd());
41e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $CurrentDirSuffix = basename($CurrentDir);
42e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
43e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy @PluginsToLoad;
44e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $CmdArgs;
45e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
46e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $HtmlTitle;
47e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
48e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $Date = localtime();
49e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
50e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
51e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Diagnostics
52e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
53e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
54e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub Diag {
55e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($UseColor) {
56e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print BOLD, MAGENTA "$Prog: @_";
57e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print RESET;
58e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
59e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  else {
60e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print "$Prog: @_";
61e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }  
62e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
63e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
64e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub ErrorDiag {
65e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($UseColor) {
66e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print STDERR BOLD, RED "$Prog: ";
67e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print STDERR RESET, RED @_;
68e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print STDERR RESET;
69e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  } else {
70e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print STDERR "$Prog: @_";
71e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }  
72e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
73e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
74e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub DiagCrashes {
75e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Dir = shift;
76e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  Diag ("The analyzer encountered problems on some source files.\n");
77e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  Diag ("Preprocessed versions of these sources were deposited in '$Dir/failures'.\n");
78e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  Diag ("Please consider submitting a bug report using these files:\n");
79e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  Diag ("  http://clang-analyzer.llvm.org/filing_bugs.html\n")
80e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
81e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
82e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub DieDiag {
83e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($UseColor) {
84e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print STDERR BOLD, RED "$Prog: ";
85e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print STDERR RESET, RED @_;
86e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print STDERR RESET;
87e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
88e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  else {
89e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print STDERR "$Prog: ", @_;
90e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
91e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  exit 1;
92e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
93e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
94e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
95e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Print default checker names
96e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
97e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
98e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (grep /^--help-checkers$/, @ARGV) {
99e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my @options = qx($0 -h);
100e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    foreach (@options) {
101e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	next unless /^ \+/;
102e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	s/^\s*//;
103e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	my ($sign, $name, @text) = split ' ', $_;
104e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	print $name, $/ if $sign eq '+';
105e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
106e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    exit 0;
107e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
108e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
109e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
110e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Declaration of Clang options.  Populated later.
111e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
112e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
113e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $Clang;
114e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $ClangSB;
115e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $ClangCXX;
116e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $ClangVersion;
117e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
118e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
119e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# GetHTMLRunDir - Construct an HTML directory name for the current sub-run.
120e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
121e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
122e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub GetHTMLRunDir {  
123e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  die "Not enough arguments." if (@_ == 0);  
124e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Dir = shift @_;    
125e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $TmpMode = 0;
126e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (!defined $Dir) {
127e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $Dir = $ENV{'TMPDIR'} || $ENV{'TEMP'} || $ENV{'TMP'} || "/tmp";
128e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $TmpMode = 1;
129e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
130e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
131e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Chop off any trailing '/' characters.
132e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  while ($Dir =~ /\/$/) { chop $Dir; }
133e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
134e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Get current date and time.
135e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my @CurrentTime = localtime();  
136e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $year  = $CurrentTime[5] + 1900;
137e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $day   = $CurrentTime[3];
138e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $month = $CurrentTime[4] + 1;
139e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day);
140e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
141e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Determine the run number.  
142e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $RunNumber;
143e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
144e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (-d $Dir) {    
145e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (! -r $Dir) {
146e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      DieDiag("directory '$Dir' exists but is not readable.\n");
147e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }    
148e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    # Iterate over all files in the specified directory.    
149e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $max = 0;    
150e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    opendir(DIR, $Dir);
151e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my @FILES = grep { -d "$Dir/$_" } readdir(DIR);
152e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    closedir(DIR);
153e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
154e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    foreach my $f (@FILES) {
155e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      # Strip the prefix '$Prog-' if we are dumping files to /tmp.
156e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if ($TmpMode) {
157e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        next if (!($f =~ /^$Prog-(.+)/));
158e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $f = $1;
159e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
160e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
161e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my @x = split/-/, $f;
162e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      next if (scalar(@x) != 4);
163e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      next if ($x[0] != $year);
164e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      next if ($x[1] != $month);
165e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      next if ($x[2] != $day);
166e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      
167e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if ($x[3] > $max) {
168e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $max = $x[3];
169e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }      
170e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
171e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
172e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $RunNumber = $max + 1;
173e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
174e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  else {
175e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
176e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (-x $Dir) {
177e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      DieDiag("'$Dir' exists but is not a directory.\n");
178e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
179e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
180e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if ($TmpMode) {
181e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      DieDiag("The directory '/tmp' does not exist or cannot be accessed.\n");
182e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
183e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
184e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    # $Dir does not exist.  It will be automatically created by the 
185e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    # clang driver.  Set the run number to 1.  
186e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
187e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $RunNumber = 1;
188e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
189e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
190e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  die "RunNumber must be defined!" if (!defined $RunNumber);
191e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
192e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Append the run number.
193e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $NewDir;
194e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($TmpMode) {
195e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $NewDir = "$Dir/$Prog-$DateString-$RunNumber";
196e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
197e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  else {
198e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $NewDir = "$Dir/$DateString-$RunNumber";
199e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
200e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  system 'mkdir','-p',$NewDir;
201e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  return $NewDir;
202e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
203e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
204e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub SetHtmlEnv {
205e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
206e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  die "Wrong number of arguments." if (scalar(@_) != 2);
207e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
208e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Args = shift;
209e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Dir = shift;
210e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
211e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  die "No build command." if (scalar(@$Args) == 0);
212e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
213e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Cmd = $$Args[0];
214e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
215e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($Cmd =~ /configure/ || $Cmd =~ /autogen/) {
216e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    return;
217e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
218e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
219e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($Verbose) {
220e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Diag("Emitting reports for this run to '$Dir'.\n");
221e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
222e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
223e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $ENV{'CCC_ANALYZER_HTML'} = $Dir;
224e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
225e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
226e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
227e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# ComputeDigest - Compute a digest of the specified file.
228e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
229e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
230e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub ComputeDigest {
231e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $FName = shift;
232e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName);  
233e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
234e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Use Digest::MD5.  We don't have to be cryptographically secure.  We're
235e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # just looking for duplicate files that come from a non-malicious source.
236e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # We use Digest::MD5 because it is a standard Perl module that should
237e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # come bundled on most systems.  
238e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n");
239e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  binmode FILE;
240e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest;
241e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  close(FILE);
242e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
243e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Return the digest.  
244e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  return $Result;
245e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
246e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
247e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
248e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh#  UpdatePrefix - Compute the common prefix of files.
249e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
250e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
251e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $Prefix;
252e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
253e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub UpdatePrefix {
254e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $x = shift;
255e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $y = basename($x);
256e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $x =~ s/\Q$y\E$//;
257e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
258e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (!defined $Prefix) {
259e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $Prefix = $x;
260e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    return;
261e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
262e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
263e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  chop $Prefix while (!($x =~ /^\Q$Prefix/));
264e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
265e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
266e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub GetPrefix {
267e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  return $Prefix;
268e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
269e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
270e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
271e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh#  UpdateInFilePath - Update the path in the report file.
272e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
273e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
274e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub UpdateInFilePath {
275e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $fname = shift;
276e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $regex = shift;
277e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $newtext = shift;
278e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
279e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  open (RIN, $fname) or die "cannot open $fname";
280e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp";
281e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
282e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  while (<RIN>) {
283e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    s/$regex/$newtext/;
284e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print ROUT $_;
285e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
286e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
287e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  close (ROUT);
288e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  close (RIN);
289e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  system("mv", "$fname.tmp", $fname);
290e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
291e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
292e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
293e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# AddStatLine - Decode and insert a statistics line into the database.
294e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
295e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
296e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub AddStatLine {
297e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Line  = shift;
298e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Stats = shift;
299e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $File  = shift;
300e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
301e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  print $Line . "\n";
302e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
303e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Regex = qr/(.*?)\ ->\ Total\ CFGBlocks:\ (\d+)\ \|\ Unreachable
304e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      \ CFGBlocks:\ (\d+)\ \|\ Exhausted\ Block:\ (yes|no)\ \|\ Empty\ WorkList:
305e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      \ (yes|no)/x;
306e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
307e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($Line !~ $Regex) {
308e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    return;
309e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
310e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
311e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Create a hash of the interesting fields
312e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Row = {
313e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Filename    => $File,
314e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Function    => $1,
315e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Total       => $2,
316e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Unreachable => $3,
317e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Aborted     => $4,
318e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Empty       => $5
319e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  };
320e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
321e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Add them to the stats array
322e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  push @$Stats, $Row;
323e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
324e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
325e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
326e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# ScanFile - Scan a report file for various identifying attributes.
327e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
328e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
329e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Sometimes a source file is scanned more than once, and thus produces
330e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# multiple error reports.  We use a cache to solve this problem.
331e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
332e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy %AlreadyScanned;
333e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
334e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub ScanFile {
335e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
336e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Index = shift;
337e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Dir = shift;
338e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $FName = shift;
339e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Stats = shift;
340e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
341e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Compute a digest for the report file.  Determine if we have already
342e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # scanned a file that looks just like it.
343e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
344e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $digest = ComputeDigest("$Dir/$FName");
345e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
346e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (defined $AlreadyScanned{$digest}) {
347e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    # Redundant file.  Remove it.
348e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    system ("rm", "-f", "$Dir/$FName");
349e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    return;
350e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
351e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
352e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $AlreadyScanned{$digest} = 1;
353e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
354e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # At this point the report file is not world readable.  Make it happen.
355e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  system ("chmod", "644", "$Dir/$FName");
356e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
357e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Scan the report file for tags.
358e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n");
359e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
360e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $BugType        = "";
361e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $BugFile        = "";
362e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $BugCategory    = "";
363e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $BugDescription = "";
364e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $BugPathLength  = 1;
365e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $BugLine        = 0;
366e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
367e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  while (<IN>) {
368e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    last if (/<!-- BUGMETAEND -->/);
369e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
370e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (/<!-- BUGTYPE (.*) -->$/) {
371e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $BugType = $1;
372e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
373e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    elsif (/<!-- BUGFILE (.*) -->$/) {
374e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $BugFile = abs_path($1);
375e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      UpdatePrefix($BugFile);
376e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
377e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    elsif (/<!-- BUGPATHLENGTH (.*) -->$/) {
378e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $BugPathLength = $1;
379e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
380e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    elsif (/<!-- BUGLINE (.*) -->$/) {
381e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $BugLine = $1;    
382e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
383e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    elsif (/<!-- BUGCATEGORY (.*) -->$/) {
384e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $BugCategory = $1;
385e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
386e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    elsif (/<!-- BUGDESC (.*) -->$/) {
387e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $BugDescription = $1;
388e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
389e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
390e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
391e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  close(IN);
392e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
393e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (!defined $BugCategory) {
394e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $BugCategory = "Other";
395e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
396e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
397e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Don't add internal statistics to the bug reports
398e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($BugCategory =~ /statistics/i) {
399e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    AddStatLine($BugDescription, $Stats, $BugFile);
400e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    return;
401e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
402e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
403e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  push @$Index,[ $FName, $BugCategory, $BugType, $BugFile, $BugLine,
404e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh                 $BugPathLength ];
405e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
406e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
407e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
408e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# CopyFiles - Copy resource files to target directory.
409e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
410e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
411e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub CopyFiles {
412e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
413e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Dir = shift;
414e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
415e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $JS = Cwd::realpath("$RealBin/sorttable.js");
416e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
417e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  DieDiag("Cannot find 'sorttable.js'.\n")
418e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (! -r $JS);  
419e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
420e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  system ("cp", $JS, "$Dir");
421e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
422e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n")
423e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (! -r "$Dir/sorttable.js");
424e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
425e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $CSS = Cwd::realpath("$RealBin/scanview.css");
426e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
427e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  DieDiag("Cannot find 'scanview.css'.\n")
428e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (! -r $CSS);
429e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
430e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  system ("cp", $CSS, "$Dir");
431e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
432e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  DieDiag("Could not copy 'scanview.css' to '$Dir'.\n")
433e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (! -r $CSS);
434e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
435e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
436e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
437e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# CalcStats - Calculates visitation statistics and returns the string.
438e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
439e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
440e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub CalcStats {
441e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Stats = shift;
442e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
443e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $TotalBlocks = 0;
444e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $UnreachedBlocks = 0;
445e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $TotalFunctions = scalar(@$Stats);
446e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $BlockAborted = 0;
447e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $WorkListAborted = 0;
448e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Aborted = 0;
449e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
450e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Calculate the unique files
451e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $FilesHash = {};
452e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
453e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  foreach my $Row (@$Stats) {
454e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $FilesHash->{$Row->{Filename}} = 1;
455e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $TotalBlocks += $Row->{Total};
456e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $UnreachedBlocks += $Row->{Unreachable};
457e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $BlockAborted++ if $Row->{Aborted} eq 'yes';
458e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $WorkListAborted++ if $Row->{Empty} eq 'no';
459e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $Aborted++ if $Row->{Aborted} eq 'yes' || $Row->{Empty} eq 'no';
460e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
461e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
462e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $TotalFiles = scalar(keys(%$FilesHash));
463e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
464e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Calculations
465e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $PercentAborted = sprintf("%.2f", $Aborted / $TotalFunctions * 100);
466e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $PercentBlockAborted = sprintf("%.2f", $BlockAborted / $TotalFunctions
467e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      * 100);
468e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $PercentWorkListAborted = sprintf("%.2f", $WorkListAborted /
469e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $TotalFunctions * 100);
470e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $PercentBlocksUnreached = sprintf("%.2f", $UnreachedBlocks / $TotalBlocks
471e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      * 100);
472e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
473e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $StatsString = "Analyzed $TotalBlocks blocks in $TotalFunctions functions"
474e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    . " in $TotalFiles files\n"
475e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    . "$Aborted functions aborted early ($PercentAborted%)\n"
476e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    . "$BlockAborted had aborted blocks ($PercentBlockAborted%)\n"
477e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    . "$WorkListAborted had unfinished worklists ($PercentWorkListAborted%)\n"
478e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    . "$UnreachedBlocks blocks were never reached ($PercentBlocksUnreached%)\n";
479e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
480e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  return $StatsString;
481e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
482e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
483e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
484e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Postprocess - Postprocess the results of an analysis scan.
485e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
486e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
487e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy @filesFound;
488e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $baseDir;
489e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub FileWanted { 
490e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $baseDirRegEx = quotemeta $baseDir;
491e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $file = $File::Find::name;
492e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if ($file =~ /report-.*\.html$/) {
493e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh       my $relative_file = $file;
494e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh       $relative_file =~ s/$baseDirRegEx//g;
495e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh       push @filesFound, $relative_file;
496e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
497e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
498e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
499e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub Postprocess {
500e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
501e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Dir           = shift;
502e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $BaseDir       = shift;
503e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $AnalyzerStats = shift;
504e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $KeepEmpty     = shift;
505e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
506e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  die "No directory specified." if (!defined $Dir);
507e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
508e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (! -d $Dir) {
509e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Diag("No bugs found.\n");
510e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    return 0;
511e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
512e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
513e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $baseDir = $Dir . "/";
514e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  find({ wanted => \&FileWanted, follow => 0}, $Dir);
515e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
516e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (scalar(@filesFound) == 0 and ! -e "$Dir/failures") {
517e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (! $KeepEmpty) {
518e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      Diag("Removing directory '$Dir' because it contains no reports.\n");
519e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      system ("rm", "-fR", $Dir);
520e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
521e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Diag("No bugs found.\n");
522e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    return 0;
523e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
524e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
525e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Scan each report file and build an index.  
526e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my @Index;
527e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my @Stats;
528e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  foreach my $file (@filesFound) { ScanFile(\@Index, $Dir, $file, \@Stats); }
529e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
530e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Scan the failures directory and use the information in the .info files
531e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # to update the common prefix directory.
532e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my @failures;
533e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my @attributes_ignored;
534e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (-d "$Dir/failures") {
535e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    opendir(DIR, "$Dir/failures");
536e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    @failures = grep { /[.]info.txt$/ && !/attribute_ignored/; } readdir(DIR);
537e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    closedir(DIR);
538e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    opendir(DIR, "$Dir/failures");        
539e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    @attributes_ignored = grep { /^attribute_ignored/; } readdir(DIR);
540e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    closedir(DIR);
541e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    foreach my $file (@failures) {
542e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      open IN, "$Dir/failures/$file" or DieDiag("cannot open $file\n");
543e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $Path = <IN>;
544e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (defined $Path) { UpdatePrefix($Path); }
545e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      close IN;
546e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }    
547e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
548e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
549e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Generate an index.html file.  
550e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $FName = "$Dir/index.html";  
551e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n");
552e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
553e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Print out the header.
554e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
555e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehprint OUT <<ENDTEXT;
556e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<html>
557e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<head>
558e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<title>${HtmlTitle}</title>
559e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<link type="text/css" rel="stylesheet" href="scanview.css"/>
560e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<script src="sorttable.js"></script>
561e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<script language='javascript' type="text/javascript">
562e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehfunction SetDisplay(RowClass, DisplayVal)
563e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh{
564e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  var Rows = document.getElementsByTagName("tr");
565e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  for ( var i = 0 ; i < Rows.length; ++i ) {
566e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (Rows[i].className == RowClass) {
567e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      Rows[i].style.display = DisplayVal;
568e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
569e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
570e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
571e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
572e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehfunction CopyCheckedStateToCheckButtons(SummaryCheckButton) {
573e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  var Inputs = document.getElementsByTagName("input");
574e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  for ( var i = 0 ; i < Inputs.length; ++i ) {
575e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (Inputs[i].type == "checkbox") {
576e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if(Inputs[i] != SummaryCheckButton) {
577e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        Inputs[i].checked = SummaryCheckButton.checked;
578e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        Inputs[i].onclick();
579e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	  }
580e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
581e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
582e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
583e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
584e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehfunction returnObjById( id ) {
585e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (document.getElementById) 
586e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        var returnVar = document.getElementById(id);
587e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    else if (document.all)
588e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        var returnVar = document.all[id];
589e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    else if (document.layers) 
590e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        var returnVar = document.layers[id];
591e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    return returnVar; 
592e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
593e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
594e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehvar NumUnchecked = 0;
595e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
596e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehfunction ToggleDisplay(CheckButton, ClassName) {
597e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (CheckButton.checked) {
598e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    SetDisplay(ClassName, "");
599e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (--NumUnchecked == 0) {
600e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      returnObjById("AllBugsCheck").checked = true;
601e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
602e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
603e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  else {
604e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    SetDisplay(ClassName, "none");
605e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    NumUnchecked++;
606e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    returnObjById("AllBugsCheck").checked = false;
607e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
608e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
609e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh</script>
610e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<!-- SUMMARYENDHEAD -->
611e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh</head>
612e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<body>
613e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<h1>${HtmlTitle}</h1>
614e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
615e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<table>
616e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<tr><th>User:</th><td>${UserName}\@${HostName}</td></tr>
617e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<tr><th>Working Directory:</th><td>${CurrentDir}</td></tr>
618e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<tr><th>Command Line:</th><td>${CmdArgs}</td></tr>
619e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<tr><th>Clang Version:</th><td>${ClangVersion}</td></tr>
620e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<tr><th>Date:</th><td>${Date}</td></tr>
621e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehENDTEXT
622e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
623e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehprint OUT "<tr><th>Version:</th><td>${BuildName} (${BuildDate})</td></tr>\n"
624e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (defined($BuildName) && defined($BuildDate));
625e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
626e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehprint OUT <<ENDTEXT;
627e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh</table>
628e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehENDTEXT
629e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
630e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (scalar(@filesFound)) {
631e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    # Print out the summary table.
632e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my %Totals;
633e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
634e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    for my $row ( @Index ) {
635e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $bug_type = ($row->[2]);
636e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $bug_category = ($row->[1]);
637e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $key = "$bug_category:$bug_type";
638e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
639e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (!defined $Totals{$key}) { $Totals{$key} = [1,$bug_category,$bug_type]; }
640e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      else { $Totals{$key}->[0]++; }
641e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
642e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
643e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print OUT "<h2>Bug Summary</h2>";
644e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
645e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (defined $BuildName) {
646e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n"
647e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
648e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
649e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $TotalBugs = scalar(@Index);
650e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehprint OUT <<ENDTEXT;
651e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<table>
652e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<thead><tr><td>Bug Type</td><td>Quantity</td><td class="sorttable_nosort">Display?</td></tr></thead>
653e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<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>
654e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehENDTEXT
655e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
656e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $last_category;
657e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
658e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    for my $key (
659e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      sort {
660e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $x = $Totals{$a};
661e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $y = $Totals{$b};
662e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $res = $x->[1] cmp $y->[1];
663e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $res = $x->[2] cmp $y->[2] if ($res == 0);
664e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $res
665e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      } keys %Totals ) 
666e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    {
667e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $val = $Totals{$key};
668e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $category = $val->[1];
669e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (!defined $last_category or $last_category ne $category) {
670e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $last_category = $category;
671e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        print OUT "<tr><th>$category</th><th colspan=2></th></tr>\n";
672e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }      
673e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $x = lc $key;
674e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $x =~ s/[ ,'":\/()]+/_/g;
675e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<tr><td class=\"SUMM_DESC\">";
676e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT $val->[2];
677e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "</td><td class=\"Q\">";
678e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT $val->[0];
679e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "</td><td><center><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></center></td></tr>\n";
680e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
681e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
682e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Print out the table of errors.
683e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
684e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehprint OUT <<ENDTEXT;
685e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh</table>
686e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<h2>Reports</h2>
687e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
688e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<table class="sortable" style="table-layout:automatic">
689e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<thead><tr>
690e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  <td>Bug Group</td>
691e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  <td class="sorttable_sorted">Bug Type<span id="sorttable_sortfwdind">&nbsp;&#x25BE;</span></td>
692e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  <td>File</td>
693e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  <td class="Q">Line</td>
694e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  <td class="Q">Path Length</td>
695e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  <td class="sorttable_nosort"></td>
696e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  <!-- REPORTBUGCOL -->
697e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh</tr></thead>
698e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh<tbody>
699e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehENDTEXT
700e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
701e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $prefix = GetPrefix();
702e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $regex;
703e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $InFileRegex;
704e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $InFilePrefix = "File:</td><td>";
705e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
706e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (defined $prefix) { 
707e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $regex = qr/^\Q$prefix\E/is;    
708e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is;
709e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }    
710e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
711e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    for my $row ( sort { $a->[2] cmp $b->[2] } @Index ) {
712e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $x = "$row->[1]:$row->[2]";
713e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $x = lc $x;
714e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $x =~ s/[ ,'":\/()]+/_/g;
715e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
716e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $ReportFile = $row->[0];
717e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          
718e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<tr class=\"bt_$x\">";
719e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<td class=\"DESC\">";
720e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT $row->[1];
721e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "</td>";
722e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<td class=\"DESC\">";
723e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT $row->[2];
724e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "</td>";
725e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      
726e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      # Update the file prefix.      
727e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $fname = $row->[3];
728e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
729e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (defined $regex) {
730e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $fname =~ s/$regex//;
731e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix)
732e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
733e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      
734e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<td>";      
735e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my @fname = split /\//,$fname;
736e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if ($#fname > 0) {
737e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        while ($#fname >= 0) {
738e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          my $x = shift @fname;
739e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          print OUT $x;
740e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          if ($#fname >= 0) {
741e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh            print OUT "<span class=\"W\"> </span>/";
742e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          }
743e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        }
744e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
745e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      else {
746e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        print OUT $fname;
747e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }      
748e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "</td>";
749e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      
750e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      # Print out the quantities.
751e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      for my $j ( 4 .. 5 ) {
752e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        print OUT "<td class=\"Q\">$row->[$j]</td>";        
753e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
754e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      
755e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      # Print the rest of the columns.
756e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      for (my $j = 6; $j <= $#{$row}; ++$j) {
757e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        print OUT "<td>$row->[$j]</td>"
758e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
759e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
760e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      # Emit the "View" link.
761e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<td><a href=\"$ReportFile#EndPath\">View Report</a></td>";
762e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        
763e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      # Emit REPORTBUG markers.
764e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "\n<!-- REPORTBUG id=\"$ReportFile\" -->\n";
765e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        
766e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      # End the row.
767e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "</tr>\n";
768e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
769e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
770e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print OUT "</tbody>\n</table>\n\n";
771e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
772e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
773e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (scalar (@failures) || scalar(@attributes_ignored)) {
774e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print OUT "<h2>Analyzer Failures</h2>\n";
775e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
776e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (scalar @attributes_ignored) {
777e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "The analyzer's parser ignored the following attributes:<p>\n";
778e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<table>\n";
779e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<thead><tr><td>Attribute</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>\n";
780e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      foreach my $file (sort @attributes_ignored) {
781e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        die "cannot demangle attribute name\n" if (! ($file =~ /^attribute_ignored_(.+).txt/));
782e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $attribute = $1;
783e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        # Open the attribute file to get the first file that failed.
784e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        next if (!open (ATTR, "$Dir/failures/$file"));
785e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $ppfile = <ATTR>;
786e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        chomp $ppfile;
787e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        close ATTR;
788e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        next if (! -e "$Dir/failures/$ppfile");
789e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        # Open the info file and get the name of the source file.
790e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        open (INFO, "$Dir/failures/$ppfile.info.txt") or
791e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          die "Cannot open $Dir/failures/$ppfile.info.txt\n";
792e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $srcfile = <INFO>;
793e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        chomp $srcfile;
794e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        close (INFO);
795e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        # Print the information in the table.
796e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $prefix = GetPrefix();
797e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; }
798e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        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";
799e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $ppfile_clang = $ppfile;
800e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $ppfile_clang =~ s/[.](.+)$/.clang.$1/;
801e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        print OUT "  <!-- REPORTPROBLEM src=\"$srcfile\" file=\"failures/$ppfile\" clangfile=\"failures/$ppfile_clang\" stderr=\"failures/$ppfile.stderr.txt\" info=\"failures/$ppfile.info.txt\" -->\n";
802e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
803e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "</table>\n";
804e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
805e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
806e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (scalar @failures) {
807e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<p>The analyzer had problems processing the following files:</p>\n";
808e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<table>\n";
809e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "<thead><tr><td>Problem</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>\n";
810e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      foreach my $file (sort @failures) {
811e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $file =~ /(.+).info.txt$/;
812e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        # Get the preprocessed file.
813e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $ppfile = $1;
814e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        # Open the info file and get the name of the source file.
815e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        open (INFO, "$Dir/failures/$file") or
816e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          die "Cannot open $Dir/failures/$file\n";
817e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $srcfile = <INFO>;
818e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        chomp $srcfile;
819e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $problem = <INFO>;
820e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        chomp $problem;
821e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        close (INFO);
822e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        # Print the information in the table.
823e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $prefix = GetPrefix();
824e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; }
825e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        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";
826e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $ppfile_clang = $ppfile;
827e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $ppfile_clang =~ s/[.](.+)$/.clang.$1/;
828e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        print OUT "  <!-- REPORTPROBLEM src=\"$srcfile\" file=\"failures/$ppfile\" clangfile=\"failures/$ppfile_clang\" stderr=\"failures/$ppfile.stderr.txt\" info=\"failures/$ppfile.info.txt\" -->\n";
829e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
830e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print OUT "</table>\n";
831e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }    
832e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print OUT "<p>Please consider submitting preprocessed files as <a href=\"http://clang-analyzer.llvm.org/filing_bugs.html\">bug reports</a>. <!-- REPORTCRASHES --> </p>\n";
833e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
834e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
835e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  print OUT "</body></html>\n";  
836e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  close(OUT);
837e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  CopyFiles($Dir);
838e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
839e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Make sure $Dir and $BaseDir are world readable/executable.
840e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  system("chmod", "755", $Dir);
841e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (defined $BaseDir) { system("chmod", "755", $BaseDir); }
842e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
843e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Print statistics
844e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  print CalcStats(\@Stats) if $AnalyzerStats;
845e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
846e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Num = scalar(@Index);
847e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  Diag("$Num bugs found.\n");
848e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($Num > 0 && -r "$Dir/index.html") {
849e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      Diag("Run '$Top/prebuilts/misc/linux-x86/analyzer/tools/scan-view/scan-view $Dir' to examine bug reports.\n");
850e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
851e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
852e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  DiagCrashes($Dir) if (scalar @failures || scalar @attributes_ignored);
853e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
854e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  return $Num;
855e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
856e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
857e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
858e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# RunBuildCommand - Run the build command.
859e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
860e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
861e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub AddIfNotPresent {
862e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Args = shift;
863e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Arg = shift;  
864e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $found = 0;
865e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
866e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  foreach my $k (@$Args) {
867e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if ($k eq $Arg) {
868e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $found = 1;
869e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      last;
870e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
871e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
872e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
873e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($found == 0) {
874e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    push @$Args, $Arg;
875e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
876e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
877e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
878e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub SetEnv {
879e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Options = shift @_;
880e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  foreach my $opt ('CC', 'CXX', 'CLANG', 'CLANG_CXX',
881e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh                    'CCC_ANALYZER_ANALYSIS', 'CCC_ANALYZER_PLUGINS') {
882e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    die "$opt is undefined\n" if (!defined $opt);
883e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $ENV{$opt} = $Options->{$opt};
884e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
885e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  foreach my $opt ('CCC_ANALYZER_STORE_MODEL',
886e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh                    'CCC_ANALYZER_PLUGINS',
887e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh                    'CCC_ANALYZER_INTERNAL_STATS',
888e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh                    'CCC_ANALYZER_OUTPUT_FORMAT') {
889e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $x = $Options->{$opt};
890e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (defined $x) { $ENV{$opt} = $x }
891e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
892e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Verbose = $Options->{'VERBOSE'};
893e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($Verbose >= 2) {
894e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $ENV{'CCC_ANALYZER_VERBOSE'} = 1;
895e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
896e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($Verbose >= 3) {
897e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $ENV{'CCC_ANALYZER_LOG'} = 1;
898e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
899e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
900e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
901e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# The flag corresponding to the --override-compiler command line option.
902e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $OverrideCompiler = 0; 
903e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
904e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub RunXcodebuild {
905e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Args = shift;
906e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $IgnoreErrors = shift;
907e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $CCAnalyzer = shift;
908e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $CXXAnalyzer = shift;
909e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Options = shift;
910e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
911e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($IgnoreErrors) {
912e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES");
913e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
914e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
915e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Detect the version of Xcode.  If Xcode 4.6 or higher, use new
916e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # in situ support for analyzer interposition without needed to override
917e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # the compiler.
918e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  open(DETECT_XCODE, "-|", $Args->[0], "-version") or
919e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    die "error: cannot detect version of xcodebuild\n";
920e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
921e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $oldBehavior = 1;
922e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
923e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  while(<DETECT_XCODE>) {
924e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (/^Xcode (.+)$/) {
925e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $ver = $1;
926e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if ($ver =~ /^([0-9]+[.][0-9]+)[^0-9]?/) {
927e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        if ($1 >= 4.6) {
928e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          $oldBehavior = 0;
929e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          last;
930e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        }
931e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
932e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
933e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
934e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  close(DETECT_XCODE);
935e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
936e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # If --override-compiler is explicitely requested, resort to the old 
937e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # behavior regardless of Xcode version.
938e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($OverrideCompiler) {
939e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $oldBehavior = 1;
940e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
941e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
942e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($oldBehavior == 0) {
943e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $OutputDir = $Options->{"OUTPUT_DIR"};
944e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $CLANG = $Options->{"CLANG"};
945e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $OtherFlags = $Options->{"CCC_ANALYZER_ANALYSIS"};
946e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    push @$Args,
947e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        "RUN_CLANG_STATIC_ANALYZER=YES",
948e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        "CLANG_ANALYZER_OUTPUT=plist-html",
949e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        "CLANG_ANALYZER_EXEC=$CLANG",
950e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        "CLANG_ANALYZER_OUTPUT_DIR=$OutputDir",
951e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        "CLANG_ANALYZER_OTHER_FLAGS=$OtherFlags";
952e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
953e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    return (system(@$Args) >> 8);
954e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
955e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
956e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Default to old behavior where we insert a bogus compiler.
957e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  SetEnv($Options);
958e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
959e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Check if using iPhone SDK 3.0 (simulator).  If so the compiler being
960e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # used should be gcc-4.2.
961e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (!defined $ENV{"CCC_CC"}) {
962e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    for (my $i = 0 ; $i < scalar(@$Args); ++$i) {
963e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if ($Args->[$i] eq "-sdk" && $i + 1 < scalar(@$Args)) {
964e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        if (@$Args[$i+1] =~ /^iphonesimulator3/) {
965e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          $ENV{"CCC_CC"} = "gcc-4.2";
966e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          $ENV{"CCC_CXX"} = "g++-4.2";
967e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        }
968e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
969e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
970e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
971e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
972e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Disable PCH files until clang supports them.
973e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO");
974e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
975e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # When 'CC' is set, xcodebuild uses it to do all linking, even if we are
976e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # linking C++ object files.  Set 'LDPLUSPLUS' so that xcodebuild uses 'g++'
977e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # (via c++-analyzer) when linking such files.
978e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $ENV{"LDPLUSPLUS"} = $CXXAnalyzer;
979e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
980e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  return (system(@$Args) >> 8); 
981e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
982e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
983e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub RunBuildCommand {  
984e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Args = shift;
985e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $IgnoreErrors = shift;
986e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Cmd = $Args->[0];
987e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $CCAnalyzer = shift;
988e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $CXXAnalyzer = shift;
989e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $Options = shift;
990e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
991e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($Cmd =~ /\bxcodebuild$/) {
992e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    return RunXcodebuild($Args, $IgnoreErrors, $CCAnalyzer, $CXXAnalyzer, $Options);
993e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
994e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
995e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Setup the environment.
996e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  SetEnv($Options);
997e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
998e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($Cmd =~ /(.*\/?gcc[^\/]*$)/ or 
999e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $Cmd =~ /(.*\/?cc[^\/]*$)/ or
1000e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $Cmd =~ /(.*\/?llvm-gcc[^\/]*$)/ or
1001e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $Cmd =~ /(.*\/?clang$)/ or 
1002e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $Cmd =~ /(.*\/?ccc-analyzer[^\/]*$)/) {
1003e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1004e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (!($Cmd =~ /ccc-analyzer/) and !defined $ENV{"CCC_CC"}) {
1005e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $ENV{"CCC_CC"} = $1;      
1006e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1007e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        
1008e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @$Args;
1009e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    unshift @$Args, $CCAnalyzer;
1010e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1011e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  elsif ($Cmd =~ /(.*\/?g\+\+[^\/]*$)/ or 
1012e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $Cmd =~ /(.*\/?c\+\+[^\/]*$)/ or
1013e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $Cmd =~ /(.*\/?llvm-g\+\+[^\/]*$)/ or
1014e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $Cmd =~ /(.*\/?clang\+\+$)/ or
1015e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $Cmd =~ /(.*\/?c\+\+-analyzer[^\/]*$)/) {
1016e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (!($Cmd =~ /c\+\+-analyzer/) and !defined $ENV{"CCC_CXX"}) {
1017e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $ENV{"CCC_CXX"} = $1;      
1018e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }        
1019e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @$Args;
1020e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    unshift @$Args, $CXXAnalyzer;
1021e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1022e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  elsif ($Cmd eq "make" or $Cmd eq "gmake") {
1023e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    AddIfNotPresent($Args, "CC=$CCAnalyzer");
1024e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    AddIfNotPresent($Args, "CXX=$CXXAnalyzer");
1025e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if ($IgnoreErrors) {
1026e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      AddIfNotPresent($Args,"-k");
1027e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      AddIfNotPresent($Args,"-i");
1028e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1029e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  } 
1030e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1031e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  return (system(@$Args) >> 8);
1032e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1033e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1034e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
1035e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# DisplayHelp - Utility function to display all help options.
1036e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
1037e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1038e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub DisplayHelp {
1039e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1040e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehprint <<ENDTEXT;
1041e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehUSAGE: $Prog [options] <build command> [build options]
1042e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1043e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehENDTEXT
1044e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1045e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (defined $BuildName) {
1046e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n";
1047e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1048e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1049e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehprint <<ENDTEXT;
1050e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehOPTIONS:
1051e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1052e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -analyze-headers
1053e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1054e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Also analyze functions in #included files.  By default, such functions
1055e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   are skipped unless they are called by functions within the main source file.
1056e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1057e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -o <output location>
1058e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1059e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Specifies the output directory for analyzer reports. Subdirectories will be
1060e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   created as needed to represent separate "runs" of the analyzer. If this
1061e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   option is not specified, a directory is created in /tmp (TMPDIR on Mac OS X)
1062e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   to store the reports.
1063e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1064e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -h             
1065e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --help
1066e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1067e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Display this message.
1068e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1069e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -k
1070e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --keep-going
1071e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh				  
1072e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Add a "keep on going" option to the specified build command. This option
1073e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   currently supports make and xcodebuild. This is a convenience option; one
1074e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   can specify this behavior directly using build options.
1075e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1076e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --html-title [title]
1077e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --html-title=[title]
1078e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1079e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Specify the title used on generated HTML pages. If not specified, a default
1080e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   title will be used.
1081e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1082e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -plist
1083e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1084e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   By default the output of scan-build is a set of HTML files. This option
1085e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   outputs the results as a set of .plist files.
1086e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1087e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -plist-html
1088e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1089e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   By default the output of scan-build is a set of HTML files. This option
1090e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   outputs the results as a set of HTML and .plist files.
1091e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1092e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --status-bugs
1093e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1094e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   By default, the exit status of scan-build is the same as the executed build
1095e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   command. Specifying this option causes the exit status of scan-build to be 1
1096e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   if it found potential bugs and 0 otherwise.
1097e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1098e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --use-cc [compiler path]   
1099e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --use-cc=[compiler path]
1100e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1101e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   scan-build analyzes a project by interposing a "fake compiler", which
1102e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   executes a real compiler for compilation and the static analyzer for analysis.
1103e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Because of the current implementation of interposition, scan-build does not
1104e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   know what compiler your project normally uses.  Instead, it simply overrides
1105e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   the CC environment variable, and guesses your default compiler.
1106e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   
1107e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   In the future, this interposition mechanism to be improved, but if you need
1108e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   scan-build to use a specific compiler for *compilation* then you can use
1109e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   this option to specify a path to that compiler.
1110e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1111e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --use-c++ [compiler path]
1112e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --use-c++=[compiler path]
1113e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1114e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   This is the same as "-use-cc" but for C++ code.
1115e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1116e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -v
1117e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1118e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Enable verbose output from scan-build. A second and third '-v' increases
1119e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   verbosity.
1120e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1121e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -V
1122e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --view
1123e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1124e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   View analysis results in a web browser when the build completes.
1125e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1126e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehADVANCED OPTIONS:
1127e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1128e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -no-failure-reports
1129e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1130e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Do not create a 'failures' subdirectory that includes analyzer crash reports
1131e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   and preprocessed source files.
1132e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1133e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -stats
1134e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1135e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Generates visitation statistics for the project being analyzed.
1136e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1137e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -maxloop <loop count>
1138e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1139e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Specifiy the number of times a block can be visited before giving up.
1140e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Default is 4. Increase for more comprehensive coverage at a cost of speed.
1141e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1142e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -internal-stats
1143e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1144e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Generate internal analyzer statistics.
1145e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1146e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --use-analyzer [Xcode|path to clang] 
1147e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --use-analyzer=[Xcode|path to clang]
1148e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1149e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   scan-build uses the 'clang' executable relative to itself for static
1150e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   analysis. One can override this behavior with this option by using the
1151e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   'clang' packaged with Xcode (on OS X) or from the PATH.
1152e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1153e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --keep-empty
1154e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1155e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Don't remove the build results directory even if no issues were reported.
1156e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1157e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh --override-compiler 
1158e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   Always resort to the ccc-analyzer even when better interposition methods 
1159e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   are available.
1160e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   
1161e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehCONTROLLING CHECKERS:
1162e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1163e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh A default group of checkers are always run unless explicitly disabled.
1164e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh Checkers may be enabled/disabled using the following options:
1165e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1166e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -enable-checker [checker name]
1167e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -disable-checker [checker name]
1168e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 
1169e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehLOADING CHECKERS:
1170e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1171e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh Loading external checkers using the clang plugin interface:
1172e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1173e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh -load-plugin [plugin library]
1174e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehENDTEXT
1175e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1176e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Query clang for list of checkers that are enabled.
1177e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1178e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# create a list to load the plugins via the 'Xclang' command line
1179e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# argument
1180e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy @PluginLoadCommandline_xclang;
1181e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehforeach my $param ( @PluginsToLoad ) {
1182e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  push ( @PluginLoadCommandline_xclang, "-Xclang" );
1183e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  push ( @PluginLoadCommandline_xclang, $param );
1184e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1185e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy %EnabledCheckers;
1186e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehforeach my $lang ("c", "objective-c", "objective-c++", "c++") {
1187e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  pipe(FROM_CHILD, TO_PARENT);
1188e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $pid = fork();
1189e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($pid == 0) {
1190e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    close FROM_CHILD;
1191e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    open(STDOUT,">&", \*TO_PARENT);
1192e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    open(STDERR,">&", \*TO_PARENT);
1193e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    exec $Clang, ( @PluginLoadCommandline_xclang, '--analyze', '-x', $lang, '-', '-###'); 
1194e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1195e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  close(TO_PARENT);
1196e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  while(<FROM_CHILD>) {
1197e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    foreach my $val (split /\s+/) {
1198e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $val =~ s/\"//g;
1199e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if ($val =~ /-analyzer-checker\=([^\s]+)/) {
1200e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $EnabledCheckers{$1} = 1;
1201e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
1202e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1203e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1204e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  waitpid($pid,0);
1205e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  close(FROM_CHILD);
1206e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1207e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1208e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Query clang for complete list of checkers.
1209e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (defined $Clang && -x $Clang) {
1210e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  pipe(FROM_CHILD, TO_PARENT);
1211e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $pid = fork();
1212e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($pid == 0) {
1213e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    close FROM_CHILD;
1214e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    open(STDOUT,">&", \*TO_PARENT);
1215e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    open(STDERR,">&", \*TO_PARENT);
1216e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    exec $Clang, ('-cc1', @PluginsToLoad , '-analyzer-checker-help');
1217e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1218e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  close(TO_PARENT);
1219e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $foundCheckers = 0;
1220e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  while(<FROM_CHILD>) {
1221e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (/CHECKERS:/) {
1222e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $foundCheckers = 1;
1223e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      last;
1224e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1225e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1226e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (!$foundCheckers) {
1227e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print "  *** Could not query Clang for the list of available checkers.";
1228e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1229e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  else {
1230e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print("\nAVAILABLE CHECKERS:\n\n");
1231e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $skip = 0;
1232e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    while(<FROM_CHILD>) {
1233e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (/experimental/) {
1234e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $skip = 1;
1235e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        next;
1236e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
1237e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if ($skip) {
1238e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        next if (!/^\s\s[^\s]/);
1239e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        $skip = 0;
1240e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
1241e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      s/^\s\s//;
1242e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (/^([^\s]+)/) {
1243e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        # Is the checker enabled?
1244e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $checker = $1;
1245e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $enabled = 0;
1246e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        my $aggregate = "";
1247e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        foreach my $domain (split /\./, $checker) {
1248e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          $aggregate .= $domain;
1249e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          if ($EnabledCheckers{$aggregate}) {
1250e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh            $enabled =1;
1251e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh            last;
1252e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          }
1253e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          # append a dot, if an additional domain is added in the next iteration
1254e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          $aggregate .= ".";
1255e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        }
1256e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      
1257e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        if ($enabled) {
1258e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          print " + ";
1259e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        }
1260e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        else {
1261e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh          print "   ";
1262e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        }
1263e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
1264e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      else {
1265e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        print "   ";
1266e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
1267e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      print $_;
1268e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1269e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n"
1270e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1271e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  waitpid($pid,0);
1272e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  close(FROM_CHILD);
1273e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1274e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1275e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehprint <<ENDTEXT
1276e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1277e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehBUILD OPTIONS
1278e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1279e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh You can specify any build option acceptable to the build command.
1280e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1281e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehEXAMPLE
1282e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1283e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh scan-build -o /tmp/myhtmldir make -j4
1284e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh     
1285e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehThe above example causes analysis reports to be deposited into a subdirectory
1286e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehof "/tmp/myhtmldir" and to run "make" with the "-j4" option. A different
1287e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsubdirectory is created each time scan-build analyzes a project. The analyzer
1288e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehshould support most parallel builds, but not distributed builds.
1289e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1290e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehENDTEXT
1291e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1292e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1293e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
1294e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# HtmlEscape - HTML entity encode characters that are special in HTML
1295e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
1296e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1297e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub HtmlEscape {
1298e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # copy argument to new variable so we don't clobber the original
1299e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $arg = shift || '';
1300e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $tmp = $arg;
1301e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $tmp =~ s/&/&amp;/g;
1302e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $tmp =~ s/</&lt;/g;
1303e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $tmp =~ s/>/&gt;/g;
1304e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  return $tmp;
1305e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1306e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1307e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
1308e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# ShellEscape - backslash escape characters that are special to the shell
1309e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
1310e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1311e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehsub ShellEscape {
1312e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # copy argument to new variable so we don't clobber the original
1313e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $arg = shift || '';
1314e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg =~ /["\s]/) { return "'" . $arg . "'"; }
1315e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  return $arg;
1316e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1317e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1318e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
1319e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Process command-line arguments.
1320e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh##----------------------------------------------------------------------------##
1321e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1322e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $AnalyzeHeaders = 0;
1323e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $HtmlDir;           # Parent directory to store HTML files.
1324e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $IgnoreErrors = 0;  # Ignore build errors.
1325e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $ViewResults  = 0;  # View results when the build terminates.
1326e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $ExitStatusFoundBugs = 0; # Exit status reflects whether bugs were found
1327e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $KeepEmpty    = 0;  # Don't remove output directory even with 0 results.
1328e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy @AnalysesToRun;
1329e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $StoreModel;
1330e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $ConstraintsModel;
1331e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $InternalStats;
1332e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $OutputFormat = "html";
1333e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $AnalyzerStats = 0;
1334e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $MaxLoop = 0;
1335e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $RequestDisplayHelp = 0;
1336e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $ForceDisplayHelp = 0;
1337e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $AnalyzerDiscoveryMethod;
1338e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1339e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (!@ARGV) {
1340e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $ForceDisplayHelp = 1
1341e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1342e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1343e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehwhile (@ARGV) {
1344e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1345e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  # Scan for options we recognize.
1346e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1347e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  my $arg = $ARGV[0];
1348e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1349e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-h" or $arg eq "--help") {
1350e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $RequestDisplayHelp = 1;
1351e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1352e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1353e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1354e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1355e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq '-analyze-headers') {
1356e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;    
1357e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $AnalyzeHeaders = 1;
1358e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1359e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1360e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1361e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-o") {
1362e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1363e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        
1364e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (!@ARGV) {
1365e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      DieDiag("'-o' option requires a target directory name.\n");
1366e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1367e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
1368e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    # Construct an absolute path.  Uses the current working directory
1369e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    # as a base if the original path was not absolute.
1370e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $HtmlDir = abs_path(shift @ARGV);
1371e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
1372e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1373e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1374e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1375e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg =~ /^--html-title(=(.+))?$/) {
1376e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1377e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1378e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (!defined $2 || $2 eq '') {
1379e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (!@ARGV) {
1380e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        DieDiag("'--html-title' option requires a string.\n");
1381e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
1382e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1383e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $HtmlTitle = shift @ARGV;
1384e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    } else {
1385e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $HtmlTitle = $2;
1386e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1387e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1388e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1389e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1390e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1391e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-k" or $arg eq "--keep-going") {
1392e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1393e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $IgnoreErrors = 1;
1394e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1395e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1396e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1397e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg =~ /^--use-cc(=(.+))?$/) {
1398e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1399e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $cc;
1400e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
1401e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (!defined $2 || $2 eq "") {
1402e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (!@ARGV) {
1403e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        DieDiag("'--use-cc' option requires a compiler executable name.\n");
1404e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
1405e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $cc = shift @ARGV;
1406e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1407e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    else {
1408e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $cc = $2;
1409e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1410e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
1411e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $ENV{"CCC_CC"} = $cc;
1412e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1413e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1414e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1415e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg =~ /^--use-c\+\+(=(.+))?$/) {
1416e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1417e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $cxx;    
1418e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
1419e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (!defined $2 || $2 eq "") {
1420e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (!@ARGV) {
1421e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        DieDiag("'--use-c++' option requires a compiler executable name.\n");
1422e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
1423e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $cxx = shift @ARGV;
1424e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1425e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    else {
1426e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $cxx = $2;
1427e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1428e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    
1429e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $ENV{"CCC_CXX"} = $cxx;
1430e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1431e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1432e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1433e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-v") {
1434e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1435e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $Verbose++;
1436e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1437e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1438e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1439e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-V" or $arg eq "--view") {
1440e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1441e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $ViewResults = 1;    
1442e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1443e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1444e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1445e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "--status-bugs") {
1446e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1447e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $ExitStatusFoundBugs = 1;
1448e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1449e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1450e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1451e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-store") {
1452e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1453e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $StoreModel = shift @ARGV;
1454e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1455e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1456e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1457e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-constraints") {
1458e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1459e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $ConstraintsModel = shift @ARGV;
1460e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1461e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1462e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1463e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-internal-stats") {
1464e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1465e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $InternalStats = 1;
1466e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1467e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1468e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1469e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-plist") {
1470e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1471e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $OutputFormat = "plist";
1472e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1473e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1474e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-plist-html") {
1475e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1476e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $OutputFormat = "plist-html";
1477e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1478e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1479e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1480e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-no-failure-reports") {
1481e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $ENV{"CCC_REPORT_FAILURES"} = 0;
1482e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1483e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1484e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-stats") {
1485e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1486e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $AnalyzerStats = 1;
1487e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1488e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1489e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-maxloop") {
1490e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1491e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $MaxLoop = shift @ARGV;
1492e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1493e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1494e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-enable-checker") {
1495e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1496e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    push @AnalysesToRun, "-analyzer-checker", shift @ARGV;
1497e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1498e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1499e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-disable-checker") {
1500e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1501e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    push @AnalysesToRun, "-analyzer-disable-checker", shift @ARGV;
1502e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1503e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1504e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "-load-plugin") {
1505e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1506e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    push @PluginsToLoad, "-load", shift @ARGV;
1507e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1508e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1509e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "--use-analyzer") {
1510e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh 	shift @ARGV;
1511e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  	$AnalyzerDiscoveryMethod = shift @ARGV;
1512e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	next;
1513e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1514e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg =~ /^--use-analyzer=(.+)$/) {
1515e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1516e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	$AnalyzerDiscoveryMethod = $1;
1517e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	next;
1518e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1519e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "--keep-empty") {
1520e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1521e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $KeepEmpty = 1;
1522e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1523e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1524e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1525e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg eq "--override-compiler") {
1526e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1527e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $OverrideCompiler = 1;
1528e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1529e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1530e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1531e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($arg =~ /^--top(=(.+))?$/) {
1532e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    shift @ARGV;
1533e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1534e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (!defined $2 || $2 eq "") {
1535e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (!@ARGV) {
1536e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh        DieDiag("'--top' option requires a directory.\n");
1537e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      }
1538e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $Top = shift @ARGV;
1539e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1540e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    else {
1541e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      $Top = $2;
1542e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1543e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    next;
1544e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1545e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1546e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/);
1547e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  
1548e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  last;
1549e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1550e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1551e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (!@ARGV and !$RequestDisplayHelp) {
1552e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  ErrorDiag("No build command specified.\n\n");
1553e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $ForceDisplayHelp = 1;
1554e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1555e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1556e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Find 'clang'
1557e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (!defined $AnalyzerDiscoveryMethod) {
1558e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $Clang = Cwd::realpath("$RealBin/bin/clang");
1559e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (!defined $Clang || ! -x $Clang) {
1560e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $Clang = Cwd::realpath("$RealBin/clang");
1561e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1562e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if (!defined $Clang || ! -x $Clang) {
1563e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if (!$RequestDisplayHelp && !$ForceDisplayHelp) {
1564e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      DieDiag("error: Cannot find an executable 'clang' relative to scan-build." .
1565e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   	          "  Consider using --use-analyzer to pick a version of 'clang' to use for static analysis.\n");
1566e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1567e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1568e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh} 
1569e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehelse {  
1570e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($AnalyzerDiscoveryMethod =~ /^[Xx]code$/) {
1571e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	my $xcrun = `which xcrun`;
1572e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    chomp $xcrun;
1573e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	if ($xcrun eq "") {
1574e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  	  DieDiag("Cannot find 'xcrun' to find 'clang' for analysis.\n");
1575e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	}
1576e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $Clang = `$xcrun -toolchain XcodeDefault -find clang`;
1577e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    chomp $Clang;  
1578e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if ($Clang eq "") {
1579e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      DieDiag("No 'clang' executable found by 'xcrun'\n"); 
1580e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1581e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1582e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  else {
1583e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    $Clang = Cwd::realpath($AnalyzerDiscoveryMethod);
1584e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	if (!defined $Clang or not -x $Clang) {
1585e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh   	  DieDiag("Cannot find an executable clang at '$AnalyzerDiscoveryMethod'\n");
1586e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh	}
1587e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1588e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1589e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1590e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif ($ForceDisplayHelp || $RequestDisplayHelp) {
1591e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  DisplayHelp();
1592e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  exit $ForceDisplayHelp;
1593e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1594e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1595e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh$ClangCXX = $Clang;
1596e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Determine operating system under which this copy of Perl was built.
1597e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $IsWinBuild = ($^O =~/msys|cygwin|MSWin32/);
1598e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif($IsWinBuild) {
1599e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $ClangCXX =~ s/.exe$/++.exe/;
1600e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1601e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehelse {
1602e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $ClangCXX =~ s/\-\d+\.\d+$//;
1603e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $ClangCXX .= "++";
1604e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1605e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1606e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Make sure to use "" to handle paths with spaces.
1607e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh$ClangVersion = HtmlEscape(`"$Clang" --version`);
1608e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1609e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Determine where results go.
1610e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh$CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV)));
1611e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh$HtmlTitle = "${CurrentDirSuffix} - scan-build results"
1612e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  unless (defined($HtmlTitle));
1613e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1614e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Determine the output directory for the HTML reports.
1615e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $BaseDir = $HtmlDir;
1616e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh$HtmlDir = GetHTMLRunDir($HtmlDir);
1617e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1618e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Determine the location of ccc-analyzer.
1619e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $AbsRealBin = Cwd::realpath($RealBin);
1620e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $Cmd = "$AbsRealBin/libexec/ccc-analyzer";
1621e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $CmdCXX = "$AbsRealBin/libexec/c++-analyzer";
1622e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1623e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Portability: use less strict but portable check -e (file exists) instead of 
1624e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# non-portable -x (file is executable). On some windows ports -x just checks
1625e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# file extension to determine if a file is executable (see Perl language 
1626e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# reference, perlport)
1627e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (!defined $Cmd || ! -e $Cmd) {
1628e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $Cmd = "$AbsRealBin/ccc-analyzer";
1629e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  DieDiag("'ccc-analyzer' does not exist at '$Cmd'\n") if(! -e $Cmd);
1630e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1631e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (!defined $CmdCXX || ! -e $CmdCXX) {
1632e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $CmdCXX = "$AbsRealBin/c++-analyzer";
1633e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  DieDiag("'c++-analyzer' does not exist at '$CmdCXX'\n") if(! -e $CmdCXX);
1634e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1635e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1636e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehDiag("Using '$Clang' for static analysis\n");
1637e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1638e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew HsiehSetHtmlEnv(\@ARGV, $HtmlDir);
1639e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif ($AnalyzeHeaders) { push @AnalysesToRun,"-analyzer-opt-analyze-headers"; }
1640e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif ($AnalyzerStats) { push @AnalysesToRun, '-analyzer-checker=debug.Stats'; }
1641e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif ($MaxLoop > 0) { push @AnalysesToRun, "-analyzer-max-loop $MaxLoop"; }
1642e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1643e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Delay setting up other environment variables in case we can do true
1644e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# interposition.
1645e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $CCC_ANALYZER_ANALYSIS = join ' ',@AnalysesToRun;
1646e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $CCC_ANALYZER_PLUGINS = join ' ',@PluginsToLoad;
1647e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy %Options = (
1648e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  'CC' => $Cmd,
1649e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  'CXX' => $CmdCXX,
1650e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  'CLANG' => $Clang,
1651e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  'CLANG_CXX' => $ClangCXX,
1652e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  'VERBOSE' => $Verbose,
1653e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  'CCC_ANALYZER_ANALYSIS' => $CCC_ANALYZER_ANALYSIS,
1654e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  'CCC_ANALYZER_PLUGINS' => $CCC_ANALYZER_PLUGINS,
1655e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  'OUTPUT_DIR' => $HtmlDir
1656e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh);
1657e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1658e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (defined $StoreModel) {
1659e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $Options{'CCC_ANALYZER_STORE_MODEL'} = $StoreModel;
1660e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1661e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (defined $ConstraintsModel) {
1662e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $Options{'CCC_ANALYZER_CONSTRAINTS_MODEL'} = $ConstraintsModel;
1663e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1664e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (defined $InternalStats) {
1665e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $Options{'CCC_ANALYZER_INTERNAL_STATS'} = 1;
1666e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1667e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (defined $OutputFormat) {
1668e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  $Options{'CCC_ANALYZER_OUTPUT_FORMAT'} = $OutputFormat;
1669e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1670e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1671e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh# Run the build.
1672e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehmy $ExitStatus = RunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd, $CmdCXX,
1673e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh                                \%Options);
1674e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1675e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehif (defined $OutputFormat) {
1676e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($OutputFormat =~ /plist/) {
1677e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Diag "Analysis run complete.\n";
1678e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    Diag "Analysis results (plist files) deposited in '$HtmlDir'\n";
1679e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1680e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  if ($OutputFormat =~ /html/) {
1681e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    # Postprocess the HTML directory.
1682e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    my $NumBugs = Postprocess($HtmlDir, $BaseDir, $AnalyzerStats, $KeepEmpty);
1683e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1684e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if ($ViewResults and -r "$HtmlDir/index.html") {
1685e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      Diag "Analysis run complete.\n";
1686e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      Diag "Viewing analysis results in '$HtmlDir' using scan-view.\n";
1687e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      my $ScanView = Cwd::realpath("$RealBin/scan-view");
1688e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      if (! -x $ScanView) { $ScanView = "scan-view"; }
1689e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      exec $ScanView, "$HtmlDir";
1690e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1691e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1692e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    if ($ExitStatusFoundBugs) {
1693e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      exit 1 if ($NumBugs > 0);
1694e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh      exit 0;
1695e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh    }
1696e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh  }
1697e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh}
1698e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1699e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsiehexit $ExitStatus;
1700e5ae5b5826d42d2e26812699c4ced96a43c02eb7Andrew Hsieh
1701