diff options
Diffstat (limited to 'contrib/llvm/tools/clang/tools/scan-build')
6 files changed, 0 insertions, 2559 deletions
diff --git a/contrib/llvm/tools/clang/tools/scan-build/c++-analyzer b/contrib/llvm/tools/clang/tools/scan-build/c++-analyzer deleted file mode 120000 index ca10bf5..0000000 --- a/contrib/llvm/tools/clang/tools/scan-build/c++-analyzer +++ /dev/null @@ -1 +0,0 @@ -ccc-analyzer
\ No newline at end of file diff --git a/contrib/llvm/tools/clang/tools/scan-build/ccc-analyzer b/contrib/llvm/tools/clang/tools/scan-build/ccc-analyzer deleted file mode 100755 index c182a68..0000000 --- a/contrib/llvm/tools/clang/tools/scan-build/ccc-analyzer +++ /dev/null @@ -1,661 +0,0 @@ -#!/usr/bin/env perl -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# A script designed to interpose between the build system and gcc. It invokes -# both gcc and the static analyzer. -# -##===----------------------------------------------------------------------===## - -use strict; -use warnings; -use FindBin; -use Cwd qw/ getcwd abs_path /; -use File::Temp qw/ tempfile /; -use File::Path qw / mkpath /; -use File::Basename; -use Text::ParseWords; - -##===----------------------------------------------------------------------===## -# Compiler command setup. -##===----------------------------------------------------------------------===## - -my $Compiler; -my $Clang; - -if ($FindBin::Script =~ /c\+\+-analyzer/) { - $Compiler = $ENV{'CCC_CXX'}; - if (!defined $Compiler) { $Compiler = "g++"; } - - $Clang = $ENV{'CLANG_CXX'}; - if (!defined $Clang) { $Clang = 'clang++'; } -} -else { - $Compiler = $ENV{'CCC_CC'}; - if (!defined $Compiler) { $Compiler = "gcc"; } - - $Clang = $ENV{'CLANG'}; - if (!defined $Clang) { $Clang = 'clang'; } -} - -##===----------------------------------------------------------------------===## -# Cleanup. -##===----------------------------------------------------------------------===## - -my $ReportFailures = $ENV{'CCC_REPORT_FAILURES'}; -if (!defined $ReportFailures) { $ReportFailures = 1; } - -my $CleanupFile; -my $ResultFile; - -# Remove any stale files at exit. -END { - if (defined $CleanupFile && -z $CleanupFile) { - `rm -f $CleanupFile`; - } -} - -##----------------------------------------------------------------------------## -# Process Clang Crashes. -##----------------------------------------------------------------------------## - -sub GetPPExt { - my $Lang = shift; - if ($Lang =~ /objective-c\+\+/) { return ".mii" }; - if ($Lang =~ /objective-c/) { return ".mi"; } - if ($Lang =~ /c\+\+/) { return ".ii"; } - return ".i"; -} - -# Set this to 1 if we want to include 'parser rejects' files. -my $IncludeParserRejects = 0; -my $ParserRejects = "Parser Rejects"; - -my $AttributeIgnored = "Attribute Ignored"; - -sub ProcessClangFailure { - my ($Clang, $Lang, $file, $Args, $HtmlDir, $ErrorType, $ofile) = @_; - my $Dir = "$HtmlDir/failures"; - mkpath $Dir; - - my $prefix = "clang_crash"; - if ($ErrorType eq $ParserRejects) { - $prefix = "clang_parser_rejects"; - } - elsif ($ErrorType eq $AttributeIgnored) { - $prefix = "clang_attribute_ignored"; - } - - # Generate the preprocessed file with Clang. - my ($PPH, $PPFile) = tempfile( $prefix . "_XXXXXX", - SUFFIX => GetPPExt($Lang), - DIR => $Dir); - system $Clang, @$Args, "-E", "-o", $PPFile; - close ($PPH); - - # Create the info file. - open (OUT, ">", "$PPFile.info.txt") or die "Cannot open $PPFile.info.txt\n"; - print OUT abs_path($file), "\n"; - print OUT "$ErrorType\n"; - print OUT "@$Args\n"; - close OUT; - `uname -a >> $PPFile.info.txt 2>&1`; - `$Compiler -v >> $PPFile.info.txt 2>&1`; - system 'mv',$ofile,"$PPFile.stderr.txt"; - return (basename $PPFile); -} - -##----------------------------------------------------------------------------## -# Running the analyzer. -##----------------------------------------------------------------------------## - -sub GetCCArgs { - my $Args = shift; - - pipe (FROM_CHILD, TO_PARENT); - my $pid = fork(); - if ($pid == 0) { - close FROM_CHILD; - open(STDOUT,">&", \*TO_PARENT); - open(STDERR,">&", \*TO_PARENT); - exec $Clang, "-###", "-fsyntax-only", @$Args; - } - close(TO_PARENT); - my $line; - while (<FROM_CHILD>) { - next if (!/-cc1/); - $line = $_; - } - - waitpid($pid,0); - close(FROM_CHILD); - - die "could not find clang line\n" if (!defined $line); - # Strip the newline and initial whitspace - chomp $line; - $line =~ s/^\s+//; - my @items = quotewords('\s+', 0, $line); - my $cmd = shift @items; - die "cannot find 'clang' in 'clang' command\n" if (!($cmd =~ /clang/)); - return \@items; -} - -sub Analyze { - my ($Clang, $Args, $AnalyzeArgs, $Lang, $Output, $Verbose, $HtmlDir, - $file, $Analyses) = @_; - - $Args = GetCCArgs($Args); - - my $RunAnalyzer = 0; - my $Cmd; - my @CmdArgs; - my @CmdArgsSansAnalyses; - - if ($Lang =~ /header/) { - exit 0 if (!defined ($Output)); - $Cmd = 'cp'; - push @CmdArgs,$file; - # Remove the PCH extension. - $Output =~ s/[.]gch$//; - push @CmdArgs,$Output; - @CmdArgsSansAnalyses = @CmdArgs; - } - else { - $Cmd = $Clang; - push @CmdArgs, "-cc1"; - push @CmdArgs,'-DIBOutlet=__attribute__((iboutlet))'; - push @CmdArgs, @$Args; - @CmdArgsSansAnalyses = @CmdArgs; - push @CmdArgs,'-analyze'; - push @CmdArgs,"-analyzer-display-progress"; - push @CmdArgs,"-analyzer-eagerly-assume"; - push @CmdArgs,"-analyzer-opt-analyze-nested-blocks"; - push @CmdArgs,(split /\s/,$Analyses); - - if (defined $ENV{"CCC_EXPERIMENTAL_CHECKS"}) { - push @CmdArgs,"-analyzer-experimental-internal-checks"; - push @CmdArgs,"-analyzer-experimental-checks"; - } - - $RunAnalyzer = 1; - } - - # Add the analysis arguments passed down from scan-build. - foreach my $Arg (@$AnalyzeArgs) { - push @CmdArgs, $Arg; - } - - my @PrintArgs; - my $dir; - - if ($RunAnalyzer) { - if (defined $ResultFile) { - push @CmdArgs,'-o'; - push @CmdArgs, $ResultFile; - } - elsif (defined $HtmlDir) { - push @CmdArgs,'-o'; - push @CmdArgs, $HtmlDir; - } - } - - if ($Verbose) { - $dir = getcwd(); - print STDERR "\n[LOCATION]: $dir\n"; - push @PrintArgs,"'$Cmd'"; - foreach my $arg (@CmdArgs) { push @PrintArgs,"\'$arg\'"; } - } - - if ($Verbose == 1) { - # We MUST print to stderr. Some clients use the stdout output of - # gcc for various purposes. - print STDERR join(' ',@PrintArgs); - print STDERR "\n"; - } - elsif ($Verbose == 2) { - print STDERR "#SHELL (cd '$dir' && @PrintArgs)\n"; - } - - if (defined $ENV{'CCC_UBI'}) { - push @CmdArgs,"--analyzer-viz-egraph-ubigraph"; - } - - # Capture the STDERR of clang and send it to a temporary file. - # Capture the STDOUT of clang and reroute it to ccc-analyzer's STDERR. - # We save the output file in the 'crashes' directory if clang encounters - # any problems with the file. - pipe (FROM_CHILD, TO_PARENT); - my $pid = fork(); - if ($pid == 0) { - close FROM_CHILD; - open(STDOUT,">&", \*TO_PARENT); - open(STDERR,">&", \*TO_PARENT); - exec $Cmd, @CmdArgs; - } - - close TO_PARENT; - my ($ofh, $ofile) = tempfile("clang_output_XXXXXX", DIR => $HtmlDir); - - while (<FROM_CHILD>) { - print $ofh $_; - print STDERR $_; - } - - waitpid($pid,0); - close(FROM_CHILD); - my $Result = $?; - - # Did the command die because of a signal? - if ($ReportFailures) { - if ($Result & 127 and $Cmd eq $Clang and defined $HtmlDir) { - ProcessClangFailure($Clang, $Lang, $file, \@CmdArgsSansAnalyses, - $HtmlDir, "Crash", $ofile); - } - elsif ($Result) { - if ($IncludeParserRejects && !($file =~/conftest/)) { - ProcessClangFailure($Clang, $Lang, $file, \@CmdArgsSansAnalyses, - $HtmlDir, $ParserRejects, $ofile); - } - } - else { - # Check if there were any unhandled attributes. - if (open(CHILD, $ofile)) { - my %attributes_not_handled; - - # Don't flag warnings about the following attributes that we - # know are currently not supported by Clang. - $attributes_not_handled{"cdecl"} = 1; - - my $ppfile; - while (<CHILD>) { - next if (! /warning: '([^\']+)' attribute ignored/); - - # Have we already spotted this unhandled attribute? - next if (defined $attributes_not_handled{$1}); - $attributes_not_handled{$1} = 1; - - # Get the name of the attribute file. - my $dir = "$HtmlDir/failures"; - my $afile = "$dir/attribute_ignored_$1.txt"; - - # Only create another preprocessed file if the attribute file - # doesn't exist yet. - next if (-e $afile); - - # Add this file to the list of files that contained this attribute. - # Generate a preprocessed file if we haven't already. - if (!(defined $ppfile)) { - $ppfile = ProcessClangFailure($Clang, $Lang, $file, - \@CmdArgsSansAnalyses, - $HtmlDir, $AttributeIgnored, $ofile); - } - - mkpath $dir; - open(AFILE, ">$afile"); - print AFILE "$ppfile\n"; - close(AFILE); - } - close CHILD; - } - } - } - - unlink($ofile); -} - -##----------------------------------------------------------------------------## -# Lookup tables. -##----------------------------------------------------------------------------## - -my %CompileOptionMap = ( - '-nostdinc' => 0, - '-fblocks' => 0, - '-fno-builtin' => 0, - '-fobjc-gc-only' => 0, - '-fobjc-gc' => 0, - '-ffreestanding' => 0, - '-include' => 1, - '-idirafter' => 1, - '-imacros' => 1, - '-iprefix' => 1, - '-iquote' => 1, - '-isystem' => 1, - '-iwithprefix' => 1, - '-iwithprefixbefore' => 1 -); - -my %LinkerOptionMap = ( - '-framework' => 1 -); - -my %CompilerLinkerOptionMap = ( - '-isysroot' => 1, - '-arch' => 1, - '-m32' => 0, - '-m64' => 0, - '-v' => 0, - '-fpascal-strings' => 0, - '-mmacosx-version-min' => 0, # This is really a 1 argument, but always has '=' - '-miphoneos-version-min' => 0 # This is really a 1 argument, but always has '=' -); - -my %IgnoredOptionMap = ( - '-MT' => 1, # Ignore these preprocessor options. - '-MF' => 1, - - '-fsyntax-only' => 0, - '-save-temps' => 0, - '-install_name' => 1, - '-exported_symbols_list' => 1, - '-current_version' => 1, - '-compatibility_version' => 1, - '-init' => 1, - '-e' => 1, - '-seg1addr' => 1, - '-bundle_loader' => 1, - '-multiply_defined' => 1, - '-sectorder' => 3, - '--param' => 1, - '-u' => 1 -); - -my %LangMap = ( - 'c' => 'c', - 'cp' => 'c++', - 'cpp' => 'c++', - 'cc' => 'c++', - 'i' => 'c-cpp-output', - 'm' => 'objective-c', - 'mi' => 'objective-c-cpp-output' -); - -my %UniqueOptions = ( - '-isysroot' => 0 -); - -##----------------------------------------------------------------------------## -# Languages accepted. -##----------------------------------------------------------------------------## - -my %LangsAccepted = ( - "objective-c" => 1, - "c" => 1 -); - -if (defined $ENV{'CCC_ANALYZER_CPLUSPLUS'}) { - $LangsAccepted{"c++"} = 1; - $LangsAccepted{"objective-c++"} = 1; -} - -##----------------------------------------------------------------------------## -# Main Logic. -##----------------------------------------------------------------------------## - -my $Action = 'link'; -my @CompileOpts; -my @LinkOpts; -my @Files; -my $Lang; -my $Output; -my %Uniqued; - -# Forward arguments to gcc. -my $Status = system($Compiler,@ARGV); -if ($Status) { exit($Status >> 8); } - -# Get the analysis options. -my $Analyses = $ENV{'CCC_ANALYZER_ANALYSIS'}; -if (!defined($Analyses)) { $Analyses = '-analyzer-check-objc-mem'; } - -# Get the store model. -my $StoreModel = $ENV{'CCC_ANALYZER_STORE_MODEL'}; -if (!defined $StoreModel) { $StoreModel = "region"; } - -# Get the constraints engine. -my $ConstraintsModel = $ENV{'CCC_ANALYZER_CONSTRAINTS_MODEL'}; -if (!defined $ConstraintsModel) { $ConstraintsModel = "range"; } - -# Get the output format. -my $OutputFormat = $ENV{'CCC_ANALYZER_OUTPUT_FORMAT'}; -if (!defined $OutputFormat) { $OutputFormat = "html"; } - -# Determine the level of verbosity. -my $Verbose = 0; -if (defined $ENV{CCC_ANALYZER_VERBOSE}) { $Verbose = 1; } -if (defined $ENV{CCC_ANALYZER_LOG}) { $Verbose = 2; } - -# Get the HTML output directory. -my $HtmlDir = $ENV{'CCC_ANALYZER_HTML'}; - -my %DisabledArchs = ('ppc' => 1, 'ppc64' => 1); -my %ArchsSeen; -my $HadArch = 0; - -# Process the arguments. -foreach (my $i = 0; $i < scalar(@ARGV); ++$i) { - my $Arg = $ARGV[$i]; - my ($ArgKey) = split /=/,$Arg,2; - - # Modes ccc-analyzer supports - if ($Arg =~ /^-(E|MM?)$/) { $Action = 'preprocess'; } - elsif ($Arg eq '-c') { $Action = 'compile'; } - elsif ($Arg =~ /^-print-prog-name/) { exit 0; } - - # Specially handle duplicate cases of -arch - if ($Arg eq "-arch") { - my $arch = $ARGV[$i+1]; - # We don't want to process 'ppc' because of Clang's lack of support - # for Altivec (also some #defines won't likely be defined correctly, etc.) - if (!(defined $DisabledArchs{$arch})) { $ArchsSeen{$arch} = 1; } - $HadArch = 1; - ++$i; - next; - } - - # Options with possible arguments that should pass through to compiler. - if (defined $CompileOptionMap{$ArgKey}) { - my $Cnt = $CompileOptionMap{$ArgKey}; - push @CompileOpts,$Arg; - while ($Cnt > 0) { ++$i; --$Cnt; push @CompileOpts, $ARGV[$i]; } - next; - } - - # Options with possible arguments that should pass through to linker. - if (defined $LinkerOptionMap{$ArgKey}) { - my $Cnt = $LinkerOptionMap{$ArgKey}; - push @LinkOpts,$Arg; - while ($Cnt > 0) { ++$i; --$Cnt; push @LinkOpts, $ARGV[$i]; } - next; - } - - # Options with possible arguments that should pass through to both compiler - # and the linker. - if (defined $CompilerLinkerOptionMap{$ArgKey}) { - my $Cnt = $CompilerLinkerOptionMap{$ArgKey}; - - # Check if this is an option that should have a unique value, and if so - # determine if the value was checked before. - if ($UniqueOptions{$Arg}) { - if (defined $Uniqued{$Arg}) { - $i += $Cnt; - next; - } - $Uniqued{$Arg} = 1; - } - - push @CompileOpts,$Arg; - push @LinkOpts,$Arg; - - while ($Cnt > 0) { - ++$i; --$Cnt; - push @CompileOpts, $ARGV[$i]; - push @LinkOpts, $ARGV[$i]; - } - next; - } - - # Ignored options. - if (defined $IgnoredOptionMap{$ArgKey}) { - my $Cnt = $IgnoredOptionMap{$ArgKey}; - while ($Cnt > 0) { - ++$i; --$Cnt; - } - next; - } - - # Compile mode flags. - if ($Arg =~ /^-[D,I,U](.*)$/) { - my $Tmp = $Arg; - if ($1 eq '') { - # FIXME: Check if we are going off the end. - ++$i; - $Tmp = $Arg . $ARGV[$i]; - } - push @CompileOpts,$Tmp; - next; - } - - # Language. - if ($Arg eq '-x') { - $Lang = $ARGV[$i+1]; - ++$i; next; - } - - # Output file. - if ($Arg eq '-o') { - ++$i; - $Output = $ARGV[$i]; - next; - } - - # Get the link mode. - if ($Arg =~ /^-[l,L,O]/) { - if ($Arg eq '-O') { push @LinkOpts,'-O1'; } - elsif ($Arg eq '-Os') { push @LinkOpts,'-O2'; } - else { push @LinkOpts,$Arg; } - next; - } - - if ($Arg =~ /^-std=/) { - push @CompileOpts,$Arg; - next; - } - -# if ($Arg =~ /^-f/) { -# # FIXME: Not sure if the remaining -fxxxx options have no arguments. -# push @CompileOpts,$Arg; -# push @LinkOpts,$Arg; # FIXME: Not sure if these are link opts. -# } - - # Get the compiler/link mode. - if ($Arg =~ /^-F(.+)$/) { - my $Tmp = $Arg; - if ($1 eq '') { - # FIXME: Check if we are going off the end. - ++$i; - $Tmp = $Arg . $ARGV[$i]; - } - push @CompileOpts,$Tmp; - push @LinkOpts,$Tmp; - next; - } - - # Input files. - if ($Arg eq '-filelist') { - # FIXME: Make sure we aren't walking off the end. - open(IN, $ARGV[$i+1]); - while (<IN>) { s/\015?\012//; push @Files,$_; } - close(IN); - ++$i; - next; - } - - # Handle -Wno-. We don't care about extra warnings, but - # we should suppress ones that we don't want to see. - if ($Arg =~ /^-Wno-/) { - push @CompileOpts, $Arg; - next; - } - - if (!($Arg =~ /^-/)) { - push @Files, $Arg; - next; - } -} - -if ($Action eq 'compile' or $Action eq 'link') { - my @Archs = keys %ArchsSeen; - # Skip the file if we don't support the architectures specified. - exit 0 if ($HadArch && scalar(@Archs) == 0); - - foreach my $file (@Files) { - # Determine the language for the file. - my $FileLang = $Lang; - - if (!defined($FileLang)) { - # Infer the language from the extension. - if ($file =~ /[.]([^.]+)$/) { - $FileLang = $LangMap{$1}; - } - } - - # FileLang still not defined? Skip the file. - next if (!defined $FileLang); - - # Language not accepted? - next if (!defined $LangsAccepted{$FileLang}); - - my @CmdArgs; - my @AnalyzeArgs; - - if ($FileLang ne 'unknown') { - push @CmdArgs,'-x'; - push @CmdArgs,$FileLang; - } - - if (defined $StoreModel) { - push @AnalyzeArgs, "-analyzer-store=$StoreModel"; - } - - if (defined $ConstraintsModel) { - push @AnalyzeArgs, "-analyzer-constraints=$ConstraintsModel"; - } - - if (defined $OutputFormat) { - push @AnalyzeArgs, "-analyzer-output=" . $OutputFormat; - if ($OutputFormat =~ /plist/) { - # Change "Output" to be a file. - my ($h, $f) = tempfile("report-XXXXXX", SUFFIX => ".plist", - DIR => $HtmlDir); - $ResultFile = $f; - $CleanupFile = $f; - } - } - - push @CmdArgs,@CompileOpts; - push @CmdArgs,$file; - - if (scalar @Archs) { - foreach my $arch (@Archs) { - my @NewArgs; - push @NewArgs, '-arch'; - push @NewArgs, $arch; - push @NewArgs, @CmdArgs; - Analyze($Clang, \@NewArgs, \@AnalyzeArgs, $FileLang, $Output, - $Verbose, $HtmlDir, $file, $Analyses); - } - } - else { - Analyze($Clang, \@CmdArgs, \@AnalyzeArgs, $FileLang, $Output, - $Verbose, $HtmlDir, $file, $Analyses); - } - } -} - -exit($Status >> 8); - diff --git a/contrib/llvm/tools/clang/tools/scan-build/scan-build b/contrib/llvm/tools/clang/tools/scan-build/scan-build deleted file mode 100755 index 8a7afbb..0000000 --- a/contrib/llvm/tools/clang/tools/scan-build/scan-build +++ /dev/null @@ -1,1265 +0,0 @@ -#!/usr/bin/env perl -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# A script designed to wrap a build so that all calls to gcc are intercepted -# and piped to the static analyzer. -# -##===----------------------------------------------------------------------===## - -use strict; -use warnings; -use FindBin qw($RealBin); -use Digest::MD5; -use File::Basename; -use Term::ANSIColor; -use Term::ANSIColor qw(:constants); -use Cwd qw/ getcwd abs_path /; -use Sys::Hostname; - -my $Verbose = 0; # Verbose output from this script. -my $Prog = "scan-build"; -my $BuildName; -my $BuildDate; - -my $TERM = $ENV{'TERM'}; -my $UseColor = (defined $TERM and $TERM eq 'xterm-color' and -t STDOUT - and defined $ENV{'SCAN_BUILD_COLOR'}); - -my $UserName = HtmlEscape(getpwuid($<) || 'unknown'); -my $HostName = HtmlEscape(hostname() || 'unknown'); -my $CurrentDir = HtmlEscape(getcwd()); -my $CurrentDirSuffix = basename($CurrentDir); - -my $CmdArgs; - -my $HtmlTitle; - -my $Date = localtime(); - -##----------------------------------------------------------------------------## -# Diagnostics -##----------------------------------------------------------------------------## - -sub Diag { - if ($UseColor) { - print BOLD, MAGENTA "$Prog: @_"; - print RESET; - } - else { - print "$Prog: @_"; - } -} - -sub DiagCrashes { - my $Dir = shift; - Diag ("The analyzer encountered problems on some source files.\n"); - Diag ("Preprocessed versions of these sources were deposited in '$Dir/failures'.\n"); - Diag ("Please consider submitting a bug report using these files:\n"); - Diag (" http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\n") -} - -sub DieDiag { - if ($UseColor) { - print BOLD, RED "$Prog: "; - print RESET, RED @_; - print RESET; - } - else { - print "$Prog: ", @_; - } - exit(0); -} - -##----------------------------------------------------------------------------## -# Some initial preprocessing of Clang options. -##----------------------------------------------------------------------------## - -# Find 'clang' -my $ClangSB = Cwd::realpath("$RealBin/bin/clang"); -if (!defined $ClangSB || ! -x $ClangSB) { - $ClangSB = Cwd::realpath("$RealBin/clang"); -} -my $Clang; -if (!defined $ClangSB || ! -x $ClangSB) { - # Default to looking for 'clang' in the path. - $Clang = `which clang`; - chomp $Clang; - if ($Clang eq "") { - DieDiag("No 'clang' executable found in path."); - } -} -else { - $Clang = $ClangSB; -} -my $ClangCXX = $Clang . "++"; - -my %AvailableAnalyses; - -# Query clang for analysis options. -open(PIPE, "-|", $Clang, "-cc1", "-help") or - DieDiag("Cannot execute '$Clang'\n"); - -while(<PIPE>) { - if (/(-analyzer-check-[^\s]+)/) { - $AvailableAnalyses{$1} = 1; - next; - } -} -close (PIPE); - -my %AnalysesDefaultEnabled = ( - '-analyzer-check-dead-stores' => 1, - '-analyzer-check-objc-mem' => 1, - '-analyzer-check-objc-methodsigs' => 1, - # Do not enable the missing -dealloc check by default. - # '-analyzer-check-objc-missing-dealloc' => 1, - '-analyzer-check-objc-unused-ivars' => 1, - '-analyzer-check-security-syntactic' => 1 -); - -##----------------------------------------------------------------------------## -# GetHTMLRunDir - Construct an HTML directory name for the current sub-run. -##----------------------------------------------------------------------------## - -sub GetHTMLRunDir { - die "Not enough arguments." if (@_ == 0); - my $Dir = shift @_; - my $TmpMode = 0; - if (!defined $Dir) { - if (`uname` =~ /Darwin/) { - $Dir = $ENV{'TMPDIR'}; - if (!defined $Dir) { $Dir = "/tmp"; } - } - else { - $Dir = "/tmp"; - } - $TmpMode = 1; - } - - # Chop off any trailing '/' characters. - while ($Dir =~ /\/$/) { chop $Dir; } - - # Get current date and time. - my @CurrentTime = localtime(); - my $year = $CurrentTime[5] + 1900; - my $day = $CurrentTime[3]; - my $month = $CurrentTime[4] + 1; - my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day); - - # Determine the run number. - my $RunNumber; - - if (-d $Dir) { - if (! -r $Dir) { - DieDiag("directory '$Dir' exists but is not readable.\n"); - } - # Iterate over all files in the specified directory. - my $max = 0; - opendir(DIR, $Dir); - my @FILES = grep { -d "$Dir/$_" } readdir(DIR); - closedir(DIR); - - foreach my $f (@FILES) { - # Strip the prefix '$Prog-' if we are dumping files to /tmp. - if ($TmpMode) { - next if (!($f =~ /^$Prog-(.+)/)); - $f = $1; - } - - my @x = split/-/, $f; - next if (scalar(@x) != 4); - next if ($x[0] != $year); - next if ($x[1] != $month); - next if ($x[2] != $day); - - if ($x[3] > $max) { - $max = $x[3]; - } - } - - $RunNumber = $max + 1; - } - else { - - if (-x $Dir) { - DieDiag("'$Dir' exists but is not a directory.\n"); - } - - if ($TmpMode) { - DieDiag("The directory '/tmp' does not exist or cannot be accessed.\n"); - } - - # $Dir does not exist. It will be automatically created by the - # clang driver. Set the run number to 1. - - $RunNumber = 1; - } - - die "RunNumber must be defined!" if (!defined $RunNumber); - - # Append the run number. - my $NewDir; - if ($TmpMode) { - $NewDir = "$Dir/$Prog-$DateString-$RunNumber"; - } - else { - $NewDir = "$Dir/$DateString-$RunNumber"; - } - system 'mkdir','-p',$NewDir; - return $NewDir; -} - -sub SetHtmlEnv { - - die "Wrong number of arguments." if (scalar(@_) != 2); - - my $Args = shift; - my $Dir = shift; - - die "No build command." if (scalar(@$Args) == 0); - - my $Cmd = $$Args[0]; - - if ($Cmd =~ /configure/) { - return; - } - - if ($Verbose) { - Diag("Emitting reports for this run to '$Dir'.\n"); - } - - $ENV{'CCC_ANALYZER_HTML'} = $Dir; -} - -##----------------------------------------------------------------------------## -# ComputeDigest - Compute a digest of the specified file. -##----------------------------------------------------------------------------## - -sub ComputeDigest { - my $FName = shift; - DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName); - - # Use Digest::MD5. We don't have to be cryptographically secure. We're - # just looking for duplicate files that come from a non-malicious source. - # We use Digest::MD5 because it is a standard Perl module that should - # come bundled on most systems. - open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n"); - binmode FILE; - my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest; - close(FILE); - - # Return the digest. - return $Result; -} - -##----------------------------------------------------------------------------## -# UpdatePrefix - Compute the common prefix of files. -##----------------------------------------------------------------------------## - -my $Prefix; - -sub UpdatePrefix { - my $x = shift; - my $y = basename($x); - $x =~ s/\Q$y\E$//; - - if (!defined $Prefix) { - $Prefix = $x; - return; - } - - chop $Prefix while (!($x =~ /^\Q$Prefix/)); -} - -sub GetPrefix { - return $Prefix; -} - -##----------------------------------------------------------------------------## -# UpdateInFilePath - Update the path in the report file. -##----------------------------------------------------------------------------## - -sub UpdateInFilePath { - my $fname = shift; - my $regex = shift; - my $newtext = shift; - - open (RIN, $fname) or die "cannot open $fname"; - open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp"; - - while (<RIN>) { - s/$regex/$newtext/; - print ROUT $_; - } - - close (ROUT); - close (RIN); - system("mv", "$fname.tmp", $fname); -} - -##----------------------------------------------------------------------------## -# ScanFile - Scan a report file for various identifying attributes. -##----------------------------------------------------------------------------## - -# Sometimes a source file is scanned more than once, and thus produces -# multiple error reports. We use a cache to solve this problem. - -my %AlreadyScanned; - -sub ScanFile { - - my $Index = shift; - my $Dir = shift; - my $FName = shift; - - # Compute a digest for the report file. Determine if we have already - # scanned a file that looks just like it. - - my $digest = ComputeDigest("$Dir/$FName"); - - if (defined $AlreadyScanned{$digest}) { - # Redundant file. Remove it. - system ("rm", "-f", "$Dir/$FName"); - return; - } - - $AlreadyScanned{$digest} = 1; - - # At this point the report file is not world readable. Make it happen. - system ("chmod", "644", "$Dir/$FName"); - - # Scan the report file for tags. - open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n"); - - my $BugType = ""; - my $BugFile = ""; - my $BugCategory; - my $BugPathLength = 1; - my $BugLine = 0; - - while (<IN>) { - last if (/<!-- BUGMETAEND -->/); - - if (/<!-- BUGTYPE (.*) -->$/) { - $BugType = $1; - } - elsif (/<!-- BUGFILE (.*) -->$/) { - $BugFile = abs_path($1); - UpdatePrefix($BugFile); - } - elsif (/<!-- BUGPATHLENGTH (.*) -->$/) { - $BugPathLength = $1; - } - elsif (/<!-- BUGLINE (.*) -->$/) { - $BugLine = $1; - } - elsif (/<!-- BUGCATEGORY (.*) -->$/) { - $BugCategory = $1; - } - } - - close(IN); - - if (!defined $BugCategory) { - $BugCategory = "Other"; - } - - push @$Index,[ $FName, $BugCategory, $BugType, $BugFile, $BugLine, - $BugPathLength ]; -} - -##----------------------------------------------------------------------------## -# CopyFiles - Copy resource files to target directory. -##----------------------------------------------------------------------------## - -sub CopyFiles { - - my $Dir = shift; - - my $JS = Cwd::realpath("$RealBin/sorttable.js"); - - DieDiag("Cannot find 'sorttable.js'.\n") - if (! -r $JS); - - system ("cp", $JS, "$Dir"); - - DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n") - if (! -r "$Dir/sorttable.js"); - - my $CSS = Cwd::realpath("$RealBin/scanview.css"); - - DieDiag("Cannot find 'scanview.css'.\n") - if (! -r $CSS); - - system ("cp", $CSS, "$Dir"); - - DieDiag("Could not copy 'scanview.css' to '$Dir'.\n") - if (! -r $CSS); -} - -##----------------------------------------------------------------------------## -# Postprocess - Postprocess the results of an analysis scan. -##----------------------------------------------------------------------------## - -sub Postprocess { - - my $Dir = shift; - my $BaseDir = shift; - - die "No directory specified." if (!defined $Dir); - - if (! -d $Dir) { - Diag("No bugs found.\n"); - return 0; - } - - opendir(DIR, $Dir); - my @files = grep { /^report-.*\.html$/ } readdir(DIR); - closedir(DIR); - - if (scalar(@files) == 0 and ! -e "$Dir/failures") { - Diag("Removing directory '$Dir' because it contains no reports.\n"); - system ("rm", "-fR", $Dir); - return 0; - } - - # Scan each report file and build an index. - my @Index; - foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); } - - # Scan the failures directory and use the information in the .info files - # to update the common prefix directory. - my @failures; - my @attributes_ignored; - if (-d "$Dir/failures") { - opendir(DIR, "$Dir/failures"); - @failures = grep { /[.]info.txt$/ && !/attribute_ignored/; } readdir(DIR); - closedir(DIR); - opendir(DIR, "$Dir/failures"); - @attributes_ignored = grep { /^attribute_ignored/; } readdir(DIR); - closedir(DIR); - foreach my $file (@failures) { - open IN, "$Dir/failures/$file" or DieDiag("cannot open $file\n"); - my $Path = <IN>; - if (defined $Path) { UpdatePrefix($Path); } - close IN; - } - } - - # Generate an index.html file. - my $FName = "$Dir/index.html"; - open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n"); - - # Print out the header. - -print OUT <<ENDTEXT; -<html> -<head> -<title>${HtmlTitle}</title> -<link type="text/css" rel="stylesheet" href="scanview.css"/> -<script src="sorttable.js"></script> -<script language='javascript' type="text/javascript"> -function SetDisplay(RowClass, DisplayVal) -{ - var Rows = document.getElementsByTagName("tr"); - for ( var i = 0 ; i < Rows.length; ++i ) { - if (Rows[i].className == RowClass) { - Rows[i].style.display = DisplayVal; - } - } -} - -function CopyCheckedStateToCheckButtons(SummaryCheckButton) { - var Inputs = document.getElementsByTagName("input"); - for ( var i = 0 ; i < Inputs.length; ++i ) { - if (Inputs[i].type == "checkbox") { - if(Inputs[i] != SummaryCheckButton) { - Inputs[i].checked = SummaryCheckButton.checked; - Inputs[i].onclick(); - } - } - } -} - -function returnObjById( id ) { - if (document.getElementById) - var returnVar = document.getElementById(id); - else if (document.all) - var returnVar = document.all[id]; - else if (document.layers) - var returnVar = document.layers[id]; - return returnVar; -} - -var NumUnchecked = 0; - -function ToggleDisplay(CheckButton, ClassName) { - if (CheckButton.checked) { - SetDisplay(ClassName, ""); - if (--NumUnchecked == 0) { - returnObjById("AllBugsCheck").checked = true; - } - } - else { - SetDisplay(ClassName, "none"); - NumUnchecked++; - returnObjById("AllBugsCheck").checked = false; - } -} -</script> -<!-- SUMMARYENDHEAD --> -</head> -<body> -<h1>${HtmlTitle}</h1> - -<table> -<tr><th>User:</th><td>${UserName}\@${HostName}</td></tr> -<tr><th>Working Directory:</th><td>${CurrentDir}</td></tr> -<tr><th>Command Line:</th><td>${CmdArgs}</td></tr> -<tr><th>Date:</th><td>${Date}</td></tr> -ENDTEXT - -print OUT "<tr><th>Version:</th><td>${BuildName} (${BuildDate})</td></tr>\n" - if (defined($BuildName) && defined($BuildDate)); - -print OUT <<ENDTEXT; -</table> -ENDTEXT - - if (scalar(@files)) { - # Print out the summary table. - my %Totals; - - for my $row ( @Index ) { - my $bug_type = ($row->[2]); - my $bug_category = ($row->[1]); - my $key = "$bug_category:$bug_type"; - - if (!defined $Totals{$key}) { $Totals{$key} = [1,$bug_category,$bug_type]; } - else { $Totals{$key}->[0]++; } - } - - print OUT "<h2>Bug Summary</h2>"; - - if (defined $BuildName) { - print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n" - } - - my $TotalBugs = scalar(@Index); -print OUT <<ENDTEXT; -<table> -<thead><tr><td>Bug Type</td><td>Quantity</td><td class="sorttable_nosort">Display?</td></tr></thead> -<tr style="font-weight:bold"><td class="SUMM_DESC">All Bugs</td><td class="Q">$TotalBugs</td><td><center><input type="checkbox" id="AllBugsCheck" onClick="CopyCheckedStateToCheckButtons(this);" checked/></center></td></tr> -ENDTEXT - - my $last_category; - - for my $key ( - sort { - my $x = $Totals{$a}; - my $y = $Totals{$b}; - my $res = $x->[1] cmp $y->[1]; - $res = $x->[2] cmp $y->[2] if ($res == 0); - $res - } keys %Totals ) - { - my $val = $Totals{$key}; - my $category = $val->[1]; - if (!defined $last_category or $last_category ne $category) { - $last_category = $category; - print OUT "<tr><th>$category</th><th colspan=2></th></tr>\n"; - } - my $x = lc $key; - $x =~ s/[ ,'":\/()]+/_/g; - print OUT "<tr><td class=\"SUMM_DESC\">"; - print OUT $val->[2]; - print OUT "</td><td class=\"Q\">"; - print OUT $val->[0]; - print OUT "</td><td><center><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></center></td></tr>\n"; - } - - # Print out the table of errors. - -print OUT <<ENDTEXT; -</table> -<h2>Reports</h2> - -<table class="sortable" style="table-layout:automatic"> -<thead><tr> - <td>Bug Group</td> - <td class="sorttable_sorted">Bug Type<span id="sorttable_sortfwdind"> ▾</span></td> - <td>File</td> - <td class="Q">Line</td> - <td class="Q">Path Length</td> - <td class="sorttable_nosort"></td> - <!-- REPORTBUGCOL --> -</tr></thead> -<tbody> -ENDTEXT - - my $prefix = GetPrefix(); - my $regex; - my $InFileRegex; - my $InFilePrefix = "File:</td><td>"; - - if (defined $prefix) { - $regex = qr/^\Q$prefix\E/is; - $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is; - } - - for my $row ( sort { $a->[2] cmp $b->[2] } @Index ) { - my $x = "$row->[1]:$row->[2]"; - $x = lc $x; - $x =~ s/[ ,'":\/()]+/_/g; - - my $ReportFile = $row->[0]; - - print OUT "<tr class=\"bt_$x\">"; - print OUT "<td class=\"DESC\">"; - print OUT $row->[1]; - print OUT "</td>"; - print OUT "<td class=\"DESC\">"; - print OUT $row->[2]; - print OUT "</td>"; - - # Update the file prefix. - my $fname = $row->[3]; - - if (defined $regex) { - $fname =~ s/$regex//; - UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix) - } - - print OUT "<td>"; - my @fname = split /\//,$fname; - if ($#fname > 0) { - while ($#fname >= 0) { - my $x = shift @fname; - print OUT $x; - if ($#fname >= 0) { - print OUT "<span class=\"W\"> </span>/"; - } - } - } - else { - print OUT $fname; - } - print OUT "</td>"; - - # Print out the quantities. - for my $j ( 4 .. 5 ) { - print OUT "<td class=\"Q\">$row->[$j]</td>"; - } - - # Print the rest of the columns. - for (my $j = 6; $j <= $#{$row}; ++$j) { - print OUT "<td>$row->[$j]</td>" - } - - # Emit the "View" link. - print OUT "<td><a href=\"$ReportFile#EndPath\">View Report</a></td>"; - - # Emit REPORTBUG markers. - print OUT "\n<!-- REPORTBUG id=\"$ReportFile\" -->\n"; - - # End the row. - print OUT "</tr>\n"; - } - - print OUT "</tbody>\n</table>\n\n"; - } - - if (scalar (@failures) || scalar(@attributes_ignored)) { - print OUT "<h2>Analyzer Failures</h2>\n"; - - if (scalar @attributes_ignored) { - print OUT "The analyzer's parser ignored the following attributes:<p>\n"; - print OUT "<table>\n"; - print OUT "<thead><tr><td>Attribute</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>\n"; - foreach my $file (sort @attributes_ignored) { - die "cannot demangle attribute name\n" if (! ($file =~ /^attribute_ignored_(.+).txt/)); - my $attribute = $1; - # Open the attribute file to get the first file that failed. - next if (!open (ATTR, "$Dir/failures/$file")); - my $ppfile = <ATTR>; - chomp $ppfile; - close ATTR; - next if (! -e "$Dir/failures/$ppfile"); - # Open the info file and get the name of the source file. - open (INFO, "$Dir/failures/$ppfile.info.txt") or - die "Cannot open $Dir/failures/$ppfile.info.txt\n"; - my $srcfile = <INFO>; - chomp $srcfile; - close (INFO); - # Print the information in the table. - my $prefix = GetPrefix(); - if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; } - print OUT "<tr><td>$attribute</td><td>$srcfile</td><td><a href=\"failures/$ppfile\">$ppfile</a></td><td><a href=\"failures/$ppfile.stderr.txt\">$ppfile.stderr.txt</a></td></tr>\n"; - my $ppfile_clang = $ppfile; - $ppfile_clang =~ s/[.](.+)$/.clang.$1/; - print OUT " <!-- REPORTPROBLEM src=\"$srcfile\" file=\"failures/$ppfile\" clangfile=\"failures/$ppfile_clang\" stderr=\"failures/$ppfile.stderr.txt\" info=\"failures/$ppfile.info.txt\" -->\n"; - } - print OUT "</table>\n"; - } - - if (scalar @failures) { - print OUT "<p>The analyzer had problems processing the following files:</p>\n"; - print OUT "<table>\n"; - print OUT "<thead><tr><td>Problem</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>\n"; - foreach my $file (sort @failures) { - $file =~ /(.+).info.txt$/; - # Get the preprocessed file. - my $ppfile = $1; - # Open the info file and get the name of the source file. - open (INFO, "$Dir/failures/$file") or - die "Cannot open $Dir/failures/$file\n"; - my $srcfile = <INFO>; - chomp $srcfile; - my $problem = <INFO>; - chomp $problem; - close (INFO); - # Print the information in the table. - my $prefix = GetPrefix(); - if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; } - print OUT "<tr><td>$problem</td><td>$srcfile</td><td><a href=\"failures/$ppfile\">$ppfile</a></td><td><a href=\"failures/$ppfile.stderr.txt\">$ppfile.stderr.txt</a></td></tr>\n"; - my $ppfile_clang = $ppfile; - $ppfile_clang =~ s/[.](.+)$/.clang.$1/; - print OUT " <!-- REPORTPROBLEM src=\"$srcfile\" file=\"failures/$ppfile\" clangfile=\"failures/$ppfile_clang\" stderr=\"failures/$ppfile.stderr.txt\" info=\"failures/$ppfile.info.txt\" -->\n"; - } - print OUT "</table>\n"; - } - print OUT "<p>Please consider submitting preprocessed files as <a href=\"http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\">bug reports</a>. <!-- REPORTCRASHES --> </p>\n"; - } - - print OUT "</body></html>\n"; - close(OUT); - CopyFiles($Dir); - - # Make sure $Dir and $BaseDir are world readable/executable. - system("chmod", "755", $Dir); - if (defined $BaseDir) { system("chmod", "755", $BaseDir); } - - my $Num = scalar(@Index); - Diag("$Num bugs found.\n"); - if ($Num > 0 && -r "$Dir/index.html") { - Diag("Run 'scan-view $Dir' to examine bug reports.\n"); - } - - DiagCrashes($Dir) if (scalar @failures || scalar @attributes_ignored); - - return $Num; -} - -##----------------------------------------------------------------------------## -# RunBuildCommand - Run the build command. -##----------------------------------------------------------------------------## - -sub AddIfNotPresent { - my $Args = shift; - my $Arg = shift; - my $found = 0; - - foreach my $k (@$Args) { - if ($k eq $Arg) { - $found = 1; - last; - } - } - - if ($found == 0) { - push @$Args, $Arg; - } -} - -sub RunBuildCommand { - - my $Args = shift; - my $IgnoreErrors = shift; - my $Cmd = $Args->[0]; - my $CCAnalyzer = shift; - my $CXXAnalyzer = shift; - - # Get only the part of the command after the last '/'. - if ($Cmd =~ /\/([^\/]+)$/) { - $Cmd = $1; - } - - if ($Cmd =~ /(.*\/?gcc[^\/]*$)/ or - $Cmd =~ /(.*\/?cc[^\/]*$)/ or - $Cmd =~ /(.*\/?llvm-gcc[^\/]*$)/ or - $Cmd =~ /(.*\/?ccc-analyzer[^\/]*$)/) { - - if (!($Cmd =~ /ccc-analyzer/) and !defined $ENV{"CCC_CC"}) { - $ENV{"CCC_CC"} = $1; - } - - shift @$Args; - unshift @$Args, $CCAnalyzer; - } - elsif ($Cmd =~ /(.*\/?g\+\+[^\/]*$)/ or - $Cmd =~ /(.*\/?c\+\+[^\/]*$)/ or - $Cmd =~ /(.*\/?llvm-g\+\+[^\/]*$)/ or - $Cmd =~ /(.*\/?c\+\+-analyzer[^\/]*$)/) { - if (!($Cmd =~ /c\+\+-analyzer/) and !defined $ENV{"CCC_CXX"}) { - $ENV{"CCC_CXX"} = $1; - } - shift @$Args; - unshift @$Args, $CXXAnalyzer; - } - elsif ($IgnoreErrors) { - if ($Cmd eq "make" or $Cmd eq "gmake") { - AddIfNotPresent($Args, "CC=$CCAnalyzer"); - AddIfNotPresent($Args, "CXX=$CXXAnalyzer"); - AddIfNotPresent($Args,"-k"); - AddIfNotPresent($Args,"-i"); - } - elsif ($Cmd eq "xcodebuild") { - AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES"); - } - } - - if ($Cmd eq "xcodebuild") { - # Check if using iPhone SDK 3.0 (simulator). If so the compiler being - # used should be gcc-4.2. - if (!defined $ENV{"CCC_CC"}) { - for (my $i = 0 ; $i < scalar(@$Args); ++$i) { - if ($Args->[$i] eq "-sdk" && $i + 1 < scalar(@$Args)) { - if (@$Args[$i+1] =~ /^iphonesimulator3/) { - $ENV{"CCC_CC"} = "gcc-4.2"; - $ENV{"CCC_CXX"} = "g++-4.2"; - } - } - } - } - - # Disable distributed builds for xcodebuild. - AddIfNotPresent($Args,"-nodistribute"); - - # Disable PCH files until clang supports them. - AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO"); - - # When 'CC' is set, xcodebuild uses it to do all linking, even if we are - # linking C++ object files. Set 'LDPLUSPLUS' so that xcodebuild uses 'g++' - # (via c++-analyzer) when linking such files. - $ENV{"LDPLUSPLUS"} = $CXXAnalyzer; - } - - return (system(@$Args) >> 8); -} - -##----------------------------------------------------------------------------## -# DisplayHelp - Utility function to display all help options. -##----------------------------------------------------------------------------## - -sub DisplayHelp { - -print <<ENDTEXT; -USAGE: $Prog [options] <build command> [build options] - -ENDTEXT - - if (defined $BuildName) { - print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n"; - } - -print <<ENDTEXT; -OPTIONS: - - -analyze-headers - Also analyze functions in #included files. - - --experimental-checks - Enable experimental checks that are currently in heavy testing - - -o - Target directory for HTML report files. Subdirectories - will be created as needed to represent separate "runs" of - the analyzer. If this option is not specified, a directory - is created in /tmp (TMPDIR on Mac OS X) to store the reports. - - -h - Display this message. - --help - - -k - Add a "keep on going" option to the specified build command. - --keep-going This option currently supports make and xcodebuild. - This is a convenience option; one can specify this - behavior directly using build options. - - --html-title [title] - Specify the title used on generated HTML pages. - --html-title=[title] If not specified, a default title will be used. - - -plist - By default the output of scan-build is a set of HTML files. - This option outputs the results as a set of .plist files. - - --status-bugs - By default, the exit status of $Prog is the same as the - executed build command. Specifying this option causes the - exit status of $Prog to be 1 if it found potential bugs - and 0 otherwise. - - --use-cc [compiler path] - By default, $Prog uses 'gcc' to compile and link - --use-cc=[compiler path] your C and Objective-C code. Use this option - to specify an alternate compiler. - - --use-c++ [compiler path] - By default, $Prog uses 'g++' to compile and link - --use-c++=[compiler path] your C++ and Objective-C++ code. Use this option - to specify an alternate compiler. - - -v - Verbose output from $Prog and the analyzer. - A second and third '-v' increases verbosity. - - -V - View analysis results in a web browser when the build - --view completes. - -ADVANCED OPTIONS: - - -constraints [model] - Specify the contraint engine used by the analyzer. - By default the 'range' model is used. Specifying - 'basic' uses a simpler, less powerful constraint model - used by checker-0.160 and earlier. - - -store [model] - Specify the store model used by the analyzer. By default, - the 'region' store model is used. 'region' specifies a field- - sensitive store model. Users can also specify 'basic', which - is far less precise but can more quickly analyze code. - 'basic' was the default store model for checker-0.221 and - earlier. - - -no-failure-reports - Do not create a 'failures' subdirectory that includes - analyzer crash reports and preprocessed source files. - -AVAILABLE ANALYSES (multiple analyses may be specified): - -ENDTEXT - - foreach my $Analysis (sort keys %AvailableAnalyses) { - if (defined $AnalysesDefaultEnabled{$Analysis}) { - print " (+)"; - } - else { - print " "; - } - - print " $Analysis\n"; - } - -print <<ENDTEXT - - NOTE: "(+)" indicates that an analysis is enabled by default unless one - or more analysis options are specified - -BUILD OPTIONS - - You can specify any build option acceptable to the build command. - -EXAMPLE - - $Prog -o /tmp/myhtmldir make -j4 - - The above example causes analysis reports to be deposited into - a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option. - A different subdirectory is created each time $Prog analyzes a project. - The analyzer should support most parallel builds, but not distributed builds. - -ENDTEXT -} - -##----------------------------------------------------------------------------## -# HtmlEscape - HTML entity encode characters that are special in HTML -##----------------------------------------------------------------------------## - -sub HtmlEscape { - # copy argument to new variable so we don't clobber the original - my $arg = shift || ''; - my $tmp = $arg; - $tmp =~ s/&/&/g; - $tmp =~ s/</</g; - $tmp =~ s/>/>/g; - return $tmp; -} - -##----------------------------------------------------------------------------## -# ShellEscape - backslash escape characters that are special to the shell -##----------------------------------------------------------------------------## - -sub ShellEscape { - # copy argument to new variable so we don't clobber the original - my $arg = shift || ''; - if ($arg =~ /["\s]/) { return "'" . $arg . "'"; } - return $arg; -} - -##----------------------------------------------------------------------------## -# Process command-line arguments. -##----------------------------------------------------------------------------## - -my $AnalyzeHeaders = 0; -my $HtmlDir; # Parent directory to store HTML files. -my $IgnoreErrors = 0; # Ignore build errors. -my $ViewResults = 0; # View results when the build terminates. -my $ExitStatusFoundBugs = 0; # Exit status reflects whether bugs were found -my @AnalysesToRun; -my $StoreModel; -my $ConstraintsModel; -my $OutputFormat = "html"; - -if (!@ARGV) { - DisplayHelp(); - exit 1; -} - -while (@ARGV) { - - # Scan for options we recognize. - - my $arg = $ARGV[0]; - - if ($arg eq "-h" or $arg eq "--help") { - DisplayHelp(); - exit 0; - } - - if ($arg eq '-analyze-headers') { - shift @ARGV; - $AnalyzeHeaders = 1; - next; - } - - if (defined $AvailableAnalyses{$arg}) { - shift @ARGV; - push @AnalysesToRun, $arg; - next; - } - - if ($arg eq "-o") { - shift @ARGV; - - if (!@ARGV) { - DieDiag("'-o' option requires a target directory name.\n"); - } - - # Construct an absolute path. Uses the current working directory - # as a base if the original path was not absolute. - $HtmlDir = abs_path(shift @ARGV); - - next; - } - - if ($arg =~ /^--html-title(=(.+))?$/) { - shift @ARGV; - - if (!defined $2 || $2 eq '') { - if (!@ARGV) { - DieDiag("'--html-title' option requires a string.\n"); - } - - $HtmlTitle = shift @ARGV; - } else { - $HtmlTitle = $2; - } - - next; - } - - if ($arg eq "-k" or $arg eq "--keep-going") { - shift @ARGV; - $IgnoreErrors = 1; - next; - } - - if ($arg eq "--experimental-checks") { - shift @ARGV; - $ENV{"CCC_EXPERIMENTAL_CHECKS"} = 1; - next; - } - - if ($arg =~ /^--use-cc(=(.+))?$/) { - shift @ARGV; - my $cc; - - if (!defined $2 || $2 eq "") { - if (!@ARGV) { - DieDiag("'--use-cc' option requires a compiler executable name.\n"); - } - $cc = shift @ARGV; - } - else { - $cc = $2; - } - - $ENV{"CCC_CC"} = $cc; - next; - } - - if ($arg =~ /^--use-c\+\+(=(.+))?$/) { - shift @ARGV; - my $cxx; - - if (!defined $2 || $2 eq "") { - if (!@ARGV) { - DieDiag("'--use-c++' option requires a compiler executable name.\n"); - } - $cxx = shift @ARGV; - } - else { - $cxx = $2; - } - - $ENV{"CCC_CXX"} = $cxx; - next; - } - - if ($arg eq "-v") { - shift @ARGV; - $Verbose++; - next; - } - - if ($arg eq "-V" or $arg eq "--view") { - shift @ARGV; - $ViewResults = 1; - next; - } - - if ($arg eq "--status-bugs") { - shift @ARGV; - $ExitStatusFoundBugs = 1; - next; - } - - if ($arg eq "-store") { - shift @ARGV; - $StoreModel = shift @ARGV; - next; - } - - if ($arg eq "-constraints") { - shift @ARGV; - $ConstraintsModel = shift @ARGV; - next; - } - - if ($arg eq "-plist") { - shift @ARGV; - $OutputFormat = "plist"; - next; - } - if ($arg eq "-plist-html") { - shift @ARGV; - $OutputFormat = "plist-html"; - next; - } - - if ($arg eq "-no-failure-reports") { - $ENV{"CCC_REPORT_FAILURES"} = 0; - next; - } - - DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/); - - last; -} - -if (!@ARGV) { - Diag("No build command specified.\n\n"); - DisplayHelp(); - exit 1; -} - -$CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV))); -$HtmlTitle = "${CurrentDirSuffix} - scan-build results" - unless (defined($HtmlTitle)); - -# Determine the output directory for the HTML reports. -my $BaseDir = $HtmlDir; -$HtmlDir = GetHTMLRunDir($HtmlDir); - -# Set the appropriate environment variables. -SetHtmlEnv(\@ARGV, $HtmlDir); - -my $AbsRealBin = Cwd::realpath($RealBin); -my $Cmd = "$AbsRealBin/libexec/ccc-analyzer"; -my $CmdCXX = "$AbsRealBin/libexec/c++-analyzer"; - -if (!defined $Cmd || ! -x $Cmd) { - $Cmd = "$AbsRealBin/ccc-analyzer"; - DieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n") if(! -x $Cmd); -} -if (!defined $CmdCXX || ! -x $CmdCXX) { - $CmdCXX = "$AbsRealBin/c++-analyzer"; - DieDiag("Executable 'c++-analyzer' does not exist at '$CmdCXX'\n") if(! -x $CmdCXX); -} - -if (!defined $ClangSB || ! -x $ClangSB) { - Diag("'clang' executable not found in '$RealBin/bin'.\n"); - Diag("Using 'clang' from path: $Clang\n"); -} - -$ENV{'CC'} = $Cmd; -$ENV{'CXX'} = $CmdCXX; -$ENV{'CLANG'} = $Clang; -$ENV{'CLANG_CXX'} = $ClangCXX; - -if ($Verbose >= 2) { - $ENV{'CCC_ANALYZER_VERBOSE'} = 1; -} - -if ($Verbose >= 3) { - $ENV{'CCC_ANALYZER_LOG'} = 1; -} - -if (scalar(@AnalysesToRun) == 0) { - foreach my $key (keys %AnalysesDefaultEnabled) { - push @AnalysesToRun,$key; - } -} - -if ($AnalyzeHeaders) { - push @AnalysesToRun,"-analyzer-opt-analyze-headers"; -} - -$ENV{'CCC_ANALYZER_ANALYSIS'} = join ' ',@AnalysesToRun; - -if (defined $StoreModel) { - $ENV{'CCC_ANALYZER_STORE_MODEL'} = $StoreModel; -} - -if (defined $ConstraintsModel) { - $ENV{'CCC_ANALYZER_CONSTRAINTS_MODEL'} = $ConstraintsModel; -} - -if (defined $OutputFormat) { - $ENV{'CCC_ANALYZER_OUTPUT_FORMAT'} = $OutputFormat; -} - -# Run the build. -my $ExitStatus = RunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd, $CmdCXX); - -if (defined $OutputFormat) { - if ($OutputFormat =~ /plist/) { - Diag "Analysis run complete.\n"; - Diag "Analysis results (plist files) deposited in '$HtmlDir'\n"; - } - elsif ($OutputFormat =~ /html/) { - # Postprocess the HTML directory. - my $NumBugs = Postprocess($HtmlDir, $BaseDir); - - if ($ViewResults and -r "$HtmlDir/index.html") { - Diag "Analysis run complete.\n"; - Diag "Viewing analysis results in '$HtmlDir' using scan-view.\n"; - my $ScanView = Cwd::realpath("$RealBin/scan-view"); - if (! -x $ScanView) { $ScanView = "scan-view"; } - exec $ScanView, "$HtmlDir"; - } - - if ($ExitStatusFoundBugs) { - exit 1 if ($NumBugs > 0); - exit 0; - } - } -} - -exit $ExitStatus; - diff --git a/contrib/llvm/tools/clang/tools/scan-build/scanview.css b/contrib/llvm/tools/clang/tools/scan-build/scanview.css deleted file mode 100644 index a0406f3..0000000 --- a/contrib/llvm/tools/clang/tools/scan-build/scanview.css +++ /dev/null @@ -1,62 +0,0 @@ -body { color:#000000; background-color:#ffffff } -body { font-family: Helvetica, sans-serif; font-size:9pt } -h1 { font-size: 14pt; } -h2 { font-size: 12pt; } -table { font-size:9pt } -table { border-spacing: 0px; border: 1px solid black } -th, table thead { - background-color:#eee; color:#666666; - font-weight: bold; cursor: default; - text-align:center; - font-weight: bold; font-family: Verdana; - white-space:nowrap; -} -.W { font-size:0px } -th, td { padding:5px; padding-left:8px; text-align:left } -td.SUMM_DESC { padding-left:12px } -td.DESC { white-space:pre } -td.Q { text-align:right } -td { text-align:left } -tbody.scrollContent { overflow:auto } - -table.form_group { - background-color: #ccc; - border: 1px solid #333; - padding: 2px; -} - -table.form_inner_group { - background-color: #ccc; - border: 1px solid #333; - padding: 0px; -} - -table.form { - background-color: #999; - border: 1px solid #333; - padding: 2px; -} - -td.form_label { - text-align: right; - vertical-align: top; -} -/* For one line entires */ -td.form_clabel { - text-align: right; - vertical-align: center; -} -td.form_value { - text-align: left; - vertical-align: top; -} -td.form_submit { - text-align: right; - vertical-align: top; -} - -h1.SubmitFail { - color: #f00; -} -h1.SubmitOk { -} diff --git a/contrib/llvm/tools/clang/tools/scan-build/set-xcode-analyzer b/contrib/llvm/tools/clang/tools/scan-build/set-xcode-analyzer deleted file mode 100755 index cc068a5..0000000 --- a/contrib/llvm/tools/clang/tools/scan-build/set-xcode-analyzer +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python - -import os -import sys -import re -import tempfile -import shutil -import stat -from AppKit import * - -def FindClangSpecs(path): - for root, dirs, files in os.walk(path): - for f in files: - if f.endswith(".xcspec") and f.startswith("Clang LLVM"): - yield os.path.join(root, f) - -def ModifySpec(path, pathToChecker): - t = tempfile.NamedTemporaryFile(delete=False) - foundAnalyzer = False - with open(path) as f: - for line in f: - if not foundAnalyzer: - if line.find("Static Analyzer") >= 0: - foundAnalyzer = True - else: - m = re.search('^(\s*ExecPath\s*=\s*")', line) - if m: - line = "".join([m.group(0), pathToChecker, '";\n']) - t.write(line) - t.close() - print "(+) processing:", path - try: - shutil.copy(t.name, path) - os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) - except IOError, why: - print " (-) Cannot update file:", why, "\n" - except OSError, why: - print " (-) Cannot update file:", why, "\n" - os.unlink(t.name) - -def main(): - from optparse import OptionParser - parser = OptionParser('usage: %prog [options]') - parser.set_description(__doc__) - parser.add_option("--use-checker-build", dest="path", - help="Use the Clang located at the provided absolute path, e.g. /Users/foo/checker-1") - parser.add_option("--use-xcode-clang", action="store_const", - const="$(CLANG)", dest="default", - help="Use the Clang bundled with Xcode") - (options, args) = parser.parse_args() - if options.path is None and options.default is None: - parser.error("You must specify a version of Clang to use for static analysis. Specify '-h' for details") - - # determine if Xcode is running - for x in NSWorkspace.sharedWorkspace().runningApplications(): - if x.localizedName().find("Xcode") >= 0: - print "(-) You must quit Xcode first before modifying its configuration files." - return - - if options.path: - # Expand tildes. - path = os.path.expanduser(options.path) - if not path.endswith("clang"): - print "(+) Using Clang bundled with checker build:", path - path = os.path.join(path, "bin", "clang"); - else: - print "(+) Using Clang located at:", path - else: - print "(+) Using the Clang bundled with Xcode" - path = options.default - - for x in FindClangSpecs('/Developer'): - ModifySpec(x, path) - -if __name__ == '__main__': - main() - diff --git a/contrib/llvm/tools/clang/tools/scan-build/sorttable.js b/contrib/llvm/tools/clang/tools/scan-build/sorttable.js deleted file mode 100644 index 4352d3b..0000000 --- a/contrib/llvm/tools/clang/tools/scan-build/sorttable.js +++ /dev/null @@ -1,493 +0,0 @@ -/* - SortTable - version 2 - 7th April 2007 - Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ - - Instructions: - Download this file - Add <script src="sorttable.js"></script> to your HTML - Add class="sortable" to any table you'd like to make sortable - Click on the headers to sort - - Thanks to many, many people for contributions and suggestions. - Licenced as X11: http://www.kryogenix.org/code/browser/licence.html - This basically means: do what you want with it. -*/ - - -var stIsIE = /*@cc_on!@*/false; - -sorttable = { - init: function() { - // quit if this function has already been called - if (arguments.callee.done) return; - // flag this function so we don't do the same thing twice - arguments.callee.done = true; - // kill the timer - if (_timer) clearInterval(_timer); - - if (!document.createElement || !document.getElementsByTagName) return; - - sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; - - forEach(document.getElementsByTagName('table'), function(table) { - if (table.className.search(/\bsortable\b/) != -1) { - sorttable.makeSortable(table); - } - }); - - }, - - makeSortable: function(table) { - if (table.getElementsByTagName('thead').length == 0) { - // table doesn't have a tHead. Since it should have, create one and - // put the first table row in it. - the = document.createElement('thead'); - the.appendChild(table.rows[0]); - table.insertBefore(the,table.firstChild); - } - // Safari doesn't support table.tHead, sigh - if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; - - if (table.tHead.rows.length != 1) return; // can't cope with two header rows - - // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as - // "total" rows, for example). This is B&R, since what you're supposed - // to do is put them in a tfoot. So, if there are sortbottom rows, - // for backwards compatibility, move them to tfoot (creating it if needed). - sortbottomrows = []; - for (var i=0; i<table.rows.length; i++) { - if (table.rows[i].className.search(/\bsortbottom\b/) != -1) { - sortbottomrows[sortbottomrows.length] = table.rows[i]; - } - } - if (sortbottomrows) { - if (table.tFoot == null) { - // table doesn't have a tfoot. Create one. - tfo = document.createElement('tfoot'); - table.appendChild(tfo); - } - for (var i=0; i<sortbottomrows.length; i++) { - tfo.appendChild(sortbottomrows[i]); - } - delete sortbottomrows; - } - - // work through each column and calculate its type - headrow = table.tHead.rows[0].cells; - for (var i=0; i<headrow.length; i++) { - // manually override the type with a sorttable_type attribute - if (!headrow[i].className.match(/\bsorttable_nosort\b/)) { // skip this col - mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/); - if (mtch) { override = mtch[1]; } - if (mtch && typeof sorttable["sort_"+override] == 'function') { - headrow[i].sorttable_sortfunction = sorttable["sort_"+override]; - } else { - headrow[i].sorttable_sortfunction = sorttable.guessType(table,i); - } - // make it clickable to sort - headrow[i].sorttable_columnindex = i; - headrow[i].sorttable_tbody = table.tBodies[0]; - dean_addEvent(headrow[i],"click", function(e) { - - if (this.className.search(/\bsorttable_sorted\b/) != -1) { - // if we're already sorted by this column, just - // reverse the table, which is quicker - sorttable.reverse(this.sorttable_tbody); - this.className = this.className.replace('sorttable_sorted', - 'sorttable_sorted_reverse'); - this.removeChild(document.getElementById('sorttable_sortfwdind')); - sortrevind = document.createElement('span'); - sortrevind.id = "sorttable_sortrevind"; - sortrevind.innerHTML = stIsIE ? ' <font face="webdings">5</font>' : ' ▴'; - this.appendChild(sortrevind); - return; - } - if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { - // if we're already sorted by this column in reverse, just - // re-reverse the table, which is quicker - sorttable.reverse(this.sorttable_tbody); - this.className = this.className.replace('sorttable_sorted_reverse', - 'sorttable_sorted'); - this.removeChild(document.getElementById('sorttable_sortrevind')); - sortfwdind = document.createElement('span'); - sortfwdind.id = "sorttable_sortfwdind"; - sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾'; - this.appendChild(sortfwdind); - return; - } - - // remove sorttable_sorted classes - theadrow = this.parentNode; - forEach(theadrow.childNodes, function(cell) { - if (cell.nodeType == 1) { // an element - cell.className = cell.className.replace('sorttable_sorted_reverse',''); - cell.className = cell.className.replace('sorttable_sorted',''); - } - }); - sortfwdind = document.getElementById('sorttable_sortfwdind'); - if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } - sortrevind = document.getElementById('sorttable_sortrevind'); - if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } - - this.className += ' sorttable_sorted'; - sortfwdind = document.createElement('span'); - sortfwdind.id = "sorttable_sortfwdind"; - sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾'; - this.appendChild(sortfwdind); - - // build an array to sort. This is a Schwartzian transform thing, - // i.e., we "decorate" each row with the actual sort key, - // sort based on the sort keys, and then put the rows back in order - // which is a lot faster because you only do getInnerText once per row - row_array = []; - col = this.sorttable_columnindex; - rows = this.sorttable_tbody.rows; - for (var j=0; j<rows.length; j++) { - row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]]; - } - /* If you want a stable sort, uncomment the following line */ - sorttable.shaker_sort(row_array, this.sorttable_sortfunction); - /* and comment out this one */ - //row_array.sort(this.sorttable_sortfunction); - - tb = this.sorttable_tbody; - for (var j=0; j<row_array.length; j++) { - tb.appendChild(row_array[j][1]); - } - - delete row_array; - }); - } - } - }, - - guessType: function(table, column) { - // guess the type of a column based on its first non-blank row - sortfn = sorttable.sort_alpha; - for (var i=0; i<table.tBodies[0].rows.length; i++) { - text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]); - if (text != '') { - if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) { - return sorttable.sort_numeric; - } - // check for a date: dd/mm/yyyy or dd/mm/yy - // can have / or . or - as separator - // can be mm/dd as well - possdate = text.match(sorttable.DATE_RE) - if (possdate) { - // looks like a date - first = parseInt(possdate[1]); - second = parseInt(possdate[2]); - if (first > 12) { - // definitely dd/mm - return sorttable.sort_ddmm; - } else if (second > 12) { - return sorttable.sort_mmdd; - } else { - // looks like a date, but we can't tell which, so assume - // that it's dd/mm (English imperialism!) and keep looking - sortfn = sorttable.sort_ddmm; - } - } - } - } - return sortfn; - }, - - getInnerText: function(node) { - // gets the text we want to use for sorting for a cell. - // strips leading and trailing whitespace. - // this is *not* a generic getInnerText function; it's special to sorttable. - // for example, you can override the cell text with a customkey attribute. - // it also gets .value for <input> fields. - - hasInputs = (typeof node.getElementsByTagName == 'function') && - node.getElementsByTagName('input').length; - - if (node.getAttribute("sorttable_customkey") != null) { - return node.getAttribute("sorttable_customkey"); - } - else if (typeof node.textContent != 'undefined' && !hasInputs) { - return node.textContent.replace(/^\s+|\s+$/g, ''); - } - else if (typeof node.innerText != 'undefined' && !hasInputs) { - return node.innerText.replace(/^\s+|\s+$/g, ''); - } - else if (typeof node.text != 'undefined' && !hasInputs) { - return node.text.replace(/^\s+|\s+$/g, ''); - } - else { - switch (node.nodeType) { - case 3: - if (node.nodeName.toLowerCase() == 'input') { - return node.value.replace(/^\s+|\s+$/g, ''); - } - case 4: - return node.nodeValue.replace(/^\s+|\s+$/g, ''); - break; - case 1: - case 11: - var innerText = ''; - for (var i = 0; i < node.childNodes.length; i++) { - innerText += sorttable.getInnerText(node.childNodes[i]); - } - return innerText.replace(/^\s+|\s+$/g, ''); - break; - default: - return ''; - } - } - }, - - reverse: function(tbody) { - // reverse the rows in a tbody - newrows = []; - for (var i=0; i<tbody.rows.length; i++) { - newrows[newrows.length] = tbody.rows[i]; - } - for (var i=newrows.length-1; i>=0; i--) { - tbody.appendChild(newrows[i]); - } - delete newrows; - }, - - /* sort functions - each sort function takes two parameters, a and b - you are comparing a[0] and b[0] */ - sort_numeric: function(a,b) { - aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); - if (isNaN(aa)) aa = 0; - bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); - if (isNaN(bb)) bb = 0; - return aa-bb; - }, - sort_alpha: function(a,b) { - if (a[0]==b[0]) return 0; - if (a[0]<b[0]) return -1; - return 1; - }, - sort_ddmm: function(a,b) { - mtch = a[0].match(sorttable.DATE_RE); - y = mtch[3]; m = mtch[2]; d = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt1 = y+m+d; - mtch = b[0].match(sorttable.DATE_RE); - y = mtch[3]; m = mtch[2]; d = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt2 = y+m+d; - if (dt1==dt2) return 0; - if (dt1<dt2) return -1; - return 1; - }, - sort_mmdd: function(a,b) { - mtch = a[0].match(sorttable.DATE_RE); - y = mtch[3]; d = mtch[2]; m = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt1 = y+m+d; - mtch = b[0].match(sorttable.DATE_RE); - y = mtch[3]; d = mtch[2]; m = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt2 = y+m+d; - if (dt1==dt2) return 0; - if (dt1<dt2) return -1; - return 1; - }, - - shaker_sort: function(list, comp_func) { - // A stable sort function to allow multi-level sorting of data - // see: http://en.wikipedia.org/wiki/Cocktail_sort - // thanks to Joseph Nahmias - var b = 0; - var t = list.length - 1; - var swap = true; - - while(swap) { - swap = false; - for(var i = b; i < t; ++i) { - if ( comp_func(list[i], list[i+1]) > 0 ) { - var q = list[i]; list[i] = list[i+1]; list[i+1] = q; - swap = true; - } - } // for - t--; - - if (!swap) break; - - for(var i = t; i > b; --i) { - if ( comp_func(list[i], list[i-1]) < 0 ) { - var q = list[i]; list[i] = list[i-1]; list[i-1] = q; - swap = true; - } - } // for - b++; - - } // while(swap) - } -} - -/* ****************************************************************** - Supporting functions: bundled here to avoid depending on a library - ****************************************************************** */ - -// Dean Edwards/Matthias Miller/John Resig - -/* for Mozilla/Opera9 */ -if (document.addEventListener) { - document.addEventListener("DOMContentLoaded", sorttable.init, false); -} - -/* for Internet Explorer */ -/*@cc_on @*/ -/*@if (@_win32) - document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>"); - var script = document.getElementById("__ie_onload"); - script.onreadystatechange = function() { - if (this.readyState == "complete") { - sorttable.init(); // call the onload handler - } - }; -/*@end @*/ - -/* for Safari */ -if (/WebKit/i.test(navigator.userAgent)) { // sniff - var _timer = setInterval(function() { - if (/loaded|complete/.test(document.readyState)) { - sorttable.init(); // call the onload handler - } - }, 10); -} - -/* for other browsers */ -window.onload = sorttable.init; - -// written by Dean Edwards, 2005 -// with input from Tino Zijdel, Matthias Miller, Diego Perini - -// http://dean.edwards.name/weblog/2005/10/add-event/ - -function dean_addEvent(element, type, handler) { - if (element.addEventListener) { - element.addEventListener(type, handler, false); - } else { - // assign each event handler a unique ID - if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++; - // create a hash table of event types for the element - if (!element.events) element.events = {}; - // create a hash table of event handlers for each element/event pair - var handlers = element.events[type]; - if (!handlers) { - handlers = element.events[type] = {}; - // store the existing event handler (if there is one) - if (element["on" + type]) { - handlers[0] = element["on" + type]; - } - } - // store the event handler in the hash table - handlers[handler.$$guid] = handler; - // assign a global event handler to do all the work - element["on" + type] = handleEvent; - } -}; -// a counter used to create unique IDs -dean_addEvent.guid = 1; - -function removeEvent(element, type, handler) { - if (element.removeEventListener) { - element.removeEventListener(type, handler, false); - } else { - // delete the event handler from the hash table - if (element.events && element.events[type]) { - delete element.events[type][handler.$$guid]; - } - } -}; - -function handleEvent(event) { - var returnValue = true; - // grab the event object (IE uses a global event object) - event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); - // get a reference to the hash table of event handlers - var handlers = this.events[event.type]; - // execute each event handler - for (var i in handlers) { - this.$$handleEvent = handlers[i]; - if (this.$$handleEvent(event) === false) { - returnValue = false; - } - } - return returnValue; -}; - -function fixEvent(event) { - // add W3C standard event methods - event.preventDefault = fixEvent.preventDefault; - event.stopPropagation = fixEvent.stopPropagation; - return event; -}; -fixEvent.preventDefault = function() { - this.returnValue = false; -}; -fixEvent.stopPropagation = function() { - this.cancelBubble = true; -} - -// Dean's forEach: http://dean.edwards.name/base/forEach.js -/* - forEach, version 1.0 - Copyright 2006, Dean Edwards - License: http://www.opensource.org/licenses/mit-license.php -*/ - -// array-like enumeration -if (!Array.forEach) { // mozilla already supports this - Array.forEach = function(array, block, context) { - for (var i = 0; i < array.length; i++) { - block.call(context, array[i], i, array); - } - }; -} - -// generic enumeration -Function.prototype.forEach = function(object, block, context) { - for (var key in object) { - if (typeof this.prototype[key] == "undefined") { - block.call(context, object[key], key, object); - } - } -}; - -// character enumeration -String.forEach = function(string, block, context) { - Array.forEach(string.split(""), function(chr, index) { - block.call(context, chr, index, string); - }); -}; - -// globally resolve forEach enumeration -var forEach = function(object, block, context) { - if (object) { - var resolve = Object; // default - if (object instanceof Function) { - // functions have a "length" property - resolve = Function; - } else if (object.forEach instanceof Function) { - // the object implements a custom forEach method so use that - object.forEach(block, context); - return; - } else if (typeof object == "string") { - // the object is a string - resolve = String; - } else if (typeof object.length == "number") { - // the object is array-like - resolve = Array; - } - resolve.forEach(object, block, context); - } -}; - |