diff options
Diffstat (limited to 'trunk/ACE/bin/fuzz.pl')
-rwxr-xr-x | trunk/ACE/bin/fuzz.pl | 1479 |
1 files changed, 1479 insertions, 0 deletions
diff --git a/trunk/ACE/bin/fuzz.pl b/trunk/ACE/bin/fuzz.pl new file mode 100755 index 00000000000..a0e49ede380 --- /dev/null +++ b/trunk/ACE/bin/fuzz.pl @@ -0,0 +1,1479 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# $Id$ +# Fuzz is a script whose purpose is to check through ACE/TAO files for +# easy to spot (by a perl script, at least) problems. + +use File::Find; +use File::Basename; +use Getopt::Std; + +###### TODO +# +# Add tests for these: +# +# - no relative path to tao_idl in the .dsp files +# - Linking to wrong type of library in dsp's +# - not setting up the release configs correctly in dsp files +# - Guards in .h files +# - no global functions +# - other commit_check checks, tabs, trailing spaces. +# - _narrow() should always have ACE_ENV_ARG_PARAMETER +# - Using ACE_TRY_NEW_ENV (Nanbor suggests using ACE_DECLARE_NEW_CORBA_ENV) +# +# And others in ACE_Guidelines and Design Rules +# +# Also add a -g flag to ignore tao_idl generated files +# +###### END TODO + +# Lists of all the files +@files_cpp = (); +@files_inl = (); +@files_h = (); +@files_html = (); +@files_dsp = (); +@files_dsw = (); +@files_gnu = (); +@files_idl = (); +@files_pl = (); +@files_changelog = (); +@files_makefile = (); +@files_mpc = (); +@files_bor = (); +@files_noncvs = (); + +# To keep track of errors and warnings +$errors = 0; +$warnings = 0; + +############################################################################## + +# Find_Modified_Files will use 'cvs -nq' to get a list of locally modified +# files to look through +sub find_mod_files () +{ + unless (open (CVS, "cvs -nq up |")) { + print STDERR "Error: Could not run cvs\n"; + exit (1); + } + + while (<CVS>) { + if (/^[M|A] (.*)/) { + store_file ($1); + } + } + close (CVS); +} + + + +# Find_Files will search for files with certain extensions in the +# directory tree +sub find_files () +{ + # wanted is only used for the File::Find + sub wanted + { + store_file ($File::Find::name); + } + + find (\&wanted, '.'); +} + +# +sub store_file ($) +{ + my $name = shift; + if ($name =~ /\.(c|cc|cpp|cxx)$/i) { + push @files_cpp, ($name); + } + elsif ($name =~ /\.(inl|i)$/i) { + push @files_inl, ($name); + } + elsif ($name =~ /\.(h|hh|hpp|hxx)$/i) { + push @files_h, ($name); + } + elsif ($name =~ /\.(htm|html)$/i) { + push @files_html, ($name); + } + elsif ($name =~ /\.(bor)$/i) { + push @files_bor, ($name); + } + elsif ($name =~ /\.(GNU)$/i) { + push @files_gnu, ($name); + } + elsif ($name =~ /\.(dsp|vcp)$/i) { + push @files_dsp, ($name); + } + elsif ($name =~ /\.(dsw|vcp)$/i) { + push @files_dsw, ($name); + } + elsif ($name =~ /\.(pidl|idl)$/i) { + push @files_idl, ($name); + } + elsif ($name =~ /\.pl$/i) { + push @files_pl, ($name); + } + elsif ($name =~ /ChangeLog/i && -f $name) { + push @files_changelog, ($name); + } + elsif ($name =~ /\/GNUmakefile.*.[^~]$/) { + push @files_makefile, ($name); + } + elsif ($name =~ /\.(mpc|mwc|mpb|mpt)$/i) { + push @files_mpc, ($name); + } + elsif ($name =~ /\.(icc|ncb|opt|zip)$/i) { + push @files_noncvs, ($name); + } +} + +############################################################################## +## Just messages + +sub print_error ($) +{ + my $msg = shift; + print "Error: $msg\n"; + ++$errors; +} + + +sub print_warning ($) +{ + my $msg = shift; + print "Warning: $msg\n"; + ++$warnings; +} + + +############################################################################## +## Tests + +# The point of this test is to check for the existence of ACE_INLINE +# or ASYS_INLINE in a .cpp file. This is most commonly caused by +# copy/pasted code from a .inl/.i file +sub check_for_inline_in_cpp () +{ + print "Running ACE_INLINE/ASYS_INLINE check\n"; + foreach $file (@files_cpp) { + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/^ACE_INLINE/) { + print_error ("$file:$.: ACE_INLINE found"); + } + if (/^ASYS_INLINE/) { + print_error ("$file:$.: ASYS_INLINE found"); + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test checks to make sure files have the $Id string in them. +# Commit_check should find these when checking in files, but this can +# be used locally or to check for files +sub check_for_id_string () +{ + print "Running \$Id\$ string check\n"; + foreach $file (@files_cpp, @files_inl, @files_h, @files_mpc, @files_bor, @files_gnu, + @files_html, @files_idl, @files_pl, @makefile_files) { + my $found = 0; + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/\$Id\:/ or /\$Id\$/) { + $found = 1; + } + if (/\$id\$/) { + print_error ("$file:$.: Incorrect \$id\$ found (correct casing)"); + } + } + close (FILE); + if ($found == 0) { + print_error ("$file:1: No \$Id\$ string found."); + } + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# check for _MSC_VER +sub check_for_msc_ver_string () +{ + print "Running _MSC_VER check\n"; + foreach $file (@files_cpp, @files_inl, @files_h) { + my $found = 0; + if (open (FILE, $file)) { + my $disable = 0; + my $mscline = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_msc_ver/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_msc_ver/) { + $disable = 0; + } + if ($disable == 0 and /\_MSC_VER \<= 1200/) { + $found = 1; + $mscline = $.; + } + if ($disable == 0 and /\_MSC_VER \>= 1200/) { + $found = 1; + $mscline = $.; + } + if ($disable == 0 and /\_MSC_VER \< 1300/) { + $found = 1; + $mscline = $.; + } + if ($disable == 0 and /\_MSC_VER \<= 1300/) { + $found = 1; + $mscline = $.; + } + } + close (FILE); + if ($found == 1) { + print_error ("$file:$mscline: Incorrect _MSC_VER check found"); + } + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test checks for the newline at the end of a file +sub check_for_newline () +{ + print "Running newline check\n"; + foreach $file (@files_cpp, @files_inl, @files_h, + @files_html, @files_idl, @files_pl) { + if (open (FILE, $file)) { + my $line; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + $line = $_ + } + close (FILE); + if ($line !~ /\n$/) { + print_error ("$file:$.: No ending newline found in $file"); + } + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + + +# This test checks for files that are not allowed to be in svn +sub check_for_noncvs_files () +{ + print "Running non svn files check\n"; + foreach $file (@files_noncvs, @files_dsp, @files_dsw, @files_makefile) { + print_error ("File $file should not be in svn!"); + } +} + + +# This test checks for the use of "inline" instead of ACE_INLINE +sub check_for_inline () +{ + print "Running inline check\n"; + foreach $file (@files_inl) { + if (open (FILE, $file)) { + my $disable = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + ++$line; + if (/FUZZ\: disable check_for_inline/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_inline/) { + $disable = 0; + } + if ($disable == 0 and m/^\s*inline/) { + print_error ("$file:$.: 'inline' keyword found"); + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + + +# This test checks for the inclusion of math.h. math.h should be avoided +# since on some platforms, "exceptions" is defined as a struct, which will +# cause problems with exception handling +sub check_for_math_include () +{ + print "Running math.h test\n"; + foreach $file (@files_h, @files_cpp, @files_inl) { + if (open (FILE, $file)) { + my $disable = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_math_include/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_math_include/) { + $disable = 0; + } + if ($disable == 0 + and /^\s*#\s*include\s*(\/\*\*\/){0,1}\s*\<math\.h\>/) { + print_error ("$file:$.: <math.h> included"); + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test checks for the inclusion of streams.h. +# // FUZZ: disable check_for_streams_include +sub check_for_streams_include () +{ + print "Running ace/streams.h test\n"; + foreach $file (@files_h, @files_cpp, @files_inl) { + if (open (FILE, $file)) { + my $disable = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_streams_include/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_streams_include/) { + $disable = 0; + } + if ($disable == 0 + and /^\s*#\s*include\s*\"ace\/streams\.h\"/) { + print_error ("$file:$.: expensive ace/streams.h included; consider ace/iosfwd.h"); + print " ace/streams.h is very expensive in both "; + print "compile-time and footprint. \n"; + print " Please consider including ace/iosfwd.h instead.\n\n"; + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test checks for the inclusion of OS.h. +sub check_for_OS_h_include () +{ + print "Running ace/OS.h test\n"; + foreach $file (@files_h, @files_cpp, @files_inl) { + if (open (FILE, $file)) { + my $disable = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_OS_h_include/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_OS_h_include/) { + $disable = 0; + } + if ($disable == 0 + and /^\s*#\s*include\s*\"ace\/OS\.h\"/) { + print_error ("$file:$.: expensive ace/OS.h included; consider an OS_NS_*.h file"); + print " OS.h is very expensive in both "; + print "compile-time and footprint. \n"; + print " Please consider including one of the "; + print "OS_NS_*.h files instead.\n\n"; + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test checks for the inclusion of Synch*.h. +sub check_for_synch_include () +{ + print "Running ace/Synch*.h test\n"; + foreach $file (@files_h, @files_cpp, @files_inl) { + if (open (FILE, $file)) { + my $disable = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_synch_include/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_synch_include/) { + $disable = 0; + } + if ($disable == 0 + and (/^\s*#\s*include\s*\"(ace\/Synch\.h)\"/ + or /^\s*#\s*include\s*\"(ace\/Synch_T\.h)\"/)) { + my $synch = $1; + print_error ("$file:$.: expensive $synch included; consider individual synch file"); + print " $synch is very expensive in both "; + print "compile-time and footprint. \n"; + print " Please consider including one of the "; + print "individual synch files instead.\n\n"; + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# For general readability, lines should not contain more than 80 characters +sub check_for_line_length () +{ + print "Running line length test\n"; + foreach $file (@files_h, @files_cpp, @files_inl) { + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + + # Make sure to ignore ACE_RCSID lines, since they + # are difficult to get under 80 chars. + if (/.{80,}/ and !/^ACE_RCSID/) { + print_error ("$file:$.: line longer than 80 chars"); + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + + +# For preprocessor directives, only the old C style comments (/* */) +# should be used, not the newer // style. +sub check_for_preprocessor_comments () +{ + print "Running preprocessor comment test\n"; + foreach $file (@files_h, @files_cpp, @files_inl) { + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/^\#.*\/\//) { + print_error ("$file:$.: C++ comment in directive"); + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# We should not have empty files in the repo +sub check_for_empty_files () +{ + print "Running empty file test\n"; + foreach $file (@files_inl, @files_cpp) { + my $found_non_empty_line = 0; + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + next if /^[:blank:]*$/; # skip empty lines + next if /^[:blank:]*\/\//; # skip C++ comments + next if /^[:blank:]*\/\*/; # skip C++ comments + $found_non_empty_line = 1; + last; + } + close (FILE); + if ($found_non_empty_line == 0) { + print_error ("$file:1: empty file should not be in the repository"); + } + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + + +# This test checks for the use of the Win32 Unicode string defines +# or outdated ASYS_* macros +# We should only be using the ACE_TCHAR, ACE_TEXT macros instead. +sub check_for_tchar +{ + print "Running TCHAR test\n"; + foreach $file (@files_h, @files_cpp, @files_inl) { + if (open (FILE, $file)) { + my $disable = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_tchar/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_tchar/) { + $disable = 0; + } + if ($disable == 0) { + if (/LPTSTR/) { + print_error ("$file:$.: LPTSTR found"); + } + + if (/LPCTSTR/) { + print_error ("$file:$.: LPCTSTR found"); + } + + if (/ASYS_TCHAR/) { + print_error ("$file:$.: ASYS_TCHAR found"); + } + elsif (/TCHAR/ and !/ACE_TCHAR/) { + ### Do a double check, since some macros do have TCHAR + ### (like DEFAULTCHARS) + if (/^TCHAR[^\w_]/ or /[^\w_]TCHAR[^\w_]/) { + print_error ("$file:$.: TCHAR found"); + } + } + + if (/ASYS_TEXT/) { + print_error ("$file:$.: ASYS_TEXT found"); + } + elsif (/TEXT/ and !/ACE_TEXT/) { + ### Do a double check, since there are several macros + ### that end with TEXT + if (/^TEXT\s*\(/ or /[^\w_]TEXT\s*\(/) { + print_error ("$file:$.: TEXT found"); + } + } + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This checks to see if Makefiles define a DEPENDENCY_FILE, and if they do +# whether or not it's in the cvs repo. +sub check_for_dependency_file () +{ + print "Running DEPENDENCY_FILE test\n"; + foreach $file (@files_makefile) { + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/^DEPENDENCY_FILE\s* =\s*(.*)/) { + my $depend = $1; + my $path = $file; + $path =~ s/\/GNUmakefile.*/\//; + $depend = $path . $depend; + unless (open (DFILE, $depend)) { + print_error ("DEPENDENCY_FILE \"$depend\" not found"); + print " Either add \"$depend\" to svn "; + print "or remove DEPENDENCY_FILE variable\n"; + print " from $file\n\n"; + } + close (DFILE); + } + } + close (FILE); + } + else { + print_error ("cannot open $file"); + } + } +} + +# This checks to see if GNUmakefiles define a MAKEFILE, and if it matches the +# name of the GNUmakefile +sub check_for_makefile_variable () +{ + print "Running MAKEFILE variable test\n"; + foreach $file (@files_makefile) { + if (!(substr($file,-4) eq ".bor") + and !(substr($file,-3) eq ".am") + and !(substr($file,-4) eq ".vac") + and !(substr($file,-4) eq ".alt")) { + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + my $makevarfound = 0; + my $filename = basename($file,""); + while (<FILE>) { + if (/^MAKEFILE\s*=\s*(.*)/) { + $makevarfound = 1; + $makevar = $1; + if (!($makevar eq $filename)) { + print_error ("$file:$.: MAKEFILE variable $makevar != $filename"); + print " Change MAKEFILE = $filename in $file.\n\n"; + } + } + } + if ($makevarfound == 0 and !($filename eq "GNUmakefile")) { + print_error ("$file:$.: MAKEFILE variable missing in $file"); + print " Add MAKEFILE = $filename to the top of $file.\n\n"; + } + close (FILE); + } + else { + print_error ("cannot open $file"); + } + } + } +} + + +# This checks to make sure files include ace/post.h if ace/pre.h is included +# and vice versa. +sub check_for_pre_and_post () +{ + print "Running pre.h/post.h test\n"; + foreach $file (@files_h) { + my $pre = 0; + my $post = 0; + if (open (FILE, $file)) { + my $disable = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_pre_and_post/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_pre_and_post/) { + $disable = 0; + } + if ($disable == 0) { + if (/^\s*#\s*include\s*\"ace\/pre\.h\"/) { + print_error ("$file:$.: pre.h missing \"/**/\""); + ++$pre; + } + if (/^\s*#\s*include\s*\s*\"ace\/post\.h\"/) { + print_error ("$file:$.: post.h missing \"/**/\""); + ++$post; + } + if (/^\s*#\s*include\s*\/\*\*\/\s*\"ace\/pre\.h\"/) { + ++$pre; + } + if (/^\s*#\s*include\s*\/\*\*\/\s*\"ace\/post\.h\"/) { + ++$post; + } + } + } + close (FILE); + + if ($disable == 0 && $pre != $post) { + print_error ("$file:1: pre.h/post.h mismatch"); + } + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test verifies that the same number of "#pragma warning(push)" and +# "#pragma warning(pop)" pragmas are used in a given header. +sub check_for_push_and_pop () +{ + print "Running #pragma (push)/(pop) test\n"; + foreach $file (@files_h) { + my $push_count = 0; + my $pop_count = 0; + if (open (FILE, $file)) { + my $disable = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_push_and_pop/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_push_and_pop/) { + $disable = 0; + } + if ($disable == 0) { + if (/^\s*#\s*pragma\s*warning\s*\(\s*push[,1-4]*\s*\)/) { + ++$push_count; + } + if (/^\s*#\s*pragma\s*warning\s*\(\s*pop\s*\)/) { + ++$pop_count; + } + } + } + close (FILE); + + if ($disable == 0 && $push_count != $pop_count) { + print_error ("$file: #pragma warning(push)/(pop) mismatch"); + } + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test verifies that the same number of +# "ACE_VERSIONED_NAMESPACE_BEGIN_DECL" and +# "ACE_END_VERSIONED_NAMESPACE_DECL" macros are used in a given +# source file. +sub check_for_versioned_namespace_begin_end () +{ + print "Running versioned namespace begin/end test\n"; + foreach $file (@files_cpp, @files_inl, @files_h) { + my $begin_count = 0; + my $end_count = 0; + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/^\s*\w+_BEGIN_VERSIONED_NAMESPACE_DECL/) { + ++$begin_count; + } + if (/^\s*\w+_END_VERSIONED_NAMESPACE_DECL/) { + ++$end_count; + } + if ($begin_count > $end_count and + /^\s*#\s*include(\s*\/\*\*\/)?\s*"/) { + print_error ("$file:$.: #include directive within Versioned namespace block"); + } + } + + close (FILE); + + if ($begin_count != $end_count) { + print_error ("$file: Versioned namespace begin($begin_count)/end($end_count) mismatch"); + } + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + + +# Check doxygen @file comments +sub check_for_mismatched_filename () +{ + print "Running doxygen \@file test\n"; + foreach $file (@files_h, @files_cpp, @files_inl, @files_idl) { + if (open (FILE, $file)) { + my $disable = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (m/\@file\s*([^\s]+)/){ + # $file includes complete path, $1 is the name after + # @file. We must strip the complete path from $file. + # we do that using the basename function from + # File::BaseName + $filename = basename($file,""); + if (!($filename eq $1)){ + print_error ("$file:$.: \@file mismatch in $file, found $1"); + } + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# check for bad run_test +sub check_for_bad_run_test () +{ + print "Running run_test.pl test\n"; + foreach $file (@files_pl) { + if (open (FILE, $file)) { + my $is_run_test = 0; + my $sub = 0; + + print "Looking at file $file\n" if $opt_d; + + while (<FILE>) { + + if (m/PerlACE/ || m/ACEutils/) { + $is_run_test = 1; + } + + if ($is_run_test == 1) { + if (m/ACEutils/) { + print_error ("$file:$.: ACEutils.pm still in use"); + } + + if (m/unshift \@INC/) { + print_error ("$file:$.: unshifting \@INC; use \"use lib\""); + } + + if (m/\$EXEPREFIX/) { + print_error ("$file:$.: using \$EXEPREFIX"); + } + + if (m/\$EXE_EXT/) { + print_error ("$file:$.: using \$EXE_EXT"); + } + + if (m/\$DIR_SEPARATOR/) { + print_error ("$file:$.: using \$DIR_SEPARATOR"); + } + if (m/ACE\:\:/ && !m/PerlACE\:\:/) { + print_error ("$file:$.: using ACE::*"); + } + + if (m/Process\:\:/ && !m/PerlACE\:\:Process\:\:/) { + print_error ("$file:$.: using Process::*"); + } + + if (m/Process\:\:Create/) { + print_error ("$file:$.: using Process::Create"); + } + + if ((m/\.ior/ || m/\.conf/) && !m/LocalFile/) { + print_error ("$file:$.: Not using PerlACE::LocalFile"); + } + + if (m/^ [^ ]/) { + print_warning ("$file:$.: using two-space indentation"); + } + + if (m/^\s*\t/) { + print_error ("$file:$.: Indenting using tabs"); + } + + if (m/^\s*\{/ && $sub != 1) { + print_warning ("$file:$.: Using Curly Brace alone"); + } + + if (m/timedout/i && !m/\#/) { + print_error ("$file:$.: timedout message found"); + } + + if (m/^\s*sub/) { + $sub = 1; + } + else { + $sub = 0; + } + } + } + + close (FILE); + + if ($is_run_test) { + my @output = `perl -wc $file 2>&1`; + + foreach $output (@output) { + chomp $output; + if ($output =~ m/error/i) { + print_error ($output); + } + elsif ($output !~ m/syntax OK/) { + print_warning ($output); + } + } + } + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + + +# Check for links to ~schmidt/ACE_wrappers/, which should not be in the +# documentation +sub check_for_absolute_ace_wrappers() +{ + print "Running absolute ACE_wrappers test\n"; + foreach $file (@files_html) { + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (m/\~schmidt\/ACE_wrappers\//) { + chomp; + print_error ("$file:$.: ~schmidt/ACE_wrappers found"); + print_error ($_) if (defined $opt_v); + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# Make sure ACE_[OS_]TRACE matches the function/method +sub check_for_bad_ace_trace() +{ + print "Running TRACE test\n"; + foreach $file (@files_inl, @files_cpp) { + if (open (FILE, $file)) { + my $class; + my $function; + + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + + # look for methods or functions + if (m/(^[^\s][^\(]*)\:\:([^\:^\(]*[^\s^\(])\s*/) { + $class = $1; + $function = $2; + } + elsif (m/^([^\s^\(^\#]*) \(/i) { + $class = ""; + $function = $1; + } + elsif (m/^(operator.*) \(/i) { + $class = ""; + $function = $1; + } + + # Look for TRACE statements + if (m/ACE_OS_TRACE\s*\(\s*\"(.*)\"/ + || m/ACE_TRACE\s*\(\s*\"(.*)\"/) { + my $trace = $1; + + # reduce the classname + if ($class =~ m/([^\s][^\<^\s]*)\s*\</) { + $class = $1; + } + + if ($class =~ m/([^\s^\&^\*]*)\s*$/) { + $class = $1; + } + + if ($trace !~ m/\Q$function\E/ + || ($trace =~ m/\:\:/ && !($trace =~ m/\Q$class\E/ && $trace =~ m/\Q$function\E/))) { + print_error ("$file:$.: Mismatched TRACE"); + print_error ("$file:$.: I see \"$trace\" but I think I'm in \"" + . $class . "::" . $function . "\"") if (defined $opt_v); + } + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + + + +# This test checks missing ACE_ENV_ARG_PARAMETER when using +# resolve_initial_references +sub check_for_missing_rir_env () +{ + print "Running resolve_initial_references() check\n"; + foreach $file (@files_cpp, @files_inl) { + if (open (FILE, $file)) { + my $disable = 0; + my $native_try = 0; + my $in_rir = 0; + my $found_env = 0; + + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_missing_rir_env/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_missing_rir_env/) { + $disable = 0; + } + if ($disable == 0) { + next if m/^\s*\/\//; + + if (m/^\s*try/) { + $disable = 1; + next; + } + + if (m/[^\:]resolve_initial_references\s*\(/) { + $found_env = 0; + $in_rir = 1; + } + + if (m/ACE_ENV_ARG_PARAMETER/) { + $found_env = 1; + } + + if ($in_rir == 1 && m/\;\s*$/) { + $in_rir = 0; + if ($found_env != 1) { + print_error ("$file:$.: Missing ACE_ENV_ARG_PARAMETER in" + . " resolve_initial_references"); + } + $found_env = 0; + } + + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test checks for usage of ACE_CHECK/ACE_TRY_CHECK +sub check_for_ace_check () +{ + print "Running ACE_CHECK check\n"; + foreach $file (@files_cpp, @files_inl) { + if (open (FILE, $file)) { + my $disable = 0; + my $in_func = 0; + my $in_return = 0; + my $in_ace_try = 0; + my $found_env = 0; + + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_ace_check/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_ace_check/) { + $disable = 0; + } + + if (/FUZZ\: ignore check_for_ace_check/) { + next; + } + + next if m/^\s*\/\//; + next if m/^\s*$/; + + if (m/ACE_TRY\s*$/ || m/ACE_TRY_EX/ || m/ACE_TRY\s*{/) { + $in_ace_try = 1; + } + if (m/ACE_CATCH/) { + $in_ace_try = 0; + } + + if ($disable == 0) { + if (m/\s*ACE_ENV_(SINGLE_)?ARG_PARAMETER[,\)]/) { + $env_line = $.; + if ($found_env) { + print_error ("$file:$env_line: Missing ACE_CHECK/ACE_TRY_CHECK"); + } + $found_env = 1; + $in_func = 1; + } + + if (m/^\s*return/) { + $in_return = 1; + } + if ($in_return && m/;/) { + $in_return = 0; + $found_env = 0; + } + + # ignore quoted ACE_ENV_ARG_PARAMETERS's + if (m/^[^\"]*\"[^\"]*ACE_ENV_(SINGLE_)?ARG_PARAMETER[^\"]*\"[^\"]*$/) { + $found_env = 0; + } + + if (m/ACE_ENV_(SINGLE_)?ARG_PARAMETER.*ACE_ENV_(SINGLE_)?ARG_PARAMETER/) { + print_error ("$file:$.: Multiple ACE_ENV_ARG_PARAMETER"); + } + + if (m/ACE_THROW/ && $in_ace_try) { + print_error ("$file:$.: ACE_THROW/ACE_THROW_RETURN used inside of an ACE_TRY"); + } + + if ($in_func && m/\)/) { + $in_func = 0; + } + elsif (!$in_func && $found_env) { + if (m/ACE_CHECK/ && $in_ace_try) { + print_error ("$file:$.: ACE_CHECK/ACE_CHECK_RETURN used inside of an ACE_TRY"); + } + elsif (!m/_CHECK/ && !m/^\}/ && !$in_return) { + print_error ("$file:$env_line: Missing ACE_CHECK/ACE_TRY_CHECK"); + } + $found_env = 0; + } + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test checks for broken ChangeLog entries. +sub check_for_changelog_errors () +{ + print "Running ChangeLog check\n"; + foreach $file (@files_changelog) { + if (open (FILE, $file)) { + my $found_backslash = 0; + my $found_cvs_conflict = 0; + + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + + next if m/^\s*\/\//; + next if m/^\s*$/; + + # Check for backslashes in paths. + if (m/\*.*\\[^ ]*:/) { + print_error ("$file:$.: Backslashes in file path"); + } + + # Check for CVS conflict tags + if (m/^<<<<</ || m/^=====/ || m/^>>>>>/) { + print_error ("$file:$.: CVS conflict markers"); + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +sub check_for_deprecated_macros () +{ + print "Running deprecated macros check\n"; + foreach $file (@files_cpp, @files_inl, @files_h) { + if (open (FILE, $file)) { + + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + # Check for ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION usage. + if (m/ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION\)/) { + print_error ("$file:$.: ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION found."); + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} +# This test checks for ptr_arith_t usage in source code. ptr_arith_t +# is non-portable. Use ptrdiff_t instead. +sub check_for_ptr_arith_t () +{ + print "Running ptr_arith_t check\n"; + foreach $file (@files_cpp, @files_inl, @files_h) { + if (open (FILE, $file)) { + + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + + next if m/^\s*\/\//; # Ignore C++ comments. + next if m/^\s*$/; # Skip lines only containing + # whitespace. + + # Check for ptr_arith_t usage. This test should + # ignore typedefs, and should only catch variable + # declarations and parameter types. + if (m/ptr_arith_t / || m/ptr_arith_t,/) { + print_error ("$file:$.: ptr_arith_t; use ptrdiff_t instead."); + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test checks for the #include <ace/...> +# This check is suggested by Don Hinton to force user to use +# " " instead of <> to avoid confict with Doxygen. +sub check_for_include () +{ + print "Running the include check\n"; + foreach $file (@files_h, @files_cpp, @files_inl, @files_idl) { + my $bad_occurance = 0; + if (open (FILE, $file)) { + my $disable = 0; + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + if (/FUZZ\: disable check_for_include/) { + $disable = 1; + } + if (/FUZZ\: enable check_for_include/) { + $disable = 0; + } + if ($disable == 0) { + if (/^\s*#\s*include\s*<[(ace)|(TAO)|(CIAO)]\/.*>/) { + print_error ("$file:$.: include <ace\/..> used") if ($opt_v); + ++$bad_occurance; + } + if (/^\s*#\s*include\s*<tao\/.*>/) { + print_error ("$file:$.: include <tao\/..> used") if ($opt_v); + ++$bad_occurance; + } + if (/^\s*#\s*include\s*<ciao\/.*>/) { + print_error ("$file:$.: include <ciao\/..> used") if ($opt_v); + ++$bad_occurance; + } + } + } + close (FILE); + + if ($disable == 0 && $bad_occurance > 0 ) { + print_error ("$file:1: found $bad_occurance usage(s) of #include <> of ace\/tao\/ciao."); + } + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test verifies that all equality, relational and logical +# operators return bool, as is the norm for modern C++. +# +# NOTE: This test isn't fool proof yet. +sub check_for_non_bool_operators () +{ + print "Running non-bool equality, relational and logical operator check\n"; + foreach $file (@files_h, @files_inl, @files_cpp) { + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + my $found_bool = 0; + my $found_return_type = 0; + while (<FILE>) { + + if ($found_bool == 0 + && (/[^\w]bool\s*$/ + || /^bool\s*$/ + || /\sbool\s+\w/ + || /^bool\s+\w/ + || /[^\w]return\s*$/)) + { + $found_bool = 1; + $found_return_type = 0; + next; + } + + if ($found_bool == 0 && $found_return_type == 0 + && /^(?:\w+|\s+\w+)\s*$/ + && !/[^\w]return\s*$/) + { + $found_return_type = 1; + $found_bool = 0; + next; + } + + if ($found_bool == 0 + && /(?<![^\w]bool)(\s+|\w+::|>\s*::)operator\s*(?:!|<|<=|>|>=|==|!=|&&|\|\|)\s*\(/ + && !/\(.*operator\s*(?:!|<|<=|>|>=|==|!=|&&|\|\|)\s*\(/ + && !/^\s*return\s+/) { + print_error ("$file:$.: non-bool return type for operator"); + } + + $found_return_type = 0; + $found_bool = 0; + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +# This test verifies that all filenames are short enough + +sub check_for_long_file_names () +{ + my $max_filename = 50; + my $max_mpc_projectname = $max_filename - 12; ## GNUmakefile.[project_name] + print "Running file names check\n"; + + foreach $file (@files_cpp, @files_inl, @files_h, @files_html, + @files_dsp, @files_dsw, @files_gnu, @files_idl, + @files_pl, @files_changelog, @files_makefile, + @files_bor, @files_mpc) { + if ( length( basename($file) ) >= $max_filename ) + { + print_error ("File name $file meets or exceeds $max_filename chars."); + } + } + foreach $file (grep(/\.mpc$/, @files_mpc)) { + if (open(FH, $file)) { + my($blen) = length(basename($file)) - 4; ## .mpc + while(<FH>) { + if (/project\s*(:.*)\s*{/) { + if ($blen >= $max_mpc_projectname) { + print_warning ("File name $file meets or exceeds $max_mpc_projectname chars."); + } + } + elsif (/project\s*\(([^\)]+)\)/) { + my($name) = $1; + if ($name =~ /\*/) { + my($length) = length($name) + (($name =~ tr/*//) * $blen); + if ($length >= $max_mpc_projectname) { + print_warning ("Project name ($name) from $file will meet or exceed $max_mpc_projectname chars when expanded by MPC."); + } + } + else { + if (length($name) >= $max_mpc_projectname) { + print_warning ("Project name ($name) from $file meets or exceeds $max_mpc_projectname chars."); + } + } + } + } + close(FH); + } + } +} + +sub check_for_refcountservantbase () +{ + print "Running PortableServer::RefCountServantBase derivation check\n"; + + foreach $file (@files_h) { + if (open (FILE, $file)) { + print "Looking at file $file\n" if $opt_d; + while (<FILE>) { + + if (/PortableServer::RefCountServantBase/) { + print_error ("$file:$.: reference to deprecated PortableServer::RefCountServantBase"); + } + } + close (FILE); + } + else { + print STDERR "Error: Could not open $file\n"; + } + } +} + +############################################################################## + +use vars qw/$opt_c $opt_d $opt_h $opt_l $opt_t $opt_m $opt_v/; + +if (!getopts ('cdhl:t:mv') || $opt_h) { + print "fuzz.pl [-cdhm] [-l level] [-t test_name][file1, file2, ...]\n"; + print "\n"; + print " -c only look at the files passed in\n"; + print " -d turn on debugging\n"; + print " -h display this help\n"; + print " -l level set detection level (default = 5)\n"; + print " -t test_name specify any single test to run. This will disable the run level setting\n"; + print " -m only check locally modified files (uses cvs)\n"; + print " -v verbose mode\n"; + print "======================================================\n"; + print "list of the tests that could be run:\n"; + print "\t check_for_noncvs_files + check_for_synch_include + check_for_OS_h_include + check_for_streams_include + check_for_dependency_file + check_for_makefile_variable + check_for_inline_in_cpp + check_for_id_string + check_for_newline + check_for_inline + check_for_math_include + check_for_line_length + check_for_preprocessor_comments + check_for_tchar + check_for_pre_and_post + check_for_push_and_pop + check_for_versioned_namespace_begin_end + check_for_mismatched_filename + check_for_bad_run_test + check_for_absolute_ace_wrappers + check_for_bad_ace_trace + check_for_missing_rir_env + check_for_ace_check + check_for_changelog_errors + check_for_ptr_arith_t + check_for_include + check_for_non_bool_operators + check_for_long_file_names + check_for_refcountservantbase\n"; + exit (1); +} + +if (!$opt_l) { + $opt_l = 5; +} + +if ($opt_c) { + foreach $file (@ARGV) { + store_file ($file); + } +} +elsif ($opt_m) { + find_mod_files (); +} +else { + find_files (); +} + +if ($opt_t) { + &$opt_t(); + exit (1); +} + +print "--------------------Configuration: Fuzz - Level ",$opt_l, + "--------------------\n"; + +check_for_deprecated_macros () if ($opt_l > 1 ); +check_for_refcountservantbase () if ($opt_l > 1 ); +check_for_msc_ver_string () if ($opt_l >= 3); +check_for_empty_files () if ($opt_l >= 1); +check_for_noncvs_files () if ($opt_l >= 1); +check_for_streams_include () if ($opt_l >= 6); +check_for_dependency_file () if ($opt_l >= 1); +check_for_makefile_variable () if ($opt_l >= 1); +check_for_inline_in_cpp () if ($opt_l >= 2); +check_for_id_string () if ($opt_l >= 1); +check_for_newline () if ($opt_l >= 1); +check_for_inline () if ($opt_l >= 2); +check_for_math_include () if ($opt_l >= 3); +check_for_synch_include () if ($opt_l >= 6); +check_for_OS_h_include () if ($opt_l >= 6); +check_for_line_length () if ($opt_l >= 8); +check_for_preprocessor_comments () if ($opt_l >= 7); +check_for_tchar () if ($opt_l >= 4); +check_for_pre_and_post () if ($opt_l >= 4); +check_for_push_and_pop () if ($opt_l >= 4); +check_for_versioned_namespace_begin_end () if ($opt_l >= 4); +check_for_mismatched_filename () if ($opt_l >= 2); +check_for_bad_run_test () if ($opt_l >= 6); +check_for_absolute_ace_wrappers () if ($opt_l >= 3); +check_for_bad_ace_trace () if ($opt_l >= 4); +check_for_missing_rir_env () if ($opt_l >= 6); +check_for_ace_check () if ($opt_l >= 6); +check_for_changelog_errors () if ($opt_l >= 4); +check_for_ptr_arith_t () if ($opt_l >= 4); +check_for_include () if ($opt_l >= 5); +check_for_non_bool_operators () if ($opt_l > 2); +check_for_long_file_names () if ($opt_l > 1 ); + + +print "\nFuzz.pl - $errors error(s), $warnings warning(s)\n"; + +exit (1) if $errors > 0; |