scan-build revision f22eacb11b50e647e7d08531ca5648d3c84c38c3
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);
199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Verbose = 0;       # Verbose output from this script.
219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Prog = "scan-build";
229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current run.
259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
27a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir {  
289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
299cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "Not enough arguments." if (@_ == 0);
309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift @_;
329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Get current date and time.
349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my @CurrentTime = localtime();
369cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
379cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $year  = $CurrentTime[5] + 1900;
389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $day   = $CurrentTime[3];
399cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $month = $CurrentTime[4] + 1;
409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $DateString = "$year-$month-$day";
429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Determine the run number.
449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $RunNumber;
469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (-d $Dir) {
489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (! -r $Dir) {
50a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop      die "error: '$Dir' exists but is not readable.\n";
519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # Iterate over all files in the specified directory.
549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    my $max = 0;
569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    opendir(DIR, $Dir);
589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    my @FILES= readdir(DIR); 
599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    closedir(DIR);
609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    foreach my $f (@FILES) {
629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      my @x = split/-/, $f;
649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      
659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if (scalar(@x) != 4);
669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[0] != $year);
679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[1] != $month);
689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      next if ($x[2] != $day);
699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      
709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      if ($x[3] > $max) {
719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek        $max = $x[3];
729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek      }      
739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $RunNumber = $max + 1;
769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  else {
789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (-x $Dir) {
80a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop      die "error: '$Dir' exists but is not a directory.\n";
819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # $Dir does not exist.  It will be automatically created by the 
849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    # clang driver.  Set the run number to 1.  
859cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $RunNumber = 1;
879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "RunNumber must be defined!" if (!defined($RunNumber));
909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Append the run number.
929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  return "$Dir/$DateString-$RunNumber";  
949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
96a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv {
979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "Wrong number of arguments." if (scalar(@_) != 2);
999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Args = shift;
1019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift;
1029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1039cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "No build command." if (scalar(@$Args) == 0);
1049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Cmd = $$Args[0];
1069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($Cmd =~ /configure/) {
1089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    return;
1099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
1109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($Verbose) {
1129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    print "$Prog: Emitting reports for this run to '$Dir'.\n";  
1139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
1149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
1159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  $ENV{'CCC_ANALYZER_HTML'} = $Dir;
1169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
1179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
1189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
11957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file.
12057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------##
12157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
12257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest {
12357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $FName = shift;
12457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  die "Cannot read $FName" if (! -r $FName);  
12557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $Result = `sha1sum -b $FName`;
12657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my @Output = split /\s+/,$Result;
12757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  die "Bad output from sha1sum" if (scalar(@Output) != 2);
12857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  return $Output[0];
12957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek}
13057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
13157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------##
1325744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes.
1335744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------##
1345744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
13557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces
13657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports.  We use a cache to solve this problem.
13757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
13857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned;
13957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
1405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile {
1415744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
1425744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $Index = shift;
1435744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $Dir = shift;
1445744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $FName = shift;
1455744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
14657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  # Compute a digest for the report file.  Determine if we have already
14757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  # scanned a file that looks just like it.
14857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
14957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  my $digest = ComputeDigest("$Dir/$FName");
15057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek
15157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  if (defined($AlreadyScanned{$digest})) {
15257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    # Redundant file.  Remove it.
15357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    `rm -f $Dir/$FName`;
15457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek    return;
15557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  }
15657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
15757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  $AlreadyScanned{$digest} = 1;
15857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek  
159809709f46f2516b4054681f0b76284055a84a50fTed Kremenek  # At this point the report file is not world readable.  Make it happen.
160684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  `chmod 644 $Dir/$FName`;
161684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  
162684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  # Scan the report file for tags.
1635744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  open(IN, "$Dir/$FName") or die "$Prog: Cannot open '$Dir/$FName'\n";
1645744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
1655744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $BugDesc = "";
16622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugFile = "";
16722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugPathLength = 1;
16822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $BugLine = 0;
1695744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
1705744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  while (<IN>) {
1715744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
1725744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    if (/<!-- BUGDESC (.*) -->$/) {
1735744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek      $BugDesc = $1;
1745744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    }
17522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGFILE (.*) -->$/) {
17622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugFile = $1;
17722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
17822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGPATHLENGTH (.*) -->$/) {
17922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugPathLength = $1;
18022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
18122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    elsif (/<!-- BUGLINE (.*) -->$/) {
18222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek      $BugLine = $1;    
18322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    }
1845744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  }
1855744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
1865744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  close(IN);
1875744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
18822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  push @$Index,[ $FName, $BugDesc, $BugFile, $BugLine, $BugPathLength ];
18922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek}
19022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
19122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------##
19222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek# CopyJS - Copy JavaScript code to target directory.
19322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------##
19422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
19522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremeneksub CopyJS {
19622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
19722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  my $Dir = shift;
19822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  
19922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  die "$Prog: Cannot find 'sorttable.js'.\n"
20022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    if (! -r "$RealBin/sorttable.js");  
20122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
20222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  `cp $RealBin/sorttable.js $Dir`;
20322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek
20422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  die "$Prog: Could not copy 'sorttable.js' to '$Dir'."
20522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    if (! -r "$Dir/sorttable.js");
2065744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek}
2075744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
2085744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------##
2099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan.
2109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
2119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
212a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess {
2139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $Dir = shift;
215684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  my $BaseDir = shift;
2169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  die "No directory specified." if (!defined($Dir));
218684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  die "No base directory specified." if (!defined($BaseDir));
2199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (! -d $Dir) {
2219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    return;
2229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
2249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  opendir(DIR, $Dir);
2259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my @files = grep(/^report-.*\.html$/,readdir(DIR));
2269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  closedir(DIR);
2279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
2289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (scalar(@files) == 0) {
22902493782bd4620969041921f2a842528ffdfc940Ted Kremenek    print "$Prog: Removing directory '$Dir' because it contains no reports.\n";
2309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    `rm -fR $Dir`;
2319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    return;
2329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
2335744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
2345744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  # Scan each report file and build an index.
2355744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
2365744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my @Index;
2375744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
2385744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); }
2395744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
2405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  # Generate an index.html file.
2415744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
2425744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  my $FName = "$Dir/index.html";
2435744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
2445744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  open(OUT, ">$FName") or die "$Prog: Cannot create file '$FName'\n";
2455744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
2466e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the header.
2476e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
2485744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT;
2495744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html>
2505744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head>
2517f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<style type="text/css">
2527f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek body { color:#000000; background-color:#ffffff }
25322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek body { font-family: Helvetica, sans-serif; font-size:9pt }
2547f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek h1 { font-size:12pt }
25522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable thead {
25622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek   background-color:#eee; color:#666666;
25722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek   font-weight: bold; cursor: default;
258bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek   text-align:center;
259bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek   border-top: 2px solid #000000;
260bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek   border-bottom: 2px solid #000000;
261bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek   font-weight: bold; font-family: Verdana
262bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek } 
26322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border: 1px #000000 solid }
26422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek table.sortable { border-collapse: collapse; border-spacing: 0px }
2657f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek td { border-bottom: 1px #000000 dotted }
26622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td { padding:5px; padding-left:8px; padding-right:8px }
267d8c6d0c8a5f970240cc4cbf8eddeae037d1b29eaTed Kremenek td { text-align:left; font-size:9pt }
26822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek td.View   { padding-left: 10px }
2697f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</style>
27022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script>
2716e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript">
2726e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal)
2736e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{
2746e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  var Rows = document.getElementsByTagName("tr");
2756e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  for ( var i = 0 ; i < Rows.length; ++i ) {
2766e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    if (Rows[i].className == RowClass) {
2776e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek      Rows[i].style.display = DisplayVal;
2786e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
2796e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
2806e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek}
2816e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
2826e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) {
2836e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  window.console.log("writing");
2846e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  if (CheckButton.checked) {
2856e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    SetDisplay(ClassName, "");
2866e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
2876e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  else {
2886e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    SetDisplay(ClassName, "none");
2896e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
2906e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek}
2916e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script>
2926e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head>
2936e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body>
2946e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT
2956e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
2966e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the summary table.
2976e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
2986e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  my %Totals;
2996e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
3006e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  for my $row ( @Index ) {
3016e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    
3026e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    my $bug_type = lc($row->[1]);
3036e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    
3046e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    if (!defined($Totals{$bug_type})) {
3056e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek      $Totals{$bug_type} = 1;
3066e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
3076e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    else {
3086e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek      $Totals{$bug_type}++;
3096e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    }
3106e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
3116e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
3126e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT;
3136e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<h3>Summary</h3>
3146e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<table class="sortable">
3156e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<tr>
3166e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  <td>Bug Type</td>
3176e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  <td>Quantity</td>
3186e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  <td "sorttable_nosort">Display?</td>
3196e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</tr>
3206e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT
3216e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  
3226e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  for my $key ( sort { $a cmp $b } keys %Totals ) {
3236e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    my $x = $key;
3246e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    $x =~ s/\s/_/g;    
3256e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    print OUT "<tr><td>$key</td><td>$Totals{$key}</td><td><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></td></tr>\n";
3266e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  }
3276e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
3286e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek  # Print out the table of errors.
3296e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek
3306e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT;
3316e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table>
3326e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<h3>Reports</h3>
33322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<table class="sortable">
3347f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek<tr>
335bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>Bug Type</td>
336bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>File</td>
337bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>Line</td>
338bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td>Path Length</td>
339bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek  <td "sorttable_nosort"></td>
3407f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek</tr>
3415744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT
3429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
3435744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  for my $row ( sort { $a->[1] cmp $b->[1] } @Index ) {
3445744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
3456e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    my $x = lc($row->[1]);
3466e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    $x =~ s/\s/_/g;    
3476e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    
3486e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek    print OUT "<tr class=\"bt_$x\">\n";
3495744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek
3505744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    my $ReportFile = $row->[0];
3519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
35222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    print OUT " <td class=\"DESC\">";
35322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    print OUT lc($row->[1]);
35422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    print OUT "</td>\n";
3555744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
3565744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    for my $j ( 2 .. $#{$row} ) {
3575744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek      print OUT "<td>$row->[$j]</td>\n"
3585744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    }
3597f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
3607f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    # Emit the "View" link.
3617f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    
36222d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek    print OUT " <td class=\"View\"><a href=\"$ReportFile#EndPath\">View</a></td>\n";
3635744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    
3647f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    # End the row.
3655744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    print OUT "</tr>\n";
3665744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  }
3675744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  
3685744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  print OUT "</table>\n</body></html>\n";  
3695744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek  close(OUT);
37022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  
37122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  CopyJS($Dir);
372684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  
373684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  # Make sure $Dir and $BaseDir is world readable/executable.
374684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  `chmod 755 $Dir`;
375684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek  `chmod 755 $BaseDir`;
3769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
3779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
3789cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
379dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command.
380dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------##
381dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek
382dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremeneksub RunBuildCommand {
383dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
384dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  my $Args = shift;
3857442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek  my $IgnoreErrors = shift;
386dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  my $Cmd = $Args->[0];
387dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
3886a43ba9cd247811b6d48ffbd4ee3c911c8c4b458Ted Kremenek  if ($Cmd eq "gcc" or $Cmd eq "cc" or $Cmd eq "llvm-gcc") {
389dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek    shift @$Args;
390dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek    unshift @$Args, "ccc-analyzer"
391dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  }
3927442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek  elsif ($IgnoreErrors) {
3937442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    if ($Cmd eq "make" or $Cmd eq "gmake") {
3947442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek      push @$Args, "-k";
3957442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    }
3967442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    elsif ($Cmd eq "xcodebuild") {
3977442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek      push @$Args, "-PBXBuildsContinueAfterErrors=YES";
3987442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek    }
39922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek  }  
400dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  
401dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  system(@$Args);
402dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek}
403dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek
404dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------##
4059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options.
4069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
4079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
408a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp {
4099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4105744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT;
411a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options]
4122b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
4132b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS:
4142b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
4152b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek  -o            - Target directory for HTML report files.  Subdirectories
416a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop                  will be created as needed to represent separate "runs" of
4172b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek                  the analyzer.  If this option is not specified, a directory
4182b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek                  is created in /tmp to store the reports.
4192b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek                
42010f883fe7ef74139f8778e49acacf0ce408e7088Ted Kremenek  -h            - Display this message.
4212b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek  --help
4222b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek  
423af08f64abc38af5914d96106aeb014a2e06eb865Ted Kremenek  -k            - Add a "keep on going" option to the specified build command.
424f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek  --keep-going    This option currently supports make and xcodebuild.
425f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek                  This is a convenience option; one can specify this
426f02e8dbf7e3bddac4efec77b0ea3f07b26eaa955Ted Kremenek                  behavior directly using build options.
4272b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
428dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek  -v            - Verbose output from $Prog and the analyzer.
429dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek                  A second "-v" increases verbosity.
4302b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
4317f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  -V            - View analysis results in a web browser when the build
4327f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  --view          completes.
4337f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
4342b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS
4352b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
43639eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek  You can specify any build option acceptable to the build command.
43739eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek
4385744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE
4392b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
4405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek    $Prog -o /tmp/myhtmldir make -j4
4412b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek     
44239eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek  The above example causes analysis reports to be deposited into
44339eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek  a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option.
44439eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek  A different subdirectory is created each time $Prog analyzes a project.
44539eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek  The analyzer should support most parallel builds, but not distributed builds.
4462b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek
4472b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT
4489cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
4499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
4509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
4519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments.
4529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------##
4539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
4549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir;           # Parent directory to store HTML files.
4559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0;  # Ignore build errors.
4567f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults  = 0;  # View results when the build terminates.
4579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
4589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) {
4599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  DisplayHelp();
460a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  exit 1;
4619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
4629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
4639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) {
4649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  # Scan for options we recognize.
4669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4679cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  my $arg = $ARGV[0];
4689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
4692f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop  if ($arg eq "-h" or $arg eq "--help") {
4709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    DisplayHelp();
471a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop    exit 0;
4729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
4739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($arg eq "-o") {
4759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
4769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek        
4779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    if (!@ARGV) {
4780062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek      die "$Prog: '-o' option requires a target directory name.\n";
4799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    }
4809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    
4819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $HtmlDir = shift @ARGV;
4829cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
4839cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
4849cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4852b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek  if ($arg eq "-k" or $arg eq "--keep-going") {
4869cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
4879cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $IgnoreErrors = 1;
4889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
4899cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
4909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if ($arg eq "-v") {
4929cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    shift @ARGV;
4939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    $Verbose++;
4949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    next;
4959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
4969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
4977f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  if ($arg eq "-V" or $arg eq "--view") {
4987f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    shift @ARGV;
4997f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    $ViewResults = 1;    
5007f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek    next;
5017f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  }
5027f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  
5030062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek  die "$Prog: unrecognized option '$arg'\n" if ($arg =~ /^-/);
5040062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek  
5059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  last;
5069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
5079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) {
5099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  print STDERR "$Prog: No build command specified.\n\n";
5109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  DisplayHelp();
511a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  exit 1;
5129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
5139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports.
5159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!defined($HtmlDir)) {
5179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
518a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop  $HtmlDir = mkdtemp("/tmp/$Prog-XXXXXX");
5199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
5209cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (!defined($HtmlDir)) {
521a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop    die "error: Cannot create HTML directory in /tmp.\n";
5229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
5239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  
5249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  if (!$Verbose) {
5259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek    print "$Prog: Using '$HtmlDir' as base HTML report directory.\n";
5269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  }
5279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
5289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
529684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir;
530a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir);
5319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5329cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Set the appropriate environment variables.
5339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
534a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopSetHtmlEnv(\@ARGV, $HtmlDir);
5359cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5360b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekmy $Cmd = "$RealBin/ccc-analyzer";
5370b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek
5380b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenekdie "$Prog: Executable 'ccc-analyzer' does not exist at '$Cmd'\n"
5390b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek  if (! -x $Cmd);
540f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek  
541f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenekmy $Clang = "$RealBin/clang";
542f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek
543f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenekif (! -x $Clang) {
544f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek  print "$Prog: 'clang' executable not found in '$RealBin'.  Using 'clang' from path.\n";
545f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek  $Clang = "clang";
546f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek}
5470b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek
5484f4b17da43d3be87a248e1e10bf0b7d8b5891efdTed Kremenek$ENV{'CC'} = $Cmd;
549f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek$ENV{'CLANG'} = $Clang;
5509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif ($Verbose >= 2) {
5529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek  $ENV{'CCC_ANALYZER_VERBOSE'} = 1;
5539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek}
5549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build.
5569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5577442ca6b274f1a935c31e34221fbd0a68077ddc5Ted KremenekRunBuildCommand(\@ARGV, $IgnoreErrors);
5589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
5599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess the HTML directory.
5609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek
561684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted KremenekPostprocess($HtmlDir, $BaseDir);
5627f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek
5637f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekif ($ViewResults and -r "$HtmlDir/index.html") {
5647f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  # Only works on Mac OS X (for now).
5657f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  print "Viewing analysis results: '$HtmlDir/index.html'\n";
5667f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek  `open $HtmlDir/index.html`
5677f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek}
568