16bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker#!/usr/bin/env perl
26bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker#
36bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker#                     The LLVM Compiler Infrastructure
46bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker#
56bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# This file is distributed under the University of Illinois Open Source
66bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# License. See LICENSE.TXT for details.
76bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker#
86bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##===----------------------------------------------------------------------===##
96bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker#
106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# A script designed to wrap a build so that all calls to gcc are intercepted
116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# and piped to the static analyzer.
126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker#
136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##===----------------------------------------------------------------------===##
146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse strict;
166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse warnings;
176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse FindBin qw($RealBin);
186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse Digest::MD5;
196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse File::Basename;
206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse File::Find;
216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse File::Copy qw(copy);
226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse File::Path qw( rmtree mkpath );
236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse Term::ANSIColor;
246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse Term::ANSIColor qw(:constants);
256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse Cwd qw/ getcwd abs_path /;
266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse Sys::Hostname;
276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickeruse Hash::Util qw(lock_keys);
286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $Prog = "scan-build";
306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $BuildName;
316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $BuildDate;
326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $TERM = $ENV{'TERM'};
346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $UseColor = (defined $TERM and $TERM =~ 'xterm-.*color' and -t STDOUT
356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                and defined $ENV{'SCAN_BUILD_COLOR'});
366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Portability: getpwuid is not implemented for Win32 (see Perl language
386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# reference, perlport), use getlogin instead.
396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $UserName = HtmlEscape(getlogin() || getpwuid($<) || 'unknown');
406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $HostName = HtmlEscape(hostname() || 'unknown');
416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $CurrentDir = HtmlEscape(getcwd());
426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $CmdArgs;
446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $Date = localtime();
466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Command-line/config arguments.
486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy %Options = (
496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  Verbose => 0,              # Verbose output from this script.
506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  AnalyzeHeaders => 0,
516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  OutputDir => undef,        # Parent directory to store HTML files.
526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  HtmlTitle => basename($CurrentDir)." - scan-build results",
536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  IgnoreErrors => 0,         # Ignore build errors.
546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  ViewResults => 0,          # View results when the build terminates.
556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  ExitStatusFoundBugs => 0,  # Exit status reflects whether bugs were found
566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  KeepEmpty => 0,            # Don't remove output directory even with 0 results.
576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  EnableCheckers => {},
586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  DisableCheckers => {},
596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  UseCC => undef,            # C compiler to use for compilation.
606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  UseCXX => undef,           # C++ compiler to use for compilation.
616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  AnalyzerTarget => undef,
626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  StoreModel => undef,
636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  ConstraintsModel => undef,
646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  InternalStats => undef,
656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  OutputFormat => "html",
666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  ConfigOptions => [],       # Options to pass through to the analyzer's -analyzer-config flag.
676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  ReportFailures => undef,
686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  AnalyzerStats => 0,
696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  MaxLoop => 0,
706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  PluginsToLoad => [],
716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  AnalyzerDiscoveryMethod => undef,
726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  OverrideCompiler => 0,      # The flag corresponding to the --override-compiler command line option.
736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  ForceAnalyzeDebugCode => 0
746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker);
756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerlock_keys(%Options);
766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Diagnostics
796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub Diag {
826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($UseColor) {
836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print BOLD, MAGENTA "$Prog: @_";
846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print RESET;
856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  else {
876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print "$Prog: @_";
886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub ErrorDiag {
926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($UseColor) {
936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print STDERR BOLD, RED "$Prog: ";
946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print STDERR RESET, RED @_;
956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print STDERR RESET;
966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  } else {
976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print STDERR "$Prog: @_";
986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
1006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub DiagCrashes {
1026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Dir = shift;
1036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  Diag ("The analyzer encountered problems on some source files.\n");
1046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  Diag ("Preprocessed versions of these sources were deposited in '$Dir/failures'.\n");
1056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  Diag ("Please consider submitting a bug report using these files:\n");
1066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  Diag ("  http://clang-analyzer.llvm.org/filing_bugs.html\n")
1076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
1086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub DieDiag {
1106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($UseColor) {
1116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print STDERR BOLD, RED "$Prog: ";
1126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print STDERR RESET, RED @_;
1136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print STDERR RESET;
1146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
1156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  else {
1166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print STDERR "$Prog: ", @_;
1176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
1186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  exit 1;
1196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
1206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
1226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Print default checker names
1236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
1246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif (grep /^--help-checkers$/, @ARGV) {
1266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my @options = qx($0 -h);
1276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    foreach (@options) {
1286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    next unless /^ \+/;
1296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    s/^\s*//;
1306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my ($sign, $name, @text) = split ' ', $_;
1316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print $name, $/ if $sign eq '+';
1326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
1336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    exit 0;
1346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
1356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
1376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Declaration of Clang options.  Populated later.
1386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
1396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $Clang;
1416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $ClangSB;
1426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $ClangCXX;
1436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $ClangVersion;
1446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
1466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# GetHTMLRunDir - Construct an HTML directory name for the current sub-run.
1476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
1486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub GetHTMLRunDir {
1506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  die "Not enough arguments." if (@_ == 0);
1516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Dir = shift @_;
1526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $TmpMode = 0;
1536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (!defined $Dir) {
1546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $Dir = $ENV{'TMPDIR'} || $ENV{'TEMP'} || $ENV{'TMP'} || "/tmp";
1556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $TmpMode = 1;
1566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
1576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Chop off any trailing '/' characters.
1596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  while ($Dir =~ /\/$/) { chop $Dir; }
1606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Get current date and time.
1626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my @CurrentTime = localtime();
1636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $year  = $CurrentTime[5] + 1900;
1646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $day   = $CurrentTime[3];
1656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $month = $CurrentTime[4] + 1;
1666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $hour =  $CurrentTime[2];
1676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $min =   $CurrentTime[1];
1686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $sec =   $CurrentTime[0];
1696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $TimeString = sprintf("%02d%02d%02d", $hour, $min, $sec);
1716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $DateString = sprintf("%d-%02d-%02d-%s-$$",
1726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                           $year, $month, $day, $TimeString);
1736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Determine the run number.
1756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $RunNumber;
1766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (-d $Dir) {
1786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (! -r $Dir) {
1796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      DieDiag("directory '$Dir' exists but is not readable.\n");
1806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
1816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # Iterate over all files in the specified directory.
1826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $max = 0;
1836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    opendir(DIR, $Dir);
1846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my @FILES = grep { -d "$Dir/$_" } readdir(DIR);
1856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    closedir(DIR);
1866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    foreach my $f (@FILES) {
1886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # Strip the prefix '$Prog-' if we are dumping files to /tmp.
1896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if ($TmpMode) {
1906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        next if (!($f =~ /^$Prog-(.+)/));
1916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $f = $1;
1926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
1936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
1946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my @x = split/-/, $f;
1956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next if (scalar(@x) != 4);
1966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next if ($x[0] != $year);
1976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next if ($x[1] != $month);
1986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next if ($x[2] != $day);
1996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next if ($x[3] != $TimeString);
2006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next if ($x[4] != $$);
2016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if ($x[5] > $max) {
2036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $max = $x[5];
2046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
2056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
2066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $RunNumber = $max + 1;
2086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
2096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  else {
2106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (-x $Dir) {
2126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      DieDiag("'$Dir' exists but is not a directory.\n");
2136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
2146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($TmpMode) {
2166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      DieDiag("The directory '/tmp' does not exist or cannot be accessed.\n");
2176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
2186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # $Dir does not exist.  It will be automatically created by the
2206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # clang driver.  Set the run number to 1.
2216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $RunNumber = 1;
2236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
2246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  die "RunNumber must be defined!" if (!defined $RunNumber);
2266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Append the run number.
2286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $NewDir;
2296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($TmpMode) {
2306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $NewDir = "$Dir/$Prog-$DateString-$RunNumber";
2316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
2326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  else {
2336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $NewDir = "$Dir/$DateString-$RunNumber";
2346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
2356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Make sure that the directory does not exist in order to avoid hijack.
2376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (-e $NewDir) {
2386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      DieDiag("The directory '$NewDir' already exists.\n");
2396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
2406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  mkpath($NewDir);
2426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return $NewDir;
2436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
2446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub SetHtmlEnv {
2466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  die "Wrong number of arguments." if (scalar(@_) != 2);
2486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Args = shift;
2506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Dir = shift;
2516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  die "No build command." if (scalar(@$Args) == 0);
2536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Cmd = $$Args[0];
2556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Cmd =~ /configure/ || $Cmd =~ /autogen/) {
2576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    return;
2586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
2596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Options{Verbose}) {
2616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Diag("Emitting reports for this run to '$Dir'.\n");
2626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
2636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $ENV{'CCC_ANALYZER_HTML'} = $Dir;
2656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
2666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
2686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# ComputeDigest - Compute a digest of the specified file.
2696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
2706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub ComputeDigest {
2726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $FName = shift;
2736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName);
2746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Use Digest::MD5.  We don't have to be cryptographically secure.  We're
2766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # just looking for duplicate files that come from a non-malicious source.
2776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # We use Digest::MD5 because it is a standard Perl module that should
2786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # come bundled on most systems.
2796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n");
2806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  binmode FILE;
2816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest;
2826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  close(FILE);
2836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Return the digest.
2856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return $Result;
2866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
2876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
2896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker#  UpdatePrefix - Compute the common prefix of files.
2906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
2916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $Prefix;
2936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub UpdatePrefix {
2956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $x = shift;
2966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $y = basename($x);
2976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $x =~ s/\Q$y\E$//;
2986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
2996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (!defined $Prefix) {
3006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $Prefix = $x;
3016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    return;
3026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
3036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  chop $Prefix while (!($x =~ /^\Q$Prefix/));
3056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
3066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub GetPrefix {
3086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return $Prefix;
3096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
3106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
3126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker#  UpdateInFilePath - Update the path in the report file.
3136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
3146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub UpdateInFilePath {
3166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $fname = shift;
3176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $regex = shift;
3186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $newtext = shift;
3196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  open (RIN, $fname) or die "cannot open $fname";
3216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp";
3226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  while (<RIN>) {
3246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    s/$regex/$newtext/;
3256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print ROUT $_;
3266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
3276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  close (ROUT);
3296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  close (RIN);
3306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  rename("$fname.tmp", $fname)
3316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
3326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
3346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# AddStatLine - Decode and insert a statistics line into the database.
3356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
3366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub AddStatLine {
3386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Line  = shift;
3396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Stats = shift;
3406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $File  = shift;
3416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  print $Line . "\n";
3436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Regex = qr/(.*?)\ ->\ Total\ CFGBlocks:\ (\d+)\ \|\ Unreachable
3456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      \ CFGBlocks:\ (\d+)\ \|\ Exhausted\ Block:\ (yes|no)\ \|\ Empty\ WorkList:
3466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      \ (yes|no)/x;
3476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Line !~ $Regex) {
3496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    return;
3506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
3516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Create a hash of the interesting fields
3536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Row = {
3546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Filename    => $File,
3556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Function    => $1,
3566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Total       => $2,
3576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Unreachable => $3,
3586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Aborted     => $4,
3596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Empty       => $5
3606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  };
3616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Add them to the stats array
3636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  push @$Stats, $Row;
3646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
3656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
3676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# ScanFile - Scan a report file for various identifying attributes.
3686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
3696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Sometimes a source file is scanned more than once, and thus produces
3716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# multiple error reports.  We use a cache to solve this problem.
3726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy %AlreadyScanned;
3746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub ScanFile {
3766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Index = shift;
3786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Dir = shift;
3796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $FName = shift;
3806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Stats = shift;
3816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Compute a digest for the report file.  Determine if we have already
3836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # scanned a file that looks just like it.
3846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $digest = ComputeDigest("$Dir/$FName");
3866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (defined $AlreadyScanned{$digest}) {
3886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # Redundant file.  Remove it.
3896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    unlink("$Dir/$FName");
3906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    return;
3916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
3926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $AlreadyScanned{$digest} = 1;
3946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # At this point the report file is not world readable.  Make it happen.
3966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  chmod(0644, "$Dir/$FName");
3976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
3986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Scan the report file for tags.
3996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n");
4006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $BugType        = "";
4026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $BugFile        = "";
4036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $BugFunction    = "";
4046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $BugCategory    = "";
4056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $BugDescription = "";
4066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $BugPathLength  = 1;
4076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $BugLine        = 0;
4086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  while (<IN>) {
4106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    last if (/<!-- BUGMETAEND -->/);
4116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (/<!-- BUGTYPE (.*) -->$/) {
4136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $BugType = $1;
4146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
4156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    elsif (/<!-- BUGFILE (.*) -->$/) {
4166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $BugFile = abs_path($1);
4176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (!defined $BugFile) {
4186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker         # The file no longer exists: use the original path.
4196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker         $BugFile = $1;
4206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
4216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      UpdatePrefix($BugFile);
4226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
4236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    elsif (/<!-- BUGPATHLENGTH (.*) -->$/) {
4246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $BugPathLength = $1;
4256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
4266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    elsif (/<!-- BUGLINE (.*) -->$/) {
4276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $BugLine = $1;
4286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
4296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    elsif (/<!-- BUGCATEGORY (.*) -->$/) {
4306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $BugCategory = $1;
4316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
4326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    elsif (/<!-- BUGDESC (.*) -->$/) {
4336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $BugDescription = $1;
4346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
4356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    elsif (/<!-- FUNCTIONNAME (.*) -->$/) {
4366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $BugFunction = $1;
4376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
4386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
4406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  close(IN);
4436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (!defined $BugCategory) {
4456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $BugCategory = "Other";
4466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
4476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Don't add internal statistics to the bug reports
4496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($BugCategory =~ /statistics/i) {
4506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    AddStatLine($BugDescription, $Stats, $BugFile);
4516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    return;
4526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
4536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  push @$Index,[ $FName, $BugCategory, $BugType, $BugFile, $BugFunction, $BugLine,
4556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                 $BugPathLength ];
4566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
4576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
4596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# CopyFiles - Copy resource files to target directory.
4606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
4616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub CopyFiles {
4636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Dir = shift;
4656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $JS = Cwd::realpath("$RealBin/../share/scan-build/sorttable.js");
4676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  DieDiag("Cannot find 'sorttable.js'.\n")
4696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (! -r $JS);
4706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  copy($JS, "$Dir");
4726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n")
4746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (! -r "$Dir/sorttable.js");
4756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $CSS = Cwd::realpath("$RealBin/../share/scan-build/scanview.css");
4776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  DieDiag("Cannot find 'scanview.css'.\n")
4796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (! -r $CSS);
4806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  copy($CSS, "$Dir");
4826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  DieDiag("Could not copy 'scanview.css' to '$Dir'.\n")
4846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (! -r $CSS);
4856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
4866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
4886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# CalcStats - Calculates visitation statistics and returns the string.
4896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
4906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub CalcStats {
4926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Stats = shift;
4936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
4946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $TotalBlocks = 0;
4956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $UnreachedBlocks = 0;
4966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $TotalFunctions = scalar(@$Stats);
4976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $BlockAborted = 0;
4986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $WorkListAborted = 0;
4996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Aborted = 0;
5006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Calculate the unique files
5026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $FilesHash = {};
5036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  foreach my $Row (@$Stats) {
5056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $FilesHash->{$Row->{Filename}} = 1;
5066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $TotalBlocks += $Row->{Total};
5076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $UnreachedBlocks += $Row->{Unreachable};
5086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $BlockAborted++ if $Row->{Aborted} eq 'yes';
5096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $WorkListAborted++ if $Row->{Empty} eq 'no';
5106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $Aborted++ if $Row->{Aborted} eq 'yes' || $Row->{Empty} eq 'no';
5116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
5126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $TotalFiles = scalar(keys(%$FilesHash));
5146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Calculations
5166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $PercentAborted = sprintf("%.2f", $Aborted / $TotalFunctions * 100);
5176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $PercentBlockAborted = sprintf("%.2f", $BlockAborted / $TotalFunctions
5186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      * 100);
5196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $PercentWorkListAborted = sprintf("%.2f", $WorkListAborted /
5206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $TotalFunctions * 100);
5216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $PercentBlocksUnreached = sprintf("%.2f", $UnreachedBlocks / $TotalBlocks
5226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      * 100);
5236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $StatsString = "Analyzed $TotalBlocks blocks in $TotalFunctions functions"
5256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    . " in $TotalFiles files\n"
5266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    . "$Aborted functions aborted early ($PercentAborted%)\n"
5276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    . "$BlockAborted had aborted blocks ($PercentBlockAborted%)\n"
5286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    . "$WorkListAborted had unfinished worklists ($PercentWorkListAborted%)\n"
5296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    . "$UnreachedBlocks blocks were never reached ($PercentBlocksUnreached%)\n";
5306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return $StatsString;
5326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
5336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
5356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Postprocess - Postprocess the results of an analysis scan.
5366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
5376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy @filesFound;
5396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $baseDir;
5406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub FileWanted {
5416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $baseDirRegEx = quotemeta $baseDir;
5426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $file = $File::Find::name;
5436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # The name of the file is generated by clang binary (HTMLDiagnostics.cpp)
5456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($file =~ /report-.*\.html$/) {
5466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker       my $relative_file = $file;
5476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker       $relative_file =~ s/$baseDirRegEx//g;
5486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker       push @filesFound, $relative_file;
5496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
5506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
5516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub Postprocess {
5536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Dir           = shift;
5556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $BaseDir       = shift;
5566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $AnalyzerStats = shift;
5576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $KeepEmpty     = shift;
5586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  die "No directory specified." if (!defined $Dir);
5606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (! -d $Dir) {
5626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Diag("No bugs found.\n");
5636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    return 0;
5646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
5656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $baseDir = $Dir . "/";
5676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  find({ wanted => \&FileWanted, follow => 0}, $Dir);
5686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (scalar(@filesFound) == 0 and ! -e "$Dir/failures") {
5706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (! $KeepEmpty) {
5716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      Diag("Removing directory '$Dir' because it contains no reports.\n");
5726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      rmtree($Dir) or die "Cannot rmtree '$Dir' : $!";
5736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
5746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Diag("No bugs found.\n");
5756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    return 0;
5766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
5776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Scan each report file and build an index.
5796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my @Index;
5806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my @Stats;
5816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  foreach my $file (@filesFound) { ScanFile(\@Index, $Dir, $file, \@Stats); }
5826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
5836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Scan the failures directory and use the information in the .info files
5846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # to update the common prefix directory.
5856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my @failures;
5866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my @attributes_ignored;
5876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (-d "$Dir/failures") {
5886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    opendir(DIR, "$Dir/failures");
5896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    @failures = grep { /[.]info.txt$/ && !/attribute_ignored/; } readdir(DIR);
5906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    closedir(DIR);
5916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    opendir(DIR, "$Dir/failures");
5926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    @attributes_ignored = grep { /^attribute_ignored/; } readdir(DIR);
5936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    closedir(DIR);
5946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    foreach my $file (@failures) {
5956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      open IN, "$Dir/failures/$file" or DieDiag("cannot open $file\n");
5966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $Path = <IN>;
5976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (defined $Path) { UpdatePrefix($Path); }
5986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      close IN;
5996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
6006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
6016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Generate an index.html file.
6036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $FName = "$Dir/index.html";
6046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n");
6056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Print out the header.
6076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerprint OUT <<ENDTEXT;
6096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<html>
6106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<head>
6116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<title>${Options{HtmlTitle}}</title>
6126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<link type="text/css" rel="stylesheet" href="scanview.css"/>
6136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<script src="sorttable.js"></script>
6146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<script language='javascript' type="text/javascript">
6156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerfunction SetDisplay(RowClass, DisplayVal)
6166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker{
6176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  var Rows = document.getElementsByTagName("tr");
6186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  for ( var i = 0 ; i < Rows.length; ++i ) {
6196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (Rows[i].className == RowClass) {
6206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      Rows[i].style.display = DisplayVal;
6216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
6226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
6236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
6246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerfunction CopyCheckedStateToCheckButtons(SummaryCheckButton) {
6266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  var Inputs = document.getElementsByTagName("input");
6276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  for ( var i = 0 ; i < Inputs.length; ++i ) {
6286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (Inputs[i].type == "checkbox") {
6296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if(Inputs[i] != SummaryCheckButton) {
6306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        Inputs[i].checked = SummaryCheckButton.checked;
6316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        Inputs[i].onclick();
6326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
6336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
6346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
6356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
6366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerfunction returnObjById( id ) {
6386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (document.getElementById)
6396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        var returnVar = document.getElementById(id);
6406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    else if (document.all)
6416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        var returnVar = document.all[id];
6426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    else if (document.layers)
6436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        var returnVar = document.layers[id];
6446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    return returnVar;
6456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
6466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickervar NumUnchecked = 0;
6486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerfunction ToggleDisplay(CheckButton, ClassName) {
6506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (CheckButton.checked) {
6516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    SetDisplay(ClassName, "");
6526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (--NumUnchecked == 0) {
6536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      returnObjById("AllBugsCheck").checked = true;
6546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
6556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
6566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  else {
6576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    SetDisplay(ClassName, "none");
6586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    NumUnchecked++;
6596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    returnObjById("AllBugsCheck").checked = false;
6606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
6616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
6626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker</script>
6636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<!-- SUMMARYENDHEAD -->
6646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker</head>
6656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<body>
6666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<h1>${Options{HtmlTitle}}</h1>
6676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<table>
6696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<tr><th>User:</th><td>${UserName}\@${HostName}</td></tr>
6706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<tr><th>Working Directory:</th><td>${CurrentDir}</td></tr>
6716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<tr><th>Command Line:</th><td>${CmdArgs}</td></tr>
6726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<tr><th>Clang Version:</th><td>${ClangVersion}</td></tr>
6736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<tr><th>Date:</th><td>${Date}</td></tr>
6746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerENDTEXT
6756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerprint OUT "<tr><th>Version:</th><td>${BuildName} (${BuildDate})</td></tr>\n"
6776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (defined($BuildName) && defined($BuildDate));
6786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerprint OUT <<ENDTEXT;
6806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker</table>
6816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerENDTEXT
6826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (scalar(@filesFound)) {
6846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # Print out the summary table.
6856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my %Totals;
6866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    for my $row ( @Index ) {
6886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $bug_type = ($row->[2]);
6896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $bug_category = ($row->[1]);
6906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $key = "$bug_category:$bug_type";
6916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (!defined $Totals{$key}) { $Totals{$key} = [1,$bug_category,$bug_type]; }
6936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      else { $Totals{$key}->[0]++; }
6946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
6956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print OUT "<h2>Bug Summary</h2>";
6976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
6986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (defined $BuildName) {
6996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n"
7006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
7016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $TotalBugs = scalar(@Index);
7036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerprint OUT <<ENDTEXT;
7046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<table>
7056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<thead><tr><td>Bug Type</td><td>Quantity</td><td class="sorttable_nosort">Display?</td></tr></thead>
7066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<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>
7076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerENDTEXT
7086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $last_category;
7106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    for my $key (
7126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      sort {
7136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $x = $Totals{$a};
7146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $y = $Totals{$b};
7156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $res = $x->[1] cmp $y->[1];
7166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $res = $x->[2] cmp $y->[2] if ($res == 0);
7176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $res
7186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      } keys %Totals )
7196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    {
7206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $val = $Totals{$key};
7216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $category = $val->[1];
7226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (!defined $last_category or $last_category ne $category) {
7236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $last_category = $category;
7246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        print OUT "<tr><th>$category</th><th colspan=2></th></tr>\n";
7256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
7266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $x = lc $key;
7276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $x =~ s/[ ,'":\/()]+/_/g;
7286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<tr><td class=\"SUMM_DESC\">";
7296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT $val->[2];
7306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "</td><td class=\"Q\">";
7316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT $val->[0];
7326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "</td><td><center><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></center></td></tr>\n";
7336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
7346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Print out the table of errors.
7366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerprint OUT <<ENDTEXT;
7386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker</table>
7396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<h2>Reports</h2>
7406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<table class="sortable" style="table-layout:automatic">
7426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<thead><tr>
7436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  <td>Bug Group</td>
7446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  <td class="sorttable_sorted">Bug Type<span id="sorttable_sortfwdind">&nbsp;&#x25BE;</span></td>
7456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  <td>File</td>
7466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  <td>Function/Method</td>
7476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  <td class="Q">Line</td>
7486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  <td class="Q">Path Length</td>
7496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  <td class="sorttable_nosort"></td>
7506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  <!-- REPORTBUGCOL -->
7516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker</tr></thead>
7526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker<tbody>
7536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerENDTEXT
7546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $prefix = GetPrefix();
7566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $regex;
7576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $InFileRegex;
7586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $InFilePrefix = "File:</td><td>";
7596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (defined $prefix) {
7616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $regex = qr/^\Q$prefix\E/is;
7626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is;
7636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
7646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    for my $row ( sort { $a->[2] cmp $b->[2] } @Index ) {
7666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $x = "$row->[1]:$row->[2]";
7676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $x = lc $x;
7686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $x =~ s/[ ,'":\/()]+/_/g;
7696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $ReportFile = $row->[0];
7716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<tr class=\"bt_$x\">";
7736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<td class=\"DESC\">";
7746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT $row->[1];
7756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "</td>";
7766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<td class=\"DESC\">";
7776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT $row->[2];
7786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "</td>";
7796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # Update the file prefix.
7816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $fname = $row->[3];
7826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (defined $regex) {
7846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $fname =~ s/$regex//;
7856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix)
7866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
7876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
7886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<td>";
7896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my @fname = split /\//,$fname;
7906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if ($#fname > 0) {
7916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        while ($#fname >= 0) {
7926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          my $x = shift @fname;
7936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          print OUT $x;
7946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          if ($#fname >= 0) {
7956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker            print OUT "/";
7966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          }
7976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
7986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
7996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      else {
8006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        print OUT $fname;
8016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
8026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "</td>";
8036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<td class=\"DESC\">";
8056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT $row->[4];
8066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "</td>";
8076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # Print out the quantities.
8096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      for my $j ( 5 .. 6 ) {
8106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        print OUT "<td class=\"Q\">$row->[$j]</td>";
8116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
8126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # Print the rest of the columns.
8146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      for (my $j = 7; $j <= $#{$row}; ++$j) {
8156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        print OUT "<td>$row->[$j]</td>"
8166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
8176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # Emit the "View" link.
8196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<td><a href=\"$ReportFile#EndPath\">View Report</a></td>";
8206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # Emit REPORTBUG markers.
8226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "\n<!-- REPORTBUG id=\"$ReportFile\" -->\n";
8236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # End the row.
8256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "</tr>\n";
8266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
8276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print OUT "</tbody>\n</table>\n\n";
8296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
8306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (scalar (@failures) || scalar(@attributes_ignored)) {
8326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print OUT "<h2>Analyzer Failures</h2>\n";
8336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (scalar @attributes_ignored) {
8356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "The analyzer's parser ignored the following attributes:<p>\n";
8366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<table>\n";
8376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<thead><tr><td>Attribute</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>\n";
8386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      foreach my $file (sort @attributes_ignored) {
8396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        die "cannot demangle attribute name\n" if (! ($file =~ /^attribute_ignored_(.+).txt/));
8406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $attribute = $1;
8416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        # Open the attribute file to get the first file that failed.
8426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        next if (!open (ATTR, "$Dir/failures/$file"));
8436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $ppfile = <ATTR>;
8446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        chomp $ppfile;
8456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        close ATTR;
8466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        next if (! -e "$Dir/failures/$ppfile");
8476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        # Open the info file and get the name of the source file.
8486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        open (INFO, "$Dir/failures/$ppfile.info.txt") or
8496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          die "Cannot open $Dir/failures/$ppfile.info.txt\n";
8506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $srcfile = <INFO>;
8516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        chomp $srcfile;
8526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        close (INFO);
8536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        # Print the information in the table.
8546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $prefix = GetPrefix();
8556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; }
8566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        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";
8576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $ppfile_clang = $ppfile;
8586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $ppfile_clang =~ s/[.](.+)$/.clang.$1/;
8596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        print OUT "  <!-- REPORTPROBLEM src=\"$srcfile\" file=\"failures/$ppfile\" clangfile=\"failures/$ppfile_clang\" stderr=\"failures/$ppfile.stderr.txt\" info=\"failures/$ppfile.info.txt\" -->\n";
8606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
8616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "</table>\n";
8626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
8636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (scalar @failures) {
8656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<p>The analyzer had problems processing the following files:</p>\n";
8666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<table>\n";
8676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "<thead><tr><td>Problem</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>\n";
8686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      foreach my $file (sort @failures) {
8696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $file =~ /(.+).info.txt$/;
8706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        # Get the preprocessed file.
8716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $ppfile = $1;
8726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        # Open the info file and get the name of the source file.
8736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        open (INFO, "$Dir/failures/$file") or
8746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          die "Cannot open $Dir/failures/$file\n";
8756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $srcfile = <INFO>;
8766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        chomp $srcfile;
8776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $problem = <INFO>;
8786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        chomp $problem;
8796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        close (INFO);
8806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        # Print the information in the table.
8816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $prefix = GetPrefix();
8826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; }
8836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        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";
8846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        my $ppfile_clang = $ppfile;
8856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $ppfile_clang =~ s/[.](.+)$/.clang.$1/;
8866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        print OUT "  <!-- REPORTPROBLEM src=\"$srcfile\" file=\"failures/$ppfile\" clangfile=\"failures/$ppfile_clang\" stderr=\"failures/$ppfile.stderr.txt\" info=\"failures/$ppfile.info.txt\" -->\n";
8876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
8886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print OUT "</table>\n";
8896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
8906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    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";
8916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
8926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  print OUT "</body></html>\n";
8946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  close(OUT);
8956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  CopyFiles($Dir);
8966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
8976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Make sure $Dir and $BaseDir are world readable/executable.
8986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  chmod(0755, $Dir);
8996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (defined $BaseDir) { chmod(0755, $BaseDir); }
9006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Print statistics
9026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  print CalcStats(\@Stats) if $AnalyzerStats;
9036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Num = scalar(@Index);
9056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Num == 1) {
9066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Diag("$Num bug found.\n");
9076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  } else {
9086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Diag("$Num bugs found.\n");
9096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
9106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Num > 0 && -r "$Dir/index.html") {
9116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Diag("Run 'scan-view $Dir' to examine bug reports.\n");
9126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
9136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  DiagCrashes($Dir) if (scalar @failures || scalar @attributes_ignored);
9156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return $Num;
9176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
9186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
9206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# RunBuildCommand - Run the build command.
9216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
9226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub AddIfNotPresent {
9246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Args = shift;
9256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Arg = shift;
9266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $found = 0;
9276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  foreach my $k (@$Args) {
9296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($k eq $Arg) {
9306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $found = 1;
9316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      last;
9326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
9336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
9346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($found == 0) {
9366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    push @$Args, $Arg;
9376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
9386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
9396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub SetEnv {
9416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $EnvVars = shift @_;
9426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  foreach my $var ('CC', 'CXX', 'CLANG', 'CLANG_CXX',
9436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                   'CCC_ANALYZER_ANALYSIS', 'CCC_ANALYZER_PLUGINS',
9446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                   'CCC_ANALYZER_CONFIG') {
9456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    die "$var is undefined\n" if (!defined $var);
9466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $ENV{$var} = $EnvVars->{$var};
9476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
9486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  foreach my $var ('CCC_ANALYZER_STORE_MODEL',
9496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                   'CCC_ANALYZER_CONSTRAINTS_MODEL',
9506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                   'CCC_ANALYZER_INTERNAL_STATS',
9516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                   'CCC_ANALYZER_OUTPUT_FORMAT',
9526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                   'CCC_CC',
9536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                   'CCC_CXX',
9546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                   'CCC_REPORT_FAILURES',
9556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                   'CLANG_ANALYZER_TARGET',
9566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                   'CCC_ANALYZER_FORCE_ANALYZE_DEBUG_CODE') {
9576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $x = $EnvVars->{$var};
9586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (defined $x) { $ENV{$var} = $x }
9596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
9606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Verbose = $EnvVars->{'VERBOSE'};
9616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Verbose >= 2) {
9626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $ENV{'CCC_ANALYZER_VERBOSE'} = 1;
9636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
9646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Verbose >= 3) {
9656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $ENV{'CCC_ANALYZER_LOG'} = 1;
9666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
9676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
9686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub RunXcodebuild {
9706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Args = shift;
9716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $IgnoreErrors = shift;
9726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $CCAnalyzer = shift;
9736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $CXXAnalyzer = shift;
9746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $EnvVars = shift;
9756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($IgnoreErrors) {
9776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES");
9786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
9796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Detect the version of Xcode.  If Xcode 4.6 or higher, use new
9816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # in situ support for analyzer interposition without needed to override
9826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # the compiler.
9836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  open(DETECT_XCODE, "-|", $Args->[0], "-version") or
9846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    die "error: cannot detect version of xcodebuild\n";
9856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $oldBehavior = 1;
9876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
9886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  while(<DETECT_XCODE>) {
9896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (/^Xcode (.+)$/) {
9906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $ver = $1;
9916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if ($ver =~ /^([0-9]+[.][0-9]+)[^0-9]?/) {
9926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if ($1 >= 4.6) {
9936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          $oldBehavior = 0;
9946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          last;
9956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
9966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
9976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
9986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
9996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  close(DETECT_XCODE);
10006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # If --override-compiler is explicitely requested, resort to the old
10026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # behavior regardless of Xcode version.
10036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Options{OverrideCompiler}) {
10046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $oldBehavior = 1;
10056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
10066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($oldBehavior == 0) {
10086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $OutputDir = $EnvVars->{"OUTPUT_DIR"};
10096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $CLANG = $EnvVars->{"CLANG"};
10106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $OtherFlags = $EnvVars->{"CCC_ANALYZER_ANALYSIS"};
10116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    push @$Args,
10126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        "RUN_CLANG_STATIC_ANALYZER=YES",
10136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        "CLANG_ANALYZER_OUTPUT=plist-html",
10146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        "CLANG_ANALYZER_EXEC=$CLANG",
10156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        "CLANG_ANALYZER_OUTPUT_DIR=$OutputDir",
10166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        "CLANG_ANALYZER_OTHER_FLAGS=$OtherFlags";
10176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    return (system(@$Args) >> 8);
10196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
10206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Default to old behavior where we insert a bogus compiler.
10226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  SetEnv($EnvVars);
10236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Check if using iPhone SDK 3.0 (simulator).  If so the compiler being
10256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # used should be gcc-4.2.
10266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (!defined $ENV{"CCC_CC"}) {
10276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    for (my $i = 0 ; $i < scalar(@$Args); ++$i) {
10286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if ($Args->[$i] eq "-sdk" && $i + 1 < scalar(@$Args)) {
10296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if (@$Args[$i+1] =~ /^iphonesimulator3/) {
10306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          $ENV{"CCC_CC"} = "gcc-4.2";
10316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          $ENV{"CCC_CXX"} = "g++-4.2";
10326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
10336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
10346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
10356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
10366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Disable PCH files until clang supports them.
10386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO");
10396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # When 'CC' is set, xcodebuild uses it to do all linking, even if we are
10416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # linking C++ object files.  Set 'LDPLUSPLUS' so that xcodebuild uses 'g++'
10426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # (via c++-analyzer) when linking such files.
10436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $ENV{"LDPLUSPLUS"} = $CXXAnalyzer;
10446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return (system(@$Args) >> 8);
10466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
10476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub RunBuildCommand {
10496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Args = shift;
10506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $IgnoreErrors = shift;
10516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Cmd = $Args->[0];
10526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $CCAnalyzer = shift;
10536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $CXXAnalyzer = shift;
10546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $EnvVars = shift;
10556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Cmd =~ /\bxcodebuild$/) {
10576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    return RunXcodebuild($Args, $IgnoreErrors, $CCAnalyzer, $CXXAnalyzer, $EnvVars);
10586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
10596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Setup the environment.
10616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  SetEnv($EnvVars);
10626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Cmd =~ /(.*\/?gcc[^\/]*$)/ or
10646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Cmd =~ /(.*\/?cc[^\/]*$)/ or
10656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Cmd =~ /(.*\/?llvm-gcc[^\/]*$)/ or
10666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Cmd =~ /(.*\/?clang$)/ or
10676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Cmd =~ /(.*\/?ccc-analyzer[^\/]*$)/) {
10686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (!($Cmd =~ /ccc-analyzer/) and !defined $ENV{"CCC_CC"}) {
10706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $ENV{"CCC_CC"} = $1;
10716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
10726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    shift @$Args;
10746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    unshift @$Args, $CCAnalyzer;
10756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
10766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  elsif ($Cmd =~ /(.*\/?g\+\+[^\/]*$)/ or
10776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $Cmd =~ /(.*\/?c\+\+[^\/]*$)/ or
10786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $Cmd =~ /(.*\/?llvm-g\+\+[^\/]*$)/ or
10796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $Cmd =~ /(.*\/?clang\+\+$)/ or
10806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $Cmd =~ /(.*\/?c\+\+-analyzer[^\/]*$)/) {
10816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (!($Cmd =~ /c\+\+-analyzer/) and !defined $ENV{"CCC_CXX"}) {
10826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $ENV{"CCC_CXX"} = $1;
10836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
10846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    shift @$Args;
10856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    unshift @$Args, $CXXAnalyzer;
10866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
10876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  elsif ($Cmd eq "make" or $Cmd eq "gmake" or $Cmd eq "mingw32-make") {
10886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    AddIfNotPresent($Args, "CC=$CCAnalyzer");
10896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    AddIfNotPresent($Args, "CXX=$CXXAnalyzer");
10906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($IgnoreErrors) {
10916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      AddIfNotPresent($Args,"-k");
10926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      AddIfNotPresent($Args,"-i");
10936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
10946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
10956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return (system(@$Args) >> 8);
10976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
10986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
10996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
11006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# DisplayHelp - Utility function to display all help options.
11016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
11026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub DisplayHelp {
11046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $ArgClangNotFoundErrMsg = shift;
11066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerprint <<ENDTEXT;
11076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerUSAGE: $Prog [options] <build command> [build options]
11086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerENDTEXT
11106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (defined $BuildName) {
11126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n";
11136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
11146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerprint <<ENDTEXT;
11166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerOPTIONS:
11176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -analyze-headers
11196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Also analyze functions in #included files.  By default, such functions
11216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   are skipped unless they are called by functions within the main source file.
11226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --force-analyze-debug-code
11246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Tells analyzer to enable assertions in code even if they were disabled
11266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   during compilation to enable more precise results.
11276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -o <output location>
11296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Specifies the output directory for analyzer reports. Subdirectories will be
11316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   created as needed to represent separate "runs" of the analyzer. If this
11326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   option is not specified, a directory is created in /tmp (TMPDIR on Mac OS X)
11336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   to store the reports.
11346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -h
11366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --help
11376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Display this message.
11396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -k
11416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --keep-going
11426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Add a "keep on going" option to the specified build command. This option
11446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   currently supports make and xcodebuild. This is a convenience option; one
11456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   can specify this behavior directly using build options.
11466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --html-title [title]
11486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --html-title=[title]
11496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Specify the title used on generated HTML pages. If not specified, a default
11516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   title will be used.
11526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -plist
11546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   By default the output of scan-build is a set of HTML files. This option
11566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   outputs the results as a set of .plist files.
11576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -plist-html
11596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   By default the output of scan-build is a set of HTML files. This option
11616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   outputs the results as a set of HTML and .plist files.
11626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --status-bugs
11646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   By default, the exit status of scan-build is the same as the executed build
11666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   command. Specifying this option causes the exit status of scan-build to be 1
11676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   if it found potential bugs and 0 otherwise.
11686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --use-cc [compiler path]
11706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --use-cc=[compiler path]
11716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   scan-build analyzes a project by interposing a "fake compiler", which
11736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   executes a real compiler for compilation and the static analyzer for analysis.
11746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Because of the current implementation of interposition, scan-build does not
11756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   know what compiler your project normally uses.  Instead, it simply overrides
11766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   the CC environment variable, and guesses your default compiler.
11776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   In the future, this interposition mechanism to be improved, but if you need
11796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   scan-build to use a specific compiler for *compilation* then you can use
11806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   this option to specify a path to that compiler.
11816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   If the given compiler is a cross compiler, you may also need to provide
11836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   --analyzer-target option to properly analyze the source code because static
11846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   analyzer runs as if the code is compiled for the host machine by default.
11856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --use-c++ [compiler path]
11876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --use-c++=[compiler path]
11886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   This is the same as "--use-cc" but for C++ code.
11906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --analyzer-target [target triple name for analysis]
11926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --analyzer-target=[target triple name for analysis]
11936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   This provides target triple information to clang static analyzer.
11956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   It only changes the target for analysis but doesn't change the target of a
11966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   real compiler given by --use-cc and --use-c++ options.
11976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
11986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -v
11996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Enable verbose output from scan-build. A second and third '-v' increases
12016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   verbosity.
12026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -V
12046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --view
12056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   View analysis results in a web browser when the build completes.
12076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerADVANCED OPTIONS:
12096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -no-failure-reports
12116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Do not create a 'failures' subdirectory that includes analyzer crash reports
12136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   and preprocessed source files.
12146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -stats
12166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Generates visitation statistics for the project being analyzed.
12186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -maxloop <loop count>
12206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Specifiy the number of times a block can be visited before giving up.
12226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Default is 4. Increase for more comprehensive coverage at a cost of speed.
12236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -internal-stats
12256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Generate internal analyzer statistics.
12276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --use-analyzer [Xcode|path to clang]
12296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --use-analyzer=[Xcode|path to clang]
12306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   scan-build uses the 'clang' executable relative to itself for static
12326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   analysis. One can override this behavior with this option by using the
12336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   'clang' packaged with Xcode (on OS X) or from the PATH.
12346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --keep-empty
12366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Don't remove the build results directory even if no issues were reported.
12386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker --override-compiler
12406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Always resort to the ccc-analyzer even when better interposition methods
12416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   are available.
12426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -analyzer-config <options>
12446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Provide options to pass through to the analyzer's -analyzer-config flag.
12466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Several options are separated with comma: 'key1=val1,key2=val2'
12476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker   Available options:
12496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker     * stable-report-filename=true or false (default)
12506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker       Switch the page naming to:
12516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker       report-<filename>-<function/method name>-<id>.html
12526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker       instead of report-XXXXXX.html
12536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerCONTROLLING CHECKERS:
12556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker A default group of checkers are always run unless explicitly disabled.
12576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker Checkers may be enabled/disabled using the following options:
12586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -enable-checker [checker name]
12606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -disable-checker [checker name]
12616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerLOADING CHECKERS:
12636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker Loading external checkers using the clang plugin interface:
12656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker -load-plugin [plugin library]
12676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerENDTEXT
12686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (defined $Clang && -x $Clang) {
12706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # Query clang for list of checkers that are enabled.
12716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # create a list to load the plugins via the 'Xclang' command line
12736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # argument
12746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my @PluginLoadCommandline_xclang;
12756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    foreach my $param ( @{$Options{PluginsToLoad}} ) {
12766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      push ( @PluginLoadCommandline_xclang, "-Xclang" );
12776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      push ( @PluginLoadCommandline_xclang, "-load" );
12786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      push ( @PluginLoadCommandline_xclang, "-Xclang" );
12796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      push ( @PluginLoadCommandline_xclang, $param );
12806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
12816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my %EnabledCheckers;
12836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    foreach my $lang ("c", "objective-c", "objective-c++", "c++") {
12846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $ExecLine = join(' ', qq/"$Clang"/, @PluginLoadCommandline_xclang, "--analyze", "-x", $lang, "-", "-###", "2>&1", "|");
12856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      open(PS, $ExecLine);
12866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      while (<PS>) {
12876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        foreach my $val (split /\s+/) {
12886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          $val =~ s/\"//g;
12896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          if ($val =~ /-analyzer-checker\=([^\s]+)/) {
12906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker            $EnabledCheckers{$1} = 1;
12916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          }
12926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
12936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
12946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
12956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
12966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # Query clang for complete list of checkers.
12976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my @PluginLoadCommandline;
12986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    foreach my $param ( @{$Options{PluginsToLoad}} ) {
12996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      push ( @PluginLoadCommandline, "-load" );
13006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      push ( @PluginLoadCommandline, $param );
13016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
13026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $ExecLine = join(' ', qq/"$Clang"/, "-cc1", @PluginLoadCommandline, "-analyzer-checker-help", "2>&1", "|");
13046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    open(PS, $ExecLine);
13056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $foundCheckers = 0;
13066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    while (<PS>) {
13076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (/CHECKERS:/) {
13086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $foundCheckers = 1;
13096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        last;
13106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
13116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
13126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (!$foundCheckers) {
13136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print "  *** Could not query Clang for the list of available checkers.";
13146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
13156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    else {
13166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print("\nAVAILABLE CHECKERS:\n\n");
13176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $skip = 0;
13186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker       while(<PS>) {
13196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if (/experimental/) {
13206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          $skip = 1;
13216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          next;
13226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
13236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if ($skip) {
13246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          next if (!/^\s\s[^\s]/);
13256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          $skip = 0;
13266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
13276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        s/^\s\s//;
13286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if (/^([^\s]+)/) {
13296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          # Is the checker enabled?
13306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          my $checker = $1;
13316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          my $enabled = 0;
13326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          my $aggregate = "";
13336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          foreach my $domain (split /\./, $checker) {
13346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker            $aggregate .= $domain;
13356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker            if ($EnabledCheckers{$aggregate}) {
13366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker              $enabled =1;
13376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker              last;
13386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker            }
13396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker            # append a dot, if an additional domain is added in the next iteration
13406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker            $aggregate .= ".";
13416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          }
13426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          if ($enabled) {
13446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker            print " + ";
13456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          }
13466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          else {
13476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker            print "   ";
13486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          }
13496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
13506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        else {
13516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          print "   ";
13526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
13536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        print $_;
13546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
13556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n";
13566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
13576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    close PS;
13586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
13596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  else {
13606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    print "  *** Could not query Clang for the list of available checkers.\n";
13616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (defined  $ArgClangNotFoundErrMsg) {
13626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      print "  *** Reason: $ArgClangNotFoundErrMsg\n";
13636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
13646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
13656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerprint <<ENDTEXT
13676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerBUILD OPTIONS
13696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker You can specify any build option acceptable to the build command.
13716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerEXAMPLE
13736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker scan-build -o /tmp/myhtmldir make -j4
13756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerThe above example causes analysis reports to be deposited into a subdirectory
13776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerof "/tmp/myhtmldir" and to run "make" with the "-j4" option. A different
13786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersubdirectory is created each time scan-build analyzes a project. The analyzer
13796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickershould support most parallel builds, but not distributed builds.
13806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerENDTEXT
13826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
13836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
13856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# HtmlEscape - HTML entity encode characters that are special in HTML
13866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
13876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub HtmlEscape {
13896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # copy argument to new variable so we don't clobber the original
13906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $arg = shift || '';
13916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $tmp = $arg;
13926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $tmp =~ s/&/&amp;/g;
13936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $tmp =~ s/</&lt;/g;
13946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $tmp =~ s/>/&gt;/g;
13956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return $tmp;
13966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
13976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
13986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
13996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# ShellEscape - backslash escape characters that are special to the shell
14006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
14016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub ShellEscape {
14036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # copy argument to new variable so we don't clobber the original
14046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $arg = shift || '';
14056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($arg =~ /["\s]/) { return "'" . $arg . "'"; }
14066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return $arg;
14076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
14086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
14106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# FindClang - searches for 'clang' executable.
14116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
14126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub FindClang {
14146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if (!defined $Options{AnalyzerDiscoveryMethod}) {
14156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $Clang = Cwd::realpath("$RealBin/bin/clang") if (-f "$RealBin/bin/clang");
14166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (!defined $Clang || ! -x $Clang) {
14176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Clang = Cwd::realpath("$RealBin/clang") if (-f "$RealBin/clang");
14186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
14196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if (!defined $Clang || ! -x $Clang) {
14206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      return "error: Cannot find an executable 'clang' relative to" .
14216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker             " scan-build. Consider using --use-analyzer to pick a version of" .
14226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker             " 'clang' to use for static analysis.\n";
14236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
14246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
14256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  else {
14266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($Options{AnalyzerDiscoveryMethod} =~ /^[Xx]code$/) {
14276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $xcrun = `which xcrun`;
14286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      chomp $xcrun;
14296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if ($xcrun eq "") {
14306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        return "Cannot find 'xcrun' to find 'clang' for analysis.\n";
14316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
14326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Clang = `$xcrun -toolchain XcodeDefault -find clang`;
14336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      chomp $Clang;
14346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if ($Clang eq "") {
14356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        return "No 'clang' executable found by 'xcrun'\n";
14366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
14376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
14386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    else {
14396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Clang = $Options{AnalyzerDiscoveryMethod};
14406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (!defined $Clang or not -x $Clang) {
14416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        return "Cannot find an executable clang at '$Options{AnalyzerDiscoveryMethod}'\n";
14426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
14436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
14446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
14456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return undef;
14466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
14476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
14496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Process command-line arguments.
14506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker##----------------------------------------------------------------------------##
14516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $RequestDisplayHelp = 0;
14536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $ForceDisplayHelp = 0;
14546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickersub ProcessArgs {
14566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $Args = shift;
14576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $NumArgs = 0;
14586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  while (@$Args) {
14606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $NumArgs++;
14626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # Scan for options we recognize.
14646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $arg = $Args->[0];
14666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-h" or $arg eq "--help") {
14686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $RequestDisplayHelp = 1;
14696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
14706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
14716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
14726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq '-analyze-headers') {
14746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
14756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{AnalyzeHeaders} = 1;
14766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
14776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
14786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-o") {
14806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
14816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (!@$Args) {
14836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        DieDiag("'-o' option requires a target directory name.\n");
14846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
14856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # Construct an absolute path.  Uses the current working directory
14876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # as a base if the original path was not absolute.
14886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $OutDir = shift @$Args;
14896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      mkpath($OutDir) unless (-e $OutDir);  # abs_path wants existing dir
14906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{OutputDir} = abs_path($OutDir);
14916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
14936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
14946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg =~ /^--html-title(=(.+))?$/) {
14966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
14976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
14986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (!defined $2 || $2 eq '') {
14996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if (!@$Args) {
15006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          DieDiag("'--html-title' option requires a string.\n");
15016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
15026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $Options{HtmlTitle} = shift @$Args;
15046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      } else {
15056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $Options{HtmlTitle} = $2;
15066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
15076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
15096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
15106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-k" or $arg eq "--keep-going") {
15126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
15136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{IgnoreErrors} = 1;
15146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
15156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
15166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg =~ /^--use-cc(=(.+))?$/) {
15186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
15196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $cc;
15206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (!defined $2 || $2 eq "") {
15226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if (!@$Args) {
15236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          DieDiag("'--use-cc' option requires a compiler executable name.\n");
15246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
15256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $cc = shift @$Args;
15266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
15276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      else {
15286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $cc = $2;
15296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
15306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{UseCC} = $cc;
15326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
15336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
15346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg =~ /^--use-c\+\+(=(.+))?$/) {
15366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
15376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $cxx;
15386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (!defined $2 || $2 eq "") {
15406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if (!@$Args) {
15416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          DieDiag("'--use-c++' option requires a compiler executable name.\n");
15426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
15436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $cxx = shift @$Args;
15446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
15456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      else {
15466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $cxx = $2;
15476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
15486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{UseCXX} = $cxx;
15506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
15516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
15526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg =~ /^--analyzer-target(=(.+))?$/) {
15546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @ARGV;
15556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $AnalyzerTarget;
15566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (!defined $2 || $2 eq "") {
15586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        if (!@ARGV) {
15596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker          DieDiag("'--analyzer-target' option requires a target triple name.\n");
15606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        }
15616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $AnalyzerTarget = shift @ARGV;
15626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
15636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      else {
15646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker        $AnalyzerTarget = $2;
15656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      }
15666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{AnalyzerTarget} = $AnalyzerTarget;
15686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
15696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
15706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-v") {
15726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
15736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{Verbose}++;
15746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
15756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
15766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-V" or $arg eq "--view") {
15786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
15796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{ViewResults} = 1;
15806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
15816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
15826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "--status-bugs") {
15846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
15856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{ExitStatusFoundBugs} = 1;
15866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
15876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
15886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-store") {
15906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
15916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{StoreModel} = shift @$Args;
15926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
15936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
15946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
15956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-constraints") {
15966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
15976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{ConstraintsModel} = shift @$Args;
15986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
15996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-internal-stats") {
16026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{InternalStats} = 1;
16046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-plist") {
16086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{OutputFormat} = "plist";
16106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-plist-html") {
16146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{OutputFormat} = "plist-html";
16166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-analyzer-config") {
16206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      push @{$Options{ConfigOptions}}, shift @$Args;
16226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-no-failure-reports") {
16266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{ReportFailures} = 0;
16286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-stats") {
16326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{AnalyzerStats} = 1;
16346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-maxloop") {
16386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{MaxLoop} = shift @$Args;
16406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-enable-checker") {
16446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $Checker = shift @$Args;
16466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # Store $NumArgs to preserve the order the checkers were enabled.
16476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{EnableCheckers}{$Checker} = $NumArgs;
16486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      delete $Options{DisableCheckers}{$Checker};
16496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-disable-checker") {
16536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $Checker = shift @$Args;
16556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      # Store $NumArgs to preserve the order the checkers were disabled.
16566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{DisableCheckers}{$Checker} = $NumArgs;
16576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      delete $Options{EnableCheckers}{$Checker};
16586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "-load-plugin") {
16626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      push @{$Options{PluginsToLoad}}, shift @$Args;
16646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "--use-analyzer") {
16686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{AnalyzerDiscoveryMethod} = shift @$Args;
16706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg =~ /^--use-analyzer=(.+)$/) {
16746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{AnalyzerDiscoveryMethod} = $1;
16766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "--keep-empty") {
16806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{KeepEmpty} = 1;
16826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "--override-compiler") {
16866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{OverrideCompiler} = 1;
16886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($arg eq "--force-analyze-debug-code") {
16926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      shift @$Args;
16936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      $Options{ForceAnalyzeDebugCode} = 1;
16946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      next;
16956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
16966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/);
16986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
16996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $NumArgs--;
17006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    last;
17016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
17026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  return $NumArgs;
17036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
17046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif (!@ARGV) {
17066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $ForceDisplayHelp = 1
17076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
17086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerProcessArgs(\@ARGV);
17106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# All arguments are now shifted from @ARGV. The rest is a build command, if any.
17116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif (!@ARGV and !$RequestDisplayHelp) {
17136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  ErrorDiag("No build command specified.\n\n");
17146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $ForceDisplayHelp = 1;
17156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
17166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $ClangNotFoundErrMsg = FindClang();
17186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif ($ForceDisplayHelp || $RequestDisplayHelp) {
17206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  DisplayHelp($ClangNotFoundErrMsg);
17216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  exit $ForceDisplayHelp;
17226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
17236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerDieDiag($ClangNotFoundErrMsg) if (defined $ClangNotFoundErrMsg);
17256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker$ClangCXX = $Clang;
17276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif ($Clang !~ /\+\+(\.exe)?$/) {
17286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # If $Clang holds the name of the clang++ executable then we leave
17296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # $ClangCXX and $Clang equal, otherwise construct the name of the clang++
17306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # executable from the clang executable name.
17316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Determine operating system under which this copy of Perl was built.
17336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  my $IsWinBuild = ($^O =~/msys|cygwin|MSWin32/);
17346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if($IsWinBuild) {
17356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $ClangCXX =~ s/.exe$/++.exe/;
17366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
17376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  else {
17386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $ClangCXX =~ s/\-\d+\.\d+$//;
17396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    $ClangCXX .= "++";
17406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
17416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
17426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Make sure to use "" to handle paths with spaces.
17446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker$ClangVersion = HtmlEscape(`"$Clang" --version`);
17456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Determine where results go.
17476bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker$CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV)));
17486bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17496bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Determine the output directory for the HTML reports.
17506bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $BaseDir = $Options{OutputDir};
17516bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker$Options{OutputDir} = GetHTMLRunDir($Options{OutputDir});
17526bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17536bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Determine the location of ccc-analyzer.
17546bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $AbsRealBin = Cwd::realpath($RealBin);
17556bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $Cmd = "$AbsRealBin/../libexec/ccc-analyzer";
17566bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $CmdCXX = "$AbsRealBin/../libexec/c++-analyzer";
17576bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17586bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Portability: use less strict but portable check -e (file exists) instead of
17596bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# non-portable -x (file is executable). On some windows ports -x just checks
17606bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# file extension to determine if a file is executable (see Perl language
17616bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# reference, perlport)
17626bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif (!defined $Cmd || ! -e $Cmd) {
17636bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $Cmd = "$AbsRealBin/ccc-analyzer";
17646bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  DieDiag("'ccc-analyzer' does not exist at '$Cmd'\n") if(! -e $Cmd);
17656bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
17666bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif (!defined $CmdCXX || ! -e $CmdCXX) {
17676bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  $CmdCXX = "$AbsRealBin/c++-analyzer";
17686bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  DieDiag("'c++-analyzer' does not exist at '$CmdCXX'\n") if(! -e $CmdCXX);
17696bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
17706bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17716bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerDiag("Using '$Clang' for static analysis\n");
17726bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17736bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerSetHtmlEnv(\@ARGV, $Options{OutputDir});
17746bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17756bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy @AnalysesToRun;
17766bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerforeach (sort { $Options{EnableCheckers}{$a} <=> $Options{EnableCheckers}{$b} } 
17776bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker         keys %{$Options{EnableCheckers}}) { 
17786bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Push checkers in order they were enabled.
17796bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  push @AnalysesToRun, "-analyzer-checker", $_;
17806bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
17816bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerforeach (sort { $Options{DisableCheckers}{$a} <=> $Options{DisableCheckers}{$b} } 
17826bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker         keys %{$Options{DisableCheckers}}) { 
17836bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  # Push checkers in order they were disabled.
17846bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  push @AnalysesToRun, "-analyzer-disable-checker", $_;
17856bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
17866bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif ($Options{AnalyzeHeaders}) { push @AnalysesToRun, "-analyzer-opt-analyze-headers"; }
17876bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif ($Options{AnalyzerStats}) { push @AnalysesToRun, '-analyzer-checker=debug.Stats'; }
17886bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif ($Options{MaxLoop} > 0) { push @AnalysesToRun, "-analyzer-max-loop $Options{MaxLoop}"; }
17896bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
17906bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Delay setting up other environment variables in case we can do true
17916bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# interposition.
17926bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $CCC_ANALYZER_ANALYSIS = join ' ', @AnalysesToRun;
17936bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $CCC_ANALYZER_PLUGINS = join ' ', map { "-load ".$_ } @{$Options{PluginsToLoad}};
17946bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $CCC_ANALYZER_CONFIG = join ' ', map { "-analyzer-config ".$_ } @{$Options{ConfigOptions}};
17956bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy %EnvVars = (
17966bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CC' => $Cmd,
17976bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CXX' => $CmdCXX,
17986bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CLANG' => $Clang,
17996bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CLANG_CXX' => $ClangCXX,
18006bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'VERBOSE' => $Options{Verbose},
18016bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_ANALYZER_ANALYSIS' => $CCC_ANALYZER_ANALYSIS,
18026bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_ANALYZER_PLUGINS' => $CCC_ANALYZER_PLUGINS,
18036bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_ANALYZER_CONFIG' => $CCC_ANALYZER_CONFIG,
18046bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'OUTPUT_DIR' => $Options{OutputDir},
18056bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_CC' => $Options{UseCC},
18066bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_CXX' => $Options{UseCXX},
18076bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_REPORT_FAILURES' => $Options{ReportFailures},
18086bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_ANALYZER_STORE_MODEL' => $Options{StoreModel},
18096bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_ANALYZER_CONSTRAINTS_MODEL' => $Options{ConstraintsModel},
18106bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_ANALYZER_INTERNAL_STATS' => $Options{InternalStats},
18116bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_ANALYZER_OUTPUT_FORMAT' => $Options{OutputFormat},
18126bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CLANG_ANALYZER_TARGET' => $Options{AnalyzerTarget},
18136bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  'CCC_ANALYZER_FORCE_ANALYZE_DEBUG_CODE' => $Options{ForceAnalyzeDebugCode}
18146bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker);
18156bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
18166bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker# Run the build.
18176bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickermy $ExitStatus = RunBuildCommand(\@ARGV, $Options{IgnoreErrors}, $Cmd, $CmdCXX,
18186bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                                \%EnvVars);
18196bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
18206bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerif (defined $Options{OutputFormat}) {
18216bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Options{OutputFormat} =~ /plist/) {
18226bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Diag "Analysis run complete.\n";
18236bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    Diag "Analysis results (plist files) deposited in '$Options{OutputDir}'\n";
18246bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
18256bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  if ($Options{OutputFormat} =~ /html/) {
18266bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    # Postprocess the HTML directory.
18276bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    my $NumBugs = Postprocess($Options{OutputDir}, $BaseDir,
18286bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker                              $Options{AnalyzerStats}, $Options{KeepEmpty});
18296bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
18306bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($Options{ViewResults} and -r "$Options{OutputDir}/index.html") {
18316bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      Diag "Analysis run complete.\n";
18326bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      Diag "Viewing analysis results in '$Options{OutputDir}' using scan-view.\n";
18336bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      my $ScanView = Cwd::realpath("$RealBin/scan-view");
18346bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (! -x $ScanView) { $ScanView = "scan-view"; }
18356bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      if (! -x $ScanView) { $ScanView = Cwd::realpath("$RealBin/../../scan-view/bin/scan-view"); }
18366bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      exec $ScanView, "$Options{OutputDir}";
18376bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
18386bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
18396bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    if ($Options{ExitStatusFoundBugs}) {
18406bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      exit 1 if ($NumBugs > 0);
18416bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker      exit 0;
18426bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker    }
18436bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker  }
18446bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker}
18456bdbd720989797e8a53237ef3ef213c4114f869gitbuildkicker
18466bdbd720989797e8a53237ef3ef213c4114f869gitbuildkickerexit $ExitStatus;
1847