scan-build revision 6195c373b86963b029a2d1d2501f899789d74ba8
19cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek#!/usr/bin/env perl
29cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek#
39cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek#                     The LLVM Compiler Infrastructure
49cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek#
59cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# This file is distributed under the University of Illinois Open Source
69cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# License. See LICENSE.TXT for details.
79cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek#
89cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##===----------------------------------------------------------------------===##
99cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek#
109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# A script designed to wrap a build so that all calls to gcc are intercepted
119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# and piped to the static analyzer.
129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek#
139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##===----------------------------------------------------------------------===##
149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse strict;
169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse warnings;
179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse File::Temp qw/ :mktemp /;
1822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenekuse FindBin qw($RealBin);
19a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenekuse Digest::MD5;
207a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekuse File::Basename;
219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Verbose = 0;       # Verbose output from this script.
239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Prog = "scan-build";
24f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildName;
25f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildDate;
269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current run.
299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
31a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir {  
329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "Not enough arguments." if (@_ == 0);
349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift @_;
369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Get current date and time.
389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my @CurrentTime = localtime();
409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $year  = $CurrentTime[5] + 1900;
429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $day   = $CurrentTime[3];
439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $month = $CurrentTime[4] + 1;
449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
459d7405fafd5bc08d38bc75579927bf414570bd61Ted Kremenek  my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day);
469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Determine the run number.
489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $RunNumber;
509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (-d $Dir) {
529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (! -r $Dir) {
54a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop      die "error: '$Dir' exists but is not readable.\n";
559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # Iterate over all files in the specified directory.
589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    my $max = 0;
609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    opendir(DIR, $Dir);
629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    my @FILES= readdir(DIR); 
639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    closedir(DIR);
649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    foreach my $f (@FILES) {
669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      my @x = split/-/, $f;
689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      
699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if (scalar(@x) != 4);
709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[0] != $year);
719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[1] != $month);
729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[2] != $day);
739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      
749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      if ($x[3] > $max) {
759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek        $max = $x[3];
769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      }      
779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $RunNumber = $max + 1;
809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  else {
829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (-x $Dir) {
84a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop      die "error: '$Dir' exists but is not a directory.\n";
859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # $Dir does not exist.  It will be automatically created by the 
889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # clang driver.  Set the run number to 1.  
899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $RunNumber = 1;
919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "RunNumber must be defined!" if (!defined($RunNumber));
949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Append the run number.
969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  return "$Dir/$DateString-$RunNumber";  
989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
100a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv {
1019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "Wrong number of arguments." if (scalar(@_) != 2);
1039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Args = shift;
1059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift;
1069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "No build command." if (scalar(@$Args) == 0);
1089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Cmd = $$Args[0];
1109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($Cmd =~ /configure/) {
1129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    return;
1139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
1149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($Verbose) {
1169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    print "$Prog: Emitting reports for this run to '$Dir'.\n";  
1179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
1189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  $ENV{'CCC_ANALYZER_HTML'} = $Dir;
1209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
1219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
1229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
12357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file.
12457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------##
12557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
12657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest {
12757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $FName = shift;
12857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  die "Cannot read $FName" if (! -r $FName);  
129a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  
130a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  # Use Digest::MD5.  We don't have to be cryptographically secure.  We're
1317ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek  # just looking for duplicate files that come from a non-malicious source.
1327ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek  # We use Digest::MD5 because it is a standard Perl module that should
133a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  # come bundled on most systems.
134a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  
135a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  open(FILE, $FName) or die "Cannot open $FName.";
136a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  binmode FILE;
137a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest;
138a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  close(FILE);
139a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  
140a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  # Return the digest.
141a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  
142a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek  return $Result;
14357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek}
14457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
14557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------##
1467a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek#  UpdatePrefix - Compute the common prefix of files.
1477a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
1487a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
1497a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekmy $Prefix;
1507a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
1517a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdatePrefix {
1527a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
1537a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $x = shift;
1547a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $y = basename($x);
1557a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  $x =~ s/\Q$y\E$//;
1567a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
1577a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  # Ignore /usr, /Library, /System, /Developer
1587a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
1597a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  return if ( $x =~ /^\/usr/ or $x =~ /^\/Library/
1607a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek              or $x =~ /^\/System/ or $x =~ /^\/Developer/);
1617a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
1627a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
1637a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  if (!defined $Prefix) {
1647a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    $Prefix = $x;
1657a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    return;
1667a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  }
1677a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
1687a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  chop $Prefix while (!($x =~ /^$Prefix/));
1697a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
1707a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
1717a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub GetPrefix {
1727a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  return $Prefix;
1737a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
1747a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
1757a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
1767a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek#  UpdateInFilePath - Update the path in the report file.
1777a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
1787a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
1797a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdateInFilePath {
1807a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $fname = shift;
1817a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $regex = shift;
1827a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $newtext = shift;
1837a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
1847a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  open (RIN, $fname) or die "cannot open $fname";
1857a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  open (ROUT, ">$fname.tmp") or die "cannot open $fname.tmp";
1867a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
1877a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  while (<RIN>) {
1887a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    s/$regex/$newtext/;
1897a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    print ROUT $_;
1907a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  }
1917a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
1927a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  close (ROUT);
1937a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  close (RIN);
1947a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  `mv $fname.tmp $fname`;
1957a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek}
1967a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
1977a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------##
1985744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes.
1995744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------##
2005744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
20157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces
20257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports.  We use a cache to solve this problem.
20357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
20457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned;
20557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
2065744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile {
2075744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
2085744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $Index = shift;
2095744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $Dir = shift;
2105744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $FName = shift;
2115744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
21257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  # Compute a digest for the report file.  Determine if we have already
21357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  # scanned a file that looks just like it.
21457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
21557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $digest = ComputeDigest("$Dir/$FName");
21657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
21757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  if (defined($AlreadyScanned{$digest})) {
21857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    # Redundant file.  Remove it.
21957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    `rm -f $Dir/$FName`;
22057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    return;
22157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  }
22257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
22357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  $AlreadyScanned{$digest} = 1;
22457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
225809709f46f2516b4054681f0b76284055a84a50fTed Kremenek  # At this point the report file is not world readable.  Make it happen.
226684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  `chmod 644 $Dir/$FName`;
227684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  
228684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  # Scan the report file for tags.
2295744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  open(IN, "$Dir/$FName") or die "$Prog: Cannot open '$Dir/$FName'\n";
2305744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
2315744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $BugDesc = "";
23222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugFile = "";
23322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugPathLength = 1;
23422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugLine = 0;
2355744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
2365744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  while (<IN>) {
2375744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
2385744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    if (/<!-- BUGDESC (.*) -->$/) {
2395744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek      $BugDesc = $1;
2405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    }
24122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGFILE (.*) -->$/) {
24222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugFile = $1;
2437a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek      UpdatePrefix($BugFile);
24422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
24522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGPATHLENGTH (.*) -->$/) {
24622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugPathLength = $1;
24722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
24822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGLINE (.*) -->$/) {
24922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugLine = $1;    
25022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
2515744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  }
2525744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
2535744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  close(IN);
2545744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
25522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  push @$Index,[ $FName, $BugDesc, $BugFile, $BugLine, $BugPathLength ];
25622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek}
25722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
25822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------##
25922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek# CopyJS - Copy JavaScript code to target directory.
26022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------##
26122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
26222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremeneksub CopyJS {
26322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
26422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $Dir = shift;
26522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  
26622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  die "$Prog: Cannot find 'sorttable.js'.\n"
26722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    if (! -r "$RealBin/sorttable.js");  
26822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
26922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  `cp $RealBin/sorttable.js $Dir`;
27022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
27122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  die "$Prog: Could not copy 'sorttable.js' to '$Dir'."
27222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    if (! -r "$Dir/sorttable.js");
2735744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek}
2745744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
2755744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------##
2769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan.
2779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
2789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
279a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess {
2809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift;
282684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  my $BaseDir = shift;
2839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "No directory specified." if (!defined($Dir));
285684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  die "No base directory specified." if (!defined($BaseDir));
2869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (! -d $Dir) {
2889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    return;
2899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  opendir(DIR, $Dir);
2929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my @files = grep(/^report-.*\.html$/,readdir(DIR));
2939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  closedir(DIR);
2949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
2959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (scalar(@files) == 0) {
29602493782bd4620969041921f2a842528ffdfc940Ted Kremenek    print "$Prog: Removing directory '$Dir' because it contains no reports.\n";
2979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    `rm -fR $Dir`;
2989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    return;
2999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
3005744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
3015744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  # Scan each report file and build an index.
3025744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
3035744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my @Index;
3045744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
3055744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); }
3065744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
3075744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  # Generate an index.html file.
3085744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
3095744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $FName = "$Dir/index.html";
3105744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
3115744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  open(OUT, ">$FName") or die "$Prog: Cannot create file '$FName'\n";
3125744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
3136e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the header.
3146e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
3155744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT;
3165744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html>
3175744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head>
3187f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<style type="text/css">
3197f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek body { color:#000000; background-color:#ffffff }
32022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek body { font-family: Helvetica, sans-serif; font-size:9pt }
3217f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek h1 { font-size:12pt }
32222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable thead {
32322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek   background-color:#eee; color:#666666;
32422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek   font-weight: bold; cursor: default;
325bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek   text-align:center;
326bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek   border-top: 2px solid #000000;
327bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek   border-bottom: 2px solid #000000;
328bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek   font-weight: bold; font-family: Verdana
329bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek } 
33022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border: 1px #000000 solid }
33122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border-collapse: collapse; border-spacing: 0px }
3327f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek td { border-bottom: 1px #000000 dotted }
33322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td { padding:5px; padding-left:8px; padding-right:8px }
334d8c6d0c8a5f970240cc4cbf8eddeae037d1b29eaTed Kremenek td { text-align:left; font-size:9pt }
33522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td.View   { padding-left: 10px }
3367f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</style>
33722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script>
3386e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript">
3396e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal)
3406e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{
3416e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  var Rows = document.getElementsByTagName("tr");
3426e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  for ( var i = 0 ; i < Rows.length; ++i ) {
3436e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    if (Rows[i].className == RowClass) {
3446e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek      Rows[i].style.display = DisplayVal;
3456e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
3466e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
3476e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek}
3486e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
3496e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) {
3506e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  if (CheckButton.checked) {
3516e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    SetDisplay(ClassName, "");
3526e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
3536e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  else {
3546e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    SetDisplay(ClassName, "none");
3556e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
3566e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek}
3576e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script>
3586e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head>
3596e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body>
3606e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT
3616e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
3626e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the summary table.
3636e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
3646e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  my %Totals;
3656e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
3666e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  for my $row ( @Index ) {
3676e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    
368432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek    #my $bug_type = lc($row->[1]);
369432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek    my $bug_type = ($row->[1]);
3706e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    
3716e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    if (!defined($Totals{$bug_type})) {
3726e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek      $Totals{$bug_type} = 1;
3736e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
3746e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    else {
3756e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek      $Totals{$bug_type}++;
3766e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
3776e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
378f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  
379f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  print OUT "<h3>Summary</h3>";
380f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek    
381f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  if (defined($BuildName)) {
382f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek    print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n"
383f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  }
384f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  
3856e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT;
3866e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<table class="sortable">
3876e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<tr>
3886e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  <td>Bug Type</td>
3896e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  <td>Quantity</td>
3906e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  <td "sorttable_nosort">Display?</td>
3916e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</tr>
3926e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT
3936e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
3946e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  for my $key ( sort { $a cmp $b } keys %Totals ) {
395bdf66c7373159aa80403d313629330fd11d4c48aTed Kremenek    my $x = lc($key);
396bdf66c7373159aa80403d313629330fd11d4c48aTed Kremenek    $x =~ s/\s[,]/_/g;
3976e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    print OUT "<tr><td>$key</td><td>$Totals{$key}</td><td><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></td></tr>\n";
3986e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
3996e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
4006e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the table of errors.
4016e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
4026e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT;
4036e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table>
4046e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<h3>Reports</h3>
40522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<table class="sortable">
4067f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<tr>
407bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>Bug Type</td>
408bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>File</td>
409bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>Line</td>
410bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>Path Length</td>
411bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td "sorttable_nosort"></td>
4127f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</tr>
4135744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT
4149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
4157a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $prefix = GetPrefix();
4167a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $regex;
4177a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $InFileRegex;
4187a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  my $InFilePrefix = "File:</td><td>";
4197a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  
4207a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  if (defined($prefix)) { 
4217a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    $regex = qr/^\Q$prefix\E/is;    
4227a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is;
4237a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek  }    
4247a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
4255744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  for my $row ( sort { $a->[1] cmp $b->[1] } @Index ) {
4265744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
4276e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    my $x = lc($row->[1]);
428bdf66c7373159aa80403d313629330fd11d4c48aTed Kremenek    $x =~ s/\s[,]/_/g;
4296e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    
4306e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    print OUT "<tr class=\"bt_$x\">\n";
4315744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
4325744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    my $ReportFile = $row->[0];
4339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
43422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    print OUT " <td class=\"DESC\">";
435432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek    #print OUT lc($row->[1]);
436432af5985a22e098cbc2329c021d5e23c944fb91Ted Kremenek    print OUT $row->[1];
43722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    print OUT "</td>\n";
4385744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
4397a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    # Update the file prefix.
4407a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    
4417a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    my $fname = $row->[2];
4427a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    if (defined($regex)) {      
4437a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek      $fname =~ s/$regex//;
4447a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek      UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix)
4457a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    }
4463e56e0b8b285e86eed4d191b1da93ded7382a847Ted Kremenek
4477a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    print OUT "<td>$fname</td>\n";
4487a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek
4497a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    # Print the rest of the columns.
4507a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    
4517a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek    for my $j ( 3 .. $#{$row} ) {
4525744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek      print OUT "<td>$row->[$j]</td>\n"
4535744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    }
4547f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
4557f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    # Emit the "View" link.
4567f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    
45722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    print OUT " <td class=\"View\"><a href=\"$ReportFile#EndPath\">View</a></td>\n";
4585744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
4597f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    # End the row.
4605744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    print OUT "</tr>\n";
4615744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  }
4625744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
4635744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  print OUT "</table>\n</body></html>\n";  
4645744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  close(OUT);
46522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  
46622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  CopyJS($Dir);
467684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  
468684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  # Make sure $Dir and $BaseDir is world readable/executable.
469684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  `chmod 755 $Dir`;
470684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  `chmod 755 $BaseDir`;
4719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
4729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
4739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
474dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command.
475dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------##
476dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek
4776b6289848e215ff12d4d54fe0602d3371db52788Ted Kremeneksub AddIfNotPresent {
4786b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $Args = shift;
4796b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $Arg = shift;  
4806b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  my $found = 0;
4816b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
4826b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  foreach my $k (@$Args) {
4836b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    if ($k eq $Arg) {
4846b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      $found = 1;
4856b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      last;
4866b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    }
4876b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
4886b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
4896b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  if ($found == 0) {
4906b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    push @$Args, $Arg;
4916b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
4926b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek}
4936b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek
494dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremeneksub RunBuildCommand {
495dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
496dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  my $Args = shift;
4977442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek  my $IgnoreErrors = shift;
498dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  my $Cmd = $Args->[0];
4996195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek  my $CCAnalyzer = shift;
500dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
5016a43ba9cd247811b6d48ffbd4ee3c911c8c4b458Ted Kremenek  if ($Cmd eq "gcc" or $Cmd eq "cc" or $Cmd eq "llvm-gcc") {
502dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek    shift @$Args;
5036195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek    unshift @$Args, $CCAnalyzer;
504dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  }
5057442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek  elsif ($IgnoreErrors) {
5067442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    if ($Cmd eq "make" or $Cmd eq "gmake") {
5076b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      AddIfNotPresent($Args,"-k");
5088912b5427a22d9032cad959c5c22cd9d28d4a66cTed Kremenek      AddIfNotPresent($Args,"-i");
5097442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    }
5107442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    elsif ($Cmd eq "xcodebuild") {
5116b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek      AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES");
5127442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    }
5136b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  } 
5146b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  
5156b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  if ($Cmd eq "xcodebuild") {
516cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    # Disable distributed builds for xcodebuild.
5176b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek    AddIfNotPresent($Args,"-nodistribute");
518cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek
519cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    # Disable PCH files until clang supports them.
520cfd4c7bef7a76c568ec033e91ba3f521e10bcbb3Ted Kremenek    AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO");
521915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    
522915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # When 'CC' is set, xcodebuild uses it to do all linking, even if we are
523915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # linking C++ object files.  Set 'LDPLUSPLUS' so that xcodebuild uses 'g++'
524915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    # when linking such files.
525915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    my $LDPLUSPLUS = `which g++`;
526915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    $LDPLUSPLUS =~ s/\015?\012//;  # strip newlines
527915e972098f1e67c7559613ccde7205cee582e61Ted Kremenek    $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS;    
5286b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek  }
529dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
530dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  system(@$Args);
531dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek}
532dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek
533dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------##
5349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options.
5359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
5369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
537a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp {
5389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
5395744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT;
540a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options]
5412b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
542f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted KremenekENDTEXT
543f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek
544f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  if (defined($BuildName)) {
545f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek    print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n";
546f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek  }
547f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek
548f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekprint <<ENDTEXT;
5492b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS:
5502b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
5511262fc4d66584224234691d30d779f8ff004585cTed Kremenek  -a            - The analysis to run.  The default is 'checker-cfref'.
5521262fc4d66584224234691d30d779f8ff004585cTed Kremenek                  Valid options are: 'checker-cfref', 'fsyntax-only'
5531262fc4d66584224234691d30d779f8ff004585cTed Kremenek
5542b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek  -o            - Target directory for HTML report files.  Subdirectories
555a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop                  will be created as needed to represent separate "runs" of
5562b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek                  the analyzer.  If this option is not specified, a directory
5572b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek                  is created in /tmp to store the reports.
5581262fc4d66584224234691d30d779f8ff004585cTed Kremenek
55910f883fe7ef74139f8778e49acacf0ce408e7088Ted Kremenek  -h            - Display this message.
5602b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek  --help
5611262fc4d66584224234691d30d779f8ff004585cTed Kremenek
562af08f64abc38af5914d96106aeb014a2e06eb865Ted Kremenek  -k            - Add a "keep on going" option to the specified build command.
563f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek  --keep-going    This option currently supports make and xcodebuild.
564f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek                  This is a convenience option; one can specify this
565f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek                  behavior directly using build options.
5662b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
567dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  -v            - Verbose output from $Prog and the analyzer.
568dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek                  A second "-v" increases verbosity.
5692b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
5707f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  -V            - View analysis results in a web browser when the build
5717f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  --view          completes.
5727f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
5732b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS
5742b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
57539eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek  You can specify any build option acceptable to the build command.
57639eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek
5775744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE
5782b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
5795744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    $Prog -o /tmp/myhtmldir make -j4
5802b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek     
58139eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek  The above example causes analysis reports to be deposited into
58239eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek  a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option.
58339eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek  A different subdirectory is created each time $Prog analyzes a project.
58439eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek  The analyzer should support most parallel builds, but not distributed builds.
5852b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
5862b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT
5879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
5889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
5909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments.
5919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
5929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir;           # Parent directory to store HTML files.
5949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0;  # Ignore build errors.
5957f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults  = 0;  # View results when the build terminates.
5961262fc4d66584224234691d30d779f8ff004585cTed Kremenekmy $Analysis = "checker-cfref";
5979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) {
5999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  DisplayHelp();
600a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  exit 1;
6019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
6029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
6039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) {
6049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
6059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Scan for options we recognize.
6069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
6079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $arg = $ARGV[0];
6089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
6092f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop  if ($arg eq "-h" or $arg eq "--help") {
6109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    DisplayHelp();
611a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop    exit 0;
6129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
6139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
6141262fc4d66584224234691d30d779f8ff004585cTed Kremenek  if ($arg eq "-a") {
6151262fc4d66584224234691d30d779f8ff004585cTed Kremenek    shift @ARGV;
6161262fc4d66584224234691d30d779f8ff004585cTed Kremenek
6171262fc4d66584224234691d30d779f8ff004585cTed Kremenek    if (!@ARGV) {
6181262fc4d66584224234691d30d779f8ff004585cTed Kremenek      die "$Prog: '-a' option requires an analysis type.\n";
6191262fc4d66584224234691d30d779f8ff004585cTed Kremenek    }
6201262fc4d66584224234691d30d779f8ff004585cTed Kremenek    
6211262fc4d66584224234691d30d779f8ff004585cTed Kremenek    $Analysis = shift @ARGV;
6221262fc4d66584224234691d30d779f8ff004585cTed Kremenek    
6231262fc4d66584224234691d30d779f8ff004585cTed Kremenek    if (!($Analysis eq "checker-cfref" or $Analysis eq "fsyntax-only")) {
6241262fc4d66584224234691d30d779f8ff004585cTed Kremenek      die "$Prog: Invalid argument '$Analysis' to -a.\n";
6251262fc4d66584224234691d30d779f8ff004585cTed Kremenek    }
6261262fc4d66584224234691d30d779f8ff004585cTed Kremenek    
6271262fc4d66584224234691d30d779f8ff004585cTed Kremenek    next;
6281262fc4d66584224234691d30d779f8ff004585cTed Kremenek  }
6291262fc4d66584224234691d30d779f8ff004585cTed Kremenek  
6309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($arg eq "-o") {
6319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
6329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek        
6339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (!@ARGV) {
6340062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek      die "$Prog: '-o' option requires a target directory name.\n";
6359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
6369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
6379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $HtmlDir = shift @ARGV;
6389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
6399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
6409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
6412b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek  if ($arg eq "-k" or $arg eq "--keep-going") {
6429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
6439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $IgnoreErrors = 1;
6449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
6459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
6469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
6479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($arg eq "-v") {
6489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
6499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $Verbose++;
6509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
6519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
6529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
6537f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  if ($arg eq "-V" or $arg eq "--view") {
6547f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    shift @ARGV;
6557f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    $ViewResults = 1;    
6567f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    next;
6577f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  }
6587f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  
6590062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek  die "$Prog: unrecognized option '$arg'\n" if ($arg =~ /^-/);
6600062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek  
6619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  last;
6629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
6639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
6649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) {
6659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  print STDERR "$Prog: No build command specified.\n\n";
6669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  DisplayHelp();
667a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  exit 1;
6689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
6699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
6709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports.
6719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
6729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!defined($HtmlDir)) {
6739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
674a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  $HtmlDir = mkdtemp("/tmp/$Prog-XXXXXX");
6759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
6769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (!defined($HtmlDir)) {
677a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop    die "error: Cannot create HTML directory in /tmp.\n";
6789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
6799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
6809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (!$Verbose) {
6819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    print "$Prog: Using '$HtmlDir' as base HTML report directory.\n";
6829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
6839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
6849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
685684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir;
686a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir);
6879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
6889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Set the appropriate environment variables.
6899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
690a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopSetHtmlEnv(\@ARGV, $HtmlDir);
6919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
6920b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekmy $Cmd = "$RealBin/ccc-analyzer";
6930b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek
6940b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekdie "$Prog: Executable 'ccc-analyzer' does not exist at '$Cmd'\n"
6950b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek  if (! -x $Cmd);
696f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek  
697f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenekmy $Clang = "$RealBin/clang";
698f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek
699f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenekif (! -x $Clang) {
700f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek  print "$Prog: 'clang' executable not found in '$RealBin'.  Using 'clang' from path.\n";
701f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek  $Clang = "clang";
702f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek}
7030b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek
7044f4b17da43d3be87a248e1e10bf0b7d8b5891efdTed Kremenek$ENV{'CC'} = $Cmd;
705f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek$ENV{'CLANG'} = $Clang;
7069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
7079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif ($Verbose >= 2) {
7089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  $ENV{'CCC_ANALYZER_VERBOSE'} = 1;
7099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
7109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
711a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenekif ($Verbose >= 3) {
712a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek  $ENV{'CCC_ANALYZER_LOG'} = 1;
713a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek}
714a9525c929b280f12bd4f92a1732f981b82a62d25Ted Kremenek
7151262fc4d66584224234691d30d779f8ff004585cTed Kremenek$ENV{'CCC_ANALYZER_ANALYSIS'} = $Analysis;
7161262fc4d66584224234691d30d779f8ff004585cTed Kremenek
7179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build.
7189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
7196195c373b86963b029a2d1d2501f899789d74ba8Ted KremenekRunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd);
7209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
7219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess the HTML directory.
7229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
723684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted KremenekPostprocess($HtmlDir, $BaseDir);
7247f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
7257f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekif ($ViewResults and -r "$HtmlDir/index.html") {
7267f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  # Only works on Mac OS X (for now).
7277f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  print "Viewing analysis results: '$HtmlDir/index.html'\n";
7287f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  `open $HtmlDir/index.html`
7297f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek}
730