summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/C++Tests/Clang-Code-Compile/lit.local.cfg2
-rw-r--r--utils/C++Tests/Clang-Syntax/lit.local.cfg1
-rw-r--r--utils/C++Tests/LLVM-Code-Compile/lit.local.cfg24
-rw-r--r--utils/C++Tests/LLVM-Code-Syntax/lit.local.cfg23
-rw-r--r--utils/C++Tests/LLVM-Syntax/lit.local.cfg3
-rw-r--r--utils/C++Tests/lit.cfg12
-rwxr-xr-xutils/analyzer/ubiviz (renamed from utils/ubiviz)0
-rwxr-xr-xutils/ccc-analyzer632
-rwxr-xr-xutils/scan-build1297
-rw-r--r--utils/scanview.css62
-rw-r--r--utils/sorttable.js493
11 files changed, 55 insertions, 2494 deletions
diff --git a/utils/C++Tests/Clang-Code-Compile/lit.local.cfg b/utils/C++Tests/Clang-Code-Compile/lit.local.cfg
index d9e39e5..59d3466 100644
--- a/utils/C++Tests/Clang-Code-Compile/lit.local.cfg
+++ b/utils/C++Tests/Clang-Code-Compile/lit.local.cfg
@@ -18,7 +18,7 @@ cxxflags = ['-D__STDC_LIMIT_MACROS',
'-I%s/tools/clang/include' % root.llvm_src_root,
'-I%s/tools/clang/include' % root.llvm_obj_root]
config.test_format = \
- lit.formats.OneCommandPerFileTest(command=[root.clang, '-c',
+ lit.formats.OneCommandPerFileTest(command=[root.clang, '-emit-llvm', '-c',
'-o', '/dev/null'] + cxxflags,
dir='%s/tools/clang/lib' % root.llvm_src_root,
recursive=True,
diff --git a/utils/C++Tests/Clang-Syntax/lit.local.cfg b/utils/C++Tests/Clang-Syntax/lit.local.cfg
index 280d1c1..89fdd8e 100644
--- a/utils/C++Tests/Clang-Syntax/lit.local.cfg
+++ b/utils/C++Tests/Clang-Syntax/lit.local.cfg
@@ -17,6 +17,7 @@ config.test_format = lit.formats.SyntaxCheckTest(compiler=root.clang,
extra_cxx_args=['-D__STDC_LIMIT_MACROS',
'-D__STDC_CONSTANT_MACROS',
'-Wno-sign-compare',
+ '-Werror',
'-I%s/include' % root.llvm_src_root,
'-I%s/include' % root.llvm_obj_root,
'-I%s/tools/clang/include' % root.llvm_src_root,
diff --git a/utils/C++Tests/LLVM-Code-Compile/lit.local.cfg b/utils/C++Tests/LLVM-Code-Compile/lit.local.cfg
new file mode 100644
index 0000000..fc493e4
--- /dev/null
+++ b/utils/C++Tests/LLVM-Code-Compile/lit.local.cfg
@@ -0,0 +1,24 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+# testFormat: The test format to use to interpret tests.
+cxxflags = ['-D__STDC_LIMIT_MACROS',
+ '-D__STDC_CONSTANT_MACROS',
+ '-Wno-sign-compare',
+ '-I%s/include' % root.llvm_src_root,
+ '-I%s/include' % root.llvm_obj_root]
+config.test_format = \
+ lit.formats.OneCommandPerFileTest(command=[root.clang, '-emit-llvm', '-c',
+ '-o', '/dev/null'] + cxxflags,
+ dir='%s/lib' % root.llvm_src_root,
+ recursive=True,
+ pattern='^(.*\\.cpp)$')
+
diff --git a/utils/C++Tests/LLVM-Code-Syntax/lit.local.cfg b/utils/C++Tests/LLVM-Code-Syntax/lit.local.cfg
new file mode 100644
index 0000000..67bc5aed
--- /dev/null
+++ b/utils/C++Tests/LLVM-Code-Syntax/lit.local.cfg
@@ -0,0 +1,23 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+# testFormat: The test format to use to interpret tests.
+cxxflags = ['-D__STDC_LIMIT_MACROS',
+ '-D__STDC_CONSTANT_MACROS',
+ '-Wno-sign-compare',
+ '-I%s/include' % root.llvm_src_root,
+ '-I%s/include' % root.llvm_obj_root]
+config.test_format = \
+ lit.formats.OneCommandPerFileTest(command=[root.clang,
+ '-fsyntax-only'] + cxxflags,
+ dir='%s/lib' % root.llvm_src_root,
+ recursive=True,
+ pattern='^(.*\\.cpp)$')
diff --git a/utils/C++Tests/LLVM-Syntax/lit.local.cfg b/utils/C++Tests/LLVM-Syntax/lit.local.cfg
index 25728bc..b67bb90 100644
--- a/utils/C++Tests/LLVM-Syntax/lit.local.cfg
+++ b/utils/C++Tests/LLVM-Syntax/lit.local.cfg
@@ -17,8 +17,9 @@ config.test_format = lit.formats.SyntaxCheckTest(compiler=root.clang,
extra_cxx_args=['-D__STDC_LIMIT_MACROS',
'-D__STDC_CONSTANT_MACROS',
'-Wno-sign-compare',
+ '-Werror',
'-I%s/include' % root.llvm_src_root,
'-I%s/include' % root.llvm_obj_root])
config.excludes = ['AbstractTypeUser.h', 'DAGISelHeader.h',
- 'AIXDataTypesFix.h', 'Solaris.h']
+ 'AIXDataTypesFix.h', 'LinkAllPasses.h', 'Solaris.h']
diff --git a/utils/C++Tests/lit.cfg b/utils/C++Tests/lit.cfg
index aa3b09d..e61502b 100644
--- a/utils/C++Tests/lit.cfg
+++ b/utils/C++Tests/lit.cfg
@@ -17,14 +17,10 @@ config.suffixes = []
# Reset these from the Clang config.
config.test_source_root = config.test_exec_root = None
-# Don't run Clang checks by default.
+# Don't run Clang and LLVM code checks by default.
config.excludes = []
-if (not lit.params.get('run_clang_syntax') and
- not lit.params.get('run_clang_all')):
- config.excludes.append('Clang-Syntax')
-if (not lit.params.get('run_clang_code_syntax') and
- not lit.params.get('run_clang_all')):
+if not lit.params.get('run_clang_all'):
config.excludes.append('Clang-Code-Syntax')
-if (not lit.params.get('run_clang_compile') and
- not lit.params.get('run_clang_all')):
config.excludes.append('Clang-Code-Compile')
+ config.excludes.append('LLVM-Code-Syntax')
+ config.excludes.append('LLVM-Code-Compile')
diff --git a/utils/ubiviz b/utils/analyzer/ubiviz
index 1582797..1582797 100755
--- a/utils/ubiviz
+++ b/utils/analyzer/ubiviz
diff --git a/utils/ccc-analyzer b/utils/ccc-analyzer
deleted file mode 100755
index 25b9800..0000000
--- a/utils/ccc-analyzer
+++ /dev/null
@@ -1,632 +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 Cwd qw/ getcwd abs_path /;
-use File::Temp qw/ tempfile /;
-use File::Path qw / mkpath /;
-use File::Basename;
-use Text::ParseWords;
-
-my $CC = $ENV{'CCC_CC'};
-if (!defined $CC) { $CC = "gcc"; }
-
-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 ".mi"; }
- 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 ($ClangCC, $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 $ClangCC, @$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`;
- `$CC -v >> $PPFile.info.txt 2>&1`;
- system 'mv',$ofile,"$PPFile.stderr.txt";
- return (basename $PPFile);
-}
-
-##----------------------------------------------------------------------------##
-# Running the analyzer.
-##----------------------------------------------------------------------------##
-
-# Determine what clang executable to use.
-my $Clang = $ENV{'CLANG'};
-if (!defined $Clang) { $Clang = 'clang'; }
-
-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 (!/clang-cc/);
- $line = $_;
- }
-
- waitpid($pid,0);
- close(FROM_CHILD);
-
- die "could not find clang-cc line\n" if (!defined $line);
- # Strip the newline and initial whitspace
- chomp $line;
- $line =~ s/^\s+//;
-
- my @items = quotewords('\s+', 1, $line);
- for (my $i = 0 ; $ i < scalar(@items); ++$i) {
- $items[$i] =~ s/^\"//;
- $items[$i] =~ s/\"$//;
- }
- my $cmd = shift @items;
- die "cannot find 'clang-cc' in 'clang' command\n" if (!($cmd =~ /clang-cc/));
- return \@items;
-}
-
-sub Analyze {
- my ($ClangCC, $Args, $AnalyzeArgs, $Lang, $Output, $Verbose, $HtmlDir,
- $file, $Analyses) = @_;
-
- $Args = GetCCArgs($Args);
-
- # Skip anything related to C++.
- return if ($Lang =~ /c[+][+]/);
-
- 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 = $ClangCC;
- 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,(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 $ClangCC and defined $HtmlDir) {
- ProcessClangFailure($ClangCC, $Lang, $file, \@CmdArgsSansAnalyses,
- $HtmlDir, "Crash", $ofile);
- }
- elsif ($Result) {
- if ($IncludeParserRejects && !($file =~/conftest/)) {
- ProcessClangFailure($ClangCC, $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($ClangCC, $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,
- '-fobjc-gc-only' => 0,
- '-fobjc-gc' => 0,
- '-ffreestanding' => 0,
- '-include' => 1,
- '-idirafter' => 1,
- '-iprefix' => 1,
- '-iquote' => 1,
- '-isystem' => 1,
- '-iwithprefix' => 1,
- '-iwithprefixbefore' => 1
-);
-
-my %LinkerOptionMap = (
- '-framework' => 1
-);
-
-my %CompilerLinkerOptionMap = (
- '-isysroot' => 1,
- '-arch' => 1,
- '-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',
- 'cpp' => 'c++',
- 'cc' => 'c++',
- 'i' => 'c-cpp-output',
- 'm' => 'objective-c',
- 'mi' => 'objective-c-cpp-output'
-);
-
-my %UniqueOptions = (
- '-isysroot' => 0
-);
-
-my %LangsAccepted = (
- "objective-c" => 1,
- "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($CC,@ARGV);
-if ($Status) { exit($Status >> 8); }
-
-# Get the analysis options.
-my $Analyses = $ENV{'CCC_ANALYZER_ANALYSIS'};
-if (!defined($Analyses)) { $Analyses = '-checker-cfref'; }
-
-# 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; }
-
-# Determine what clang-cc executable to use.
-my $ClangCC = $ENV{'CLANG_CC'};
-if (!defined $ClangCC) { $ClangCC = 'clang-cc'; }
-
-# 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};
- }
- }
-
- next if (!defined $FileLang);
- 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($ClangCC, \@NewArgs, \@AnalyzeArgs, $FileLang, $Output,
- $Verbose, $HtmlDir, $file, $Analyses);
- }
- }
- else {
- Analyze($ClangCC, \@CmdArgs, \@AnalyzeArgs, $FileLang, $Output,
- $Verbose, $HtmlDir, $file, $Analyses);
- }
- }
-}
-
-exit($Status >> 8);
-
diff --git a/utils/scan-build b/utils/scan-build
deleted file mode 100755
index ca95676..0000000
--- a/utils/scan-build
+++ /dev/null
@@ -1,1297 +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 $CXX; # Leave undefined initially.
-
-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.
-##----------------------------------------------------------------------------##
-
-# First, look for 'clang-cc' in libexec.
-my $ClangCCSB = Cwd::realpath("$RealBin/libexec/clang-cc");
-# Second, look for 'clang-cc' in the same directory as scan-build.
-if (!defined $ClangCCSB || ! -x $ClangCCSB) {
- $ClangCCSB = Cwd::realpath("$RealBin/clang-cc");
-}
-# Third, look for 'clang-cc' in ../libexec
-if (!defined $ClangCCSB || ! -x $ClangCCSB) {
- $ClangCCSB = Cwd::realpath("$RealBin/../libexec/clang-cc");
-}
-# Finally, default to looking for 'clang-cc' in the path.
-if (!defined $ClangCCSB || ! -x $ClangCCSB) {
- $ClangCCSB = "clang-cc";
-}
-my $ClangCC = $ClangCCSB;
-
-# Now find 'clang'
-my $ClangSB = Cwd::realpath("$RealBin/bin/clang");
-if (!defined $ClangSB || ! -x $ClangSB) {
- $ClangSB = Cwd::realpath("$RealBin/clang");
-}
-# Third, look for 'clang' in ../bin
-if (!defined $ClangSB || ! -x $ClangSB) {
- $ClangSB = Cwd::realpath("$RealBin/../bin/clang");
-}
-# Finally, default to looking for 'clang-cc' in the path.
-if (!defined $ClangSB || ! -x $ClangSB) {
- $ClangSB = "clang";
-}
-my $Clang = $ClangSB;
-
-
-my %AvailableAnalyses;
-
-# Query clang for analysis options.
-open(PIPE, "-|", $ClangCC, "--help") or
- DieDiag("Cannot execute '$ClangCC'\n");
-
-my $FoundAnalysis = 0;
-
-while(<PIPE>) {
- if ($FoundAnalysis == 0) {
- if (/Checks and Analyses/) {
- $FoundAnalysis = 1;
- }
- next;
- }
-
- if (/^\s\s\s\s([^\s]+)\s(.+)$/) {
- next if ($1 =~ /-dump/ or $1 =~ /-view/
- or $1 =~ /-checker-simple/ or $1 =~ /-warn-uninit/);
-
- $AvailableAnalyses{$1} = $2;
- next;
- }
- last;
-}
-
-close (PIPE);
-
-my %AnalysesDefaultEnabled = (
- '-warn-dead-stores' => 1,
- '-checker-cfref' => 1,
- '-warn-objc-methodsigs' => 1,
- # Do not enable the missing -dealloc check by default.
- # '-warn-objc-missing-dealloc' => 1,
- '-warn-objc-unused-ivars' => 1,
- '-warn-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">&nbsp;&#x25BE;</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;
-
- # 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 ($IgnoreErrors) {
- if ($Cmd eq "make" or $Cmd eq "gmake") {
- 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";
- }
- }
- }
- }
-
- # 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++'
- # when linking such files.
- die if (!defined $CXX);
- my $LDPLUSPLUS = `which $CXX`;
- $LDPLUSPLUS =~ s/\015?\012//; # strip newlines
- $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS;
- }
-
- 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 $AvailableAnalyses{$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/&/&amp;/g;
- $tmp =~ s/</&lt;/g;
- $tmp =~ s/>/&gt;/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;
-
- if (!defined $2 || $2 eq "") {
- if (!@ARGV) {
- DieDiag("'--use-c++' option requires a compiler executable name.\n");
- }
- $CXX = shift @ARGV;
- }
- else {
- $CXX = $2;
- }
- 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 $Cmd = Cwd::realpath("$RealBin/libexec/ccc-analyzer");
-if (!defined $Cmd || ! -x $Cmd) {
- $Cmd = Cwd::realpath("$RealBin/ccc-analyzer");
- DieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n") if(! -x $Cmd);
-}
-
-if (!defined $ClangCCSB || ! -x $ClangCCSB) {
- Diag("'clang-cc' executable not found in '$RealBin/libexec'.\n");
- Diag("Using 'clang-cc' from path.\n");
-}
-if (!defined $ClangSB || ! -x $ClangSB) {
- Diag("'clang' executable not found in '$RealBin/bin'.\n");
- Diag("Using 'clang' from path.\n");
-}
-
-if (defined $CXX) {
- $ENV{'CXX'} = $CXX;
-}
-else {
- $CXX = 'g++'; # This variable is used by other parts of scan-build
- # that need to know a default C++ compiler to fall back to.
-}
-
-$ENV{'CC'} = $Cmd;
-$ENV{'CLANG_CC'} = $ClangCC;
-$ENV{'CLANG'} = $Clang;
-
-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);
-
-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/utils/scanview.css b/utils/scanview.css
deleted file mode 100644
index a0406f3..0000000
--- a/utils/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/utils/sorttable.js b/utils/sorttable.js
deleted file mode 100644
index 4352d3b..0000000
--- a/utils/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 ? '&nbsp<font face="webdings">5</font>' : '&nbsp;&#x25B4;';
- 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 ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
- 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 ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
- 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);
- }
-};
-
OpenPOWER on IntegriCloud