#! /bin/sh
exec perl -w -l012 -x $0 ${1+"$@"}
#! perl -w -l012
#line 5

# Purpose: list all files in the vxl source tree that have tab characters
# (and that shouldn't have them because vxl C++ source files shouldn't).
# There are a few other "inconsistencies" which are also mentioned, some of
# these optionally, unless "-f" is specified on the command line.

# If "-e" is given on the command line, output lines are in this format:
# <filename>:<line_number>: # <message>
# so the result can be processed by emacs in compile-mode.  Right now
# the line number is almost always 1, which at least allows you to jump to the
# file, if not the correct line number.
# For use with vim, use "-v" on the command line; then, the output format is
# vim +<line_number> <filename> # <message>
#
# ;; sample compile command for emacs
# (setq compile-command
#  "find $VXLROOT -type f \( -name \*.cxx -o -name \*.txx -o -name \*.h \) | xargs $VXLROOT/core/bin/check_consistency -e" )
# ESC-x compile

undef $/;
$full = '';
$brief = '';
$emacs = '';
$vim = '';
$check_includes = '';

while (@ARGV && $ARGV[0] =~ m!^-!)
{
  $_ = shift @ARGV;
  if (m/^-f$/) { $full = 1; }
  elsif (m/^-b$/) { $brief = 1; }
  elsif (m/^-e$/) { $emacs = 1; }
  elsif (m/^-v$/) { $vim = 1; }
  elsif (m/^-i$/) { $check_includes = 1; }
  else { warn "Unrecognised command line option $_ ignored\n"; }
}

if (@ARGV)
{
  @FILES = @ARGV;
}
else
{
  $V = $ENV{VXLROOT};
  if (defined($V)) {
    $DIRS = "$V/vcl $V/core $V/contrib $V/v3p/Qv";
  }
  elsif (-d 'vcl' && -d 'core' && -d 'contrib') {
    $V = '.'; $DIRS = "vcl core contrib v3p/Qv";
  }
  else
  {
    die "VXLROOT is not defined, and no command line arguments were given\n";
  }
  $FILES = qx(find $DIRS -type f \\\( -name \\\*.cxx -o -name \\\*.txx -o -name \\\*.cc -o -name \\\*.cpp -o -name \\\*.c -o -name \\\*.h -o -name \\\*.hxx -o -name \\\*.cl \\\) -print);
  @FILES = grep { ! m!/b3p/(minizip|shapelib|expatp*)/! } split /\s+/, $FILES;
}

# In what follows, $f is the name of the file, $file is the file content, and $file_s is a comment-stripped version of $file.
foreach $f (@FILES)
{
  $f =~ s!\\!/!g; # directory delimiter
  if (-d $f)
  {
    warn "File $f is actually a directory\n";
    next;
  }
  unless (open(FILE, $f))
  {
    warn "File $f does not exist or cannot be opened for reading\n";
    next;
  }
  $file=<FILE>;
  close FILE;
  next unless (defined($file));
  $file =~ s!\$\{FILESTEM\}!classtemplate_emacs!g;
  $file =~ s!libname/classname!config/classtemplate!g;
  $file =~ s!\@\(eval \(file-name-nondirectory \(file-name-directory-noslash dirname\)\)\)/\@\(eval dirbase\)!config!g;
  $printed = $full;

  $cpp_file = ($f !~ m!\.c$! &&
               $f !~ m!\.cl$! &&
               $f !~ m!\bintroduction_doxy\.txt$! &&
               $f !~ m!_mocced\.cxx$! &&
               $f !~ m!\bv3p/(netlib|[jm]peg2?|tiff|png|zlib|bzlib|Qv)/! &&
               $f !~ m!vil1?/file_formats/vil1?_viff(header|_support)! &&
               $f !~ m!\bvgui/internals/trackball! &&
               $f !~ m!\bcore/vgl/internals/gpc\.h$! &&
               $f !~ m!\bcore/vidl_vil1/vidl_vil1_mpegcodec_helper\.cxx$! &&
               $f !~ m!/oufgl/(pxc200|bt848(-addons)?)\.h$! &&
               $f !~ m!\bgel/vgel/kl/.*\.h$! &&
               $f !~ m!\bvcl(/[^/]+)?/vcl_(c|[siof]+stream|io|strstream|streambuf)! &&
               $f !~ m!\bvcl/emulation/!
              );
  study $file;

# 1. abnormal characters (tabs, ascii < 32, etc.)
  $file =~ s!\347!c!g; # treat  as normal character
  $file =~ s!(\"http:)//!$1\\\\!g; # do not treat "http://" as a comment delimiter
  &msg(1, "contains tabs")
    if ($file =~ m!\t! && $file !~ m!\basm\s*\(\"\t! && $f !~ m!\bv3p/netlib/!);
  &msg(1, "contains carriage returns (ascii 13)")
    if ($file =~ m!\r! && $f !~ m!\.ds[pw]$!);
  &msg(1, "contains non-standard ascii characters")
    if ($f !~ m!test_vul_file\.cxx! &&
        $file =~ m![\000-\010\013\014\016-\037\177-\257\261-\277\320\327\336\360\367\376]!);

# 2. no end-of-line at end-of-file
  &msg(10000, "has no final end-of-line")
    unless ($file eq '' || substr($file,-1) eq "\n");

# 3. spaces (more than 1) at end of line
  $has_end_spaces = ($file =~ m!  +\n!);

# 4. Lines longer than 132 characters, continuation ostream, single-char strings
  if ($file =~ m!^[^#].{132,}! && $f !~ m!\.dsp$!)
  {
    $tmp=$file; $tmp =~ s!.{133,}[^\000]*!!; $tmp =~ s![^\n]*!!g; $tmp=length($tmp)+1;
    &msg($tmp, "has lines of more than 132 characters");
  }
  &msg(1, "has vcl_endl following a string: consider replacing by \"\\n\"")
    if ($printed && $file =~ m!\"\s*\<\<\s*vcl_endl\b!);
  &msg(1, "consider joining consecutive \"\<\<\" output lines for $2")
    if ($printed && $file =~ m![{;:](\s*//.*\n)?\s*([a-zA-Z]\S*)\s*\<\<[^;]+\;\s*\2\s*\<\<!);
  &msg(1, "consider joining consecutive strings in output for $1")
    if ($printed && $file =~ m!(\S+)\s*\<\<[^;]*(..)\"\s*\<\<\s*\"! && $2 ne "\\n" && $2 ne " -");
  $file =~ s/\\\"/\005/g;
  &msg(1, "consider replacing \"$2\" by \'$2\' in output for $1")
    if ($printed && $file =~ m!(\S+)\s*\<\<[^;]+\"([^\\]|\\.)\"!);
  $file =~ s/\005/\\\"/g;
  &msg(1, "consider removing space before \\n")
    if ($printed && $file =~ m!(\s|\\t)(\\n\b|\"\s*<<\s*vcl_endl)!);

# 5. Consecutive comment blocks, separated by blank lines
  if ($file =~ m!\n(\s*)//:.*\n(\1//.*\n)*\s*\n\1// *[^:=*-]! &&
      $f !~ m!\bvcl_config_(compiler|headers)\.h$! &&
      $f !~ m!\bvnl/vnl_error\.h$!)
  {
    $tmp=$file; $tmp =~ s!\n\s*//:.*\n( *//.*\n)*\s*\n\s*[^\000]*!!; $tmp =~ s![^\n]*!!g; $tmp=length($tmp)+2;
    &msg($tmp, "contains comment blocks separated by a blank line; consider joining");
  }

# 6. Quick consistency check of Doxygen structured comments, including ambiguous \date
  &msg(1, "Doxygen comments will not be shown without \\file")
    if ($file =~ m!\n\s*//:! && $file !~ m!\n\s*//:(\s*\n\s*//)?\s*\\file\b! &&
                                $file !~ m!^\s*//:(\s*\n\s*//)?\s*\\file\b!);
  &msg(1, "Doxygen \\file better not have an argument, so remove \"$1\"")
    if ($file =~ m!//\s*\\file[ \t]+(\S.*)!);
  if ($file =~ m!\n\s*//(:|\s*\\brief\b)[ \t]*(.{40,})\n *// *([a-z].*)!)
  {
    $first=$2; $second=$3;
    unless ($first =~ m/[.?!]$/ || $second =~ m!^v[bcginpsu]l_!)
    {
      $tmp=$file; $tmp =~ s!\n\s*//(:|\s*\\brief\b)[ \t]*(.{40,})\n *//[^\000]*!!; $tmp =~ s![^\n]*!!g; $tmp=length($tmp)+2;
      &msg($tmp, "brief Doxygen comment possibly continued on next line");
    }
  }
  elsif ($file =~ m!\n\s*//(:|\s*\\brief\b)(.{40,}\b(and|if|but|since|that|,))\s*\n *// *(.+)!i)
  {
    $tmp=$file; $tmp =~ s!\n\s*//(:|\s*\\brief\b)(.{40,}\b(and|if|but|since|that|,))\s*\n *// *(.+)[^\000]*!!i; $tmp =~ s![^\n]*!!g; $tmp=length($tmp)+2;
    &msg($tmp, "brief Doxygen comment possibly continued on next line");
  }
  &msg(1, "Ambiguous \\date $1")
    if ($file =~ m!\n\s*//\s*\\date\s+\b((\d\d)?[/.-](\d\d?)[/.-](\d\d+))! && (($2 <= 12 && $3 <= 12 && $2 != $3) || $printed));

# 7. Unnecessary #include files and missing #include files.
#   Unnecessary includes are in principle anything which is not
#   used or directly referred to in the current file.
#   Missing includes is currently only vcl_cassert.h and vcl_iostream.h
#   unless the command line switch "-i" was given (variable "$check_includes")

  if ($check_includes)
  {
    @class_list = map {s!^\s*\#\s*include\s*[<\"](.*?)[>\"].*!$1!; s/\bvpl\.h/vpl_.h/; $_} grep {m!^\s*\#\s*include!} split /\n/,$file;
    $file =~ s!\#\s*include\s*[<\"].*?[>\"]\s*!!g;
    $file =~ s!\bvnl_huge_val\b!vnl_math_huge!g;
    $file =~ s!\bVIL_PIXEL_FORMAT_\w+!vil_pixel_format!g;
    $file =~ s!\b(VNL_)?MATLAB_?PRINT\w*!vnl_matlab_print!g;
    $file =~ s!\bvnl_log_beta!vnl_beta!g;
    $file =~ s!\b(vnl_log_gamma|vnl_digamma|vnl_cum_prob_chi2)!vnl_gamma!g;
    $file =~ s!\bmbl_erf\b!mbl_gamma!g;
    foreach $pref (qw(vul vbl vpl vil vnl vgl vidl vcsl vpgl vpdl mbl))
    {
      foreach $class (map {s!^$pref/(${pref}_[^/]+)\.h$!$1!; s!(vul_get_time)stamp!$1!; s!(mbl_matrix_product)s!$1!; s!(vnl_matlab_print)2!$1!; $_}
                      grep {!m!_traits\.h$! && m!^$pref/${pref}_([^/]+)\.h$! && $1 ne 'fwd' } @class_list)
      {
        my $x = $class; $x =~ s!_sptr$!!;
        &msg(1,"maybe unnecessary #include <$pref/$class.h>")
          unless ($class =~ m!^${pref}_config$! || $f =~ m!/test_include\.cxx$! || $f =~ m!/Templates/! || $file =~ m!\b$class! || $f =~ m!$x\.h$!);
      }
    }
  }
  $fl = $file; $fl =~ s!//.*!!g;
  $includes = "\004\n$fl\003";
  $includes =~ s!\n\s*\#\s*include\s\<([^>]+)\>.*!\003$1\004!g;
  $includes =~ s!^[^\003]*\003!\003!; $includes =~ s!\004[^\004]*$!\004!;
  $includes =~ s!\004[^\003]*\003!\n!g; $includes =~ s![\004\003]!!g;
  @includes = sort split "\n", $includes;
  $jj = ""; $found_cassert = ""; $found_iostream = "";
  foreach $j (@includes)
  {
    next if ($j eq '');
    next if ($j =~ m!^Q[A-Z]\w+$! && $f =~ m!\bvgui/impl/qt!);
    $found_cassert = 1 if ($j eq 'vcl_cassert.h' || $j eq 'assert.h');
    $found_iostream = 1 if ($j =~ m!^vcl_((i|o|io|f)stream|iosfwd|streambuf)\.h! || $j eq 'vsl/vsl_binary_io.h');
    &msg(1, "invalid #include <$j>")
      unless ($j =~ m!\.(h|H|hxx|hpp|txx)$! ||
              $f =~ m!\bvcl/|\bcmake/config/! ||
              $j eq 'std/complext.cc');
    next unless ($j =~ m!\.h$!i);
    next if ($f =~ m!(v.l)/tests/(\1_)?test_(includes?|all)\.cxx$! && $j =~ m!^$1(/algo)?/$1_!);
    next if ($f =~ m!vnl/algo/Templates/vcl_vector\+vnl_amoeba_SimplexCorner-\.cxx$! && $j eq 'vnl/algo/vnl_amoeba.h');
    next if ($f =~ m!vnl/vnl_math\.cxx$! && $j eq 'math.h');
    next if ($f =~ m!vpl/vpl\.cxx$! && $j eq 'vpl/os_unix/vpl.cxx');
    next if ($f =~ m!vbl_test_smart_ptr\.cxx$! && $j eq 'vbl/vbl_smart_ptr.h');
    next if ($f =~ m!vpdfl/vpdfl_all\.h$!);
    next if ($f =~ m!pdf1d/pdf1d_all\.h$!);
    next if ($f =~ m!doc/vxl_doc_rules\.h!);
    &msg(1, "has multiple occurrence of \#include <$j>")
      if ($j eq $jj &&
          $f !~ m!\bvcl/vcl_(cstddef|climits|new|sys/time)\.h$! &&
          $f !~ m!\bvcl/tests/test_stlfwd\.cxx$! &&
          $f !~ m!\bcmake/config/vxl_platform_tests\.cxx$! &&
          $f !~ m!\bv.l/io/tests/golden_test_v.l_io\.cxx$! &&
          $f !~ m!\bvnl/vnl_sse.h$! &&
         "$f-$j" !~ m!\bvnl/vnl_math\.cxx-float\.h$! &&
         "$f-$j" !~ m!\bv3p/netlib/triangle\.c\-math\.h$! &&
         "$f-$j" !~ m!\bv3p/png/tests/pngtest\.c\-time\.h$! &&
         "$f-$j" !~ m!\bbgui3d_file_io\.cxx-Inventor/! &&
         "$f-$j" !~ m!\bboxm_ocl_\w+_tableau\.cxx-GL/glew\.h$! &&
         "$f-$j" !~ m!\bbocl_cl\.h-CL/cl\.h$! &&
          $j !~ m!^(stdlib|varargs|sys/types|stdio|windows|GL/glu?t?)\.h$!);
    $jj = $j; $i = $j;
    next unless ($i =~ s!^(v[bginpsu]l|vil1|vgui|vidl|vidl_vil1|vpgl|vpdl|vtol|vsol|vdgl|vipl/vipl_with_[a-z_]+|vipl|vepl1?|mbl|pdf1d|vpdfl|mil|mil3d|vimt|vimt3d|gevd|bsol|btol|bugl|bvnl|bvgl|bgui|bdgl|rrel|rsdl|rgrl)/(file_formats/|algo/|io/|internals/|filter/|section/|vrml/|impl/(X|glut|gtk|mfc)/|)(.*)\.h!$4! || $i =~ s!^(v[cx]l_[a-z]+)\.h$!$1!);
#   next if ("$f-$j" =~ m!(.*)\.h-\1_sptr\.h!);
    next if ($j eq 'vcl_compiler.h' || $j eq 'vcl_new.h');
    next if ($j eq 'vcl_cstdio.h' && $f =~ m!/StdAfx\.h$!);
    next if ($j eq 'vcl_cmath.h' && $f =~ m!\bvcl/(vcl_cfloat|win32-vc60/vcl_complex)\.h$!);
    next if ($j eq 'vcl_cmath.h' && $f =~ m!\bvnl/algo/vnl_generalized_eigensystem\.cxx$!);
    next if ($j eq 'vcl_cstdlib.h' && $f =~ m!\bvcl/emulation/vcl_algobase\.h$!);
    next if ($j eq 'vcl_ctime.h' && $f =~ m!\bvcl/emulation/vcl_alloc\.h$!);
    next if ($j eq 'vcl_algorithm.h' && $f =~ m!\bvcl/gcc-295/vcl_deque\.txx$!);
    next if ($i =~ m!^(vnl|vil|vil1|vsl|vul|vpl|vgl|vgl_algo|vbl)_fwd$! || $i =~ m!^vgui_glu?x?t?$! || $i eq 'StdAfx');
    next if ($i =~ m!^mil_! && $f =~ m!\bmul/mil/mil_all\.h$!);
    next if ($j eq 'mil/mil_all.h' && $f =~ m!\bmul/mil/mil_add_all_loaders\.cxx$!);
    next if ($i =~ m!^(v.l)_io_! && $f =~ m!/$1/io/!);
    next if ($i =~ m!^accessors/vipl_accessors_! && $f =~ m!/v[ie]pl2?/!);
    next if ($i =~ m!^vbl_sparse_array_[123]d$! && $f =~ m!vbl/io/vbl_io_sparse_array_[123]d\.h$!);
    next if ($i eq 'vcl_string' && $f =~ m!vgui/impl/gtk/(vgui_gtk_adaptor\.h|Templates/vcl_vector\+GtkWidget\~-\.cxx)$!);
    next if ($j eq 'vsol/vsol_line_2d.h' && $f =~ m!bbas/bgui/bgui_vsol_soview2D\.cxx$!);
    $ii = $i;
    $i =~ s!^([vb]gui.*)!$1\(\|_sptr\|_new\)!;
    $i =~ s!^(v(so|to|dg|cs)l.*)!$1\(\|_sptr\)! unless ($f =~ m!\.h$!);
    # CURRENTLY NOT YET WELL TESTED, HENCE IGNORED:
    next if (!$check_includes && $j =~ m!^(vsl/|vidl_vil1/|vidl/|vgui/|bgui/|vsol/|vtol/|vdgl/|vpgl/|vpdl/|v.l/io/|rgrl/|rsdl/|rrel/)!);
    # VCL
    if ($j eq 'vcl_algorithm.h') { $i='vcl_(adjacent_find|and|binary|binary_search|copy|copy_|count|count_if|equal|equal_range|fill|fill_n|find|find_end|find_first_of|find_if|for_each|generate|generate_n|generators_|heap|includes|inplace_merge|iter_swap|lexicographical_compare|lower_bound|make_heap|max|min|max_element|merge|merge_|min_element|mismatch|next_permutation|nth_element|partial_sort|partial_sort_copy|partition|stable_partition|partitions_|pop_heap|prev_permutation|push_heap|random_shuffle|remove|remove_copy|remove_copy_if|remove_if|replace|replace_copy|replace_copy_if|replace_if|reverse|reverse_copy|rotate|rotate_copy|search|search_n|set_difference|set_intersection|set_symmetric_difference|set_union|sort|sort_|sort_heap|stable_sort|swap|swap_|swap_ranges|transform|unique|unique_copy|upper_bound)'; }
    elsif ($j eq 'vxl_config.h') { $i='VXL_\w+|vxl_([su]?(int|ieee)_(8|16|32|64)|s?byte)'; }
    elsif ($j eq 'vcl_cassert.h') { $i='assert'; }
    elsif ($j eq 'vcl_cctype.h') { $i='(vcl_|)(isalnum|isdigit|isprint|isupper|tolower|isalpha|isgraph|ispunct|isxdigit|toupper|iscntrl|islower|isspace)'; }
    elsif ($j eq 'vcl_cerrno.h') { $i='errno|EBUSY|EEXIST'; }
    elsif ($j eq 'vcl_cfloat.h') { $i='FLT_MAX|DBL_MAX|MAXFLOAT|MAXDOUBLE'; }
    elsif ($j eq 'vcl_climits.h') { $i='CHAR_BIT|CLK_TCK|[US]?(INT|CHAR)_(MIN|MAX)'; }
    elsif ($j eq 'vcl_cmath.h') { $i='vcl_(abs|acos|asin|atan|atan2|ceil|cos|cosh|exp|fabs|floor|fmod|frexp|ldexp|log|log10|modf|pow|sin|sinh|sqrt|tan|tanh)|hypot|HUGE_VAL'; }
    elsif ($j eq 'vcl_complex.h') { $i='vcl_(complex|real|imag|abs|arg|norm|conj|polar|cos|cosh|exp|log|log10|pow|sin|sinh|sqrt|tan|tanh)'; }
    elsif ($j eq 'vcl_complex.h' && $f =~ m!/tests/test_cmath\.cxx$!) { $i=''; }
    elsif ($j eq 'vcl_csetjmp.h') { $i='setjmp|vcl_(jmp_buf|longjmp)'; }
    elsif ($j eq 'vcl_csignal.h') { $i='vcl_(sig_atomic_t|raise|signal)'; }
    elsif ($j eq 'vcl_cstdarg.h') { $i='(vcl_|)va_list'; }
    elsif ($j eq 'vcl_cstddef.h') { next if ($f =~ m!\bcore/vil1?(/file_formats)?/vil1?_jpeglib\.h$!); $i='vcl_(ptrdiff_t|size_t)'; }
    elsif ($j eq 'vcl_cstdio.h') { next if ($f =~ m!\b(vcl/vcl_cassert|core/vil1?(/file_formats)?/vil1?_jpeglib)\.h|\bcore/vul/vul_temp_filename\.cxx$!); $i='vcl_(FILE|fpos_t|fopen|fclose|feof|ferror|fflush|fgetc|fgetpos|fgets|fwrite|fread|fseek|ftell|perror|clearerr|rename|fputc|fputs|freopen|fsetpos|getc|getchar|gets|putc|putchar|puts|remove|rewind|setbuf|setvbuf|tmpfile|tmpnam|ungetc|printf|sprintf|fprintf|vprintf|vsprintf|vfprintf|scanf|sscanf|fscanf|vscanf|vsscanf|vfscanf)|EOF'; }
    elsif ($j eq 'vcl_cstdlib.h') { next if ($f =~ m!\bvcl/vcl_cassert\.h$!); $i='vcl_(abs|div|labs|ldiv|srand|rand|atexit|getenv|system|exit|abort|qsort|calloc|malloc|free|realloc|atol|atof|atoi|mblen|mbstowcs|mbtowc|strtod|strtol|strtoul|wctomb|wcstombs)|[sd]rand48|memalign|EXIT_FAILURE'; }
    elsif ($j eq 'vcl_cstring.h') { $i='vcl_(memchr|memcmp|memcpy|memmove|memset|strcat|strchr|strcmp|strcoll|strcpy|strcspn|strerror|strlen|strncat|strncmp|strncpy|strpbrk|strrchr|strspn|strstr|strtok|strxfrm)'; }
    elsif ($j eq 'vcl_ctime.h') { $i='vcl_(clock_t|time_t|tm|asctime|clock|difftime|localtime|strftime|ctime|gmtime|mktime|time)'; }
    elsif ($j eq 'vcl_cwchar.h') { $i='vcl_(mbstate_t|wint_t|btowc|fgetwc|fgetws|fputwc|fputws|fwide|fwprintf|fwscanf|getwc|getwchar|mbrlen|mbrtowc|putwc|putwchar|swprintf|swscanf|ungetwc|vfwprintf|vswprintf|vwprintf|wcrtomb|wcscat|wcschr|wcscmp|wcscoll|wcscpy|wcscspn|wcsftime|wcslen|wcsncat|wcsncmp|wcsncpy|wcspbrk|wcsrchr|wcsrtombs|wcsspn|wcsstr|wcstod|wcstok|wcstol|wctoul|wcsxfrm|wctob|wmemchr|wmemcmp|wmemcpy|wmemmove|wmemset|wprintf|wscanf)'; }
    elsif ($j eq 'vcl_cwctype.h') { $i='vcl_(wctrans_t|wctype_t|wint_t|iswalnum|iswalpha|iswcntrl|iswctype|iswdigit|iswgraph|iswlower|iswprint|iswpunct|iswspace|iswupper|iswxdigit|iswctrans|iswupper|iswxdigit|towctrans|towlower|towupper|wctrans|wctype)'; }
    elsif ($j eq 'vcl_deque.h') { $i='vcl_(deque|swap)'; }
    elsif ($j eq 'vcl_deprecated.h') { $i='vcl_deprecated_(warn|abort)|VXL_DEPRECATED'; }
    elsif ($j eq 'vcl_exception.h') { $i='vcl_(exception|bad_exception|throw|catch|catch_all)'; }
    elsif ($j eq 'vcl_fstream.h') { next if ($f =~ m!\bvcl/(Templates/f?stream|vcl_iostream)!); $i='vcl_(filebuf|fstream|ifstream|ofstream)'; }
    elsif ($j eq 'vcl_functional.h') { $i='vcl_((|pointer_to_)(unary|binary)_(function|negate)|plus|minus|multiplies|divides|modulus|negate|(|not_)equal_to|(greater|less)(|_equal)|logical_(and|or|not)|not(1|2)|bind(|er)(1st|2nd)|ptr_fun|(|const_)mem_fun(|1)(|_ref)(_t|)|transform)'; }
    elsif ($j eq 'vcl_iomanip.h') { $i='vcl_((re|)setiosflags|set(base|fill|precision|w)|(no|)(boolalpha|showbase|showpoint|showpos|skipws|uppercase)|internal|left|right|dec|hex|oct|fixed|scientific)'; }
    elsif ($j eq 'vcl_ios.h') { next if ($f =~ m!\bvcl_iomanip\.h$!); $i='vcl_(ios|streamoff|streamsize|fpos|basic_ios|ios_((base|float|adjust)field|(no|)(boolalpha|showbase|showpoint|showpos|skipws|uppercase)|internal|left|right|dec|hex|oct|fixed|scientific|fmtflags|seekdir|beg|cur|end))'; }
    elsif ($j eq 'vcl_iosfwd.h') { $i='vcl_((basic_||w)(io|i|o|if|of|f|(|i|o)string)stream|streamoff|char_traits|allocator|(basic||w)_ios|(basic_||w)(stream|string|file)buf|(i|o)streambuf_iterator|fpos|(|w)streampos)'; }
    elsif ($j eq 'vcl_istream.h') { $i='vcl_(basic_||w)i(|o)stream'; }
    elsif ($j eq 'vcl_iostream.h') { next if ($f =~ m!/(vcl_ios\.h|StdAfx\.h)$!); $i='vcl_(cin|cout|cerr|clog|(i|o)stream|endl|ends|flush|stream(pos|buf|size)|hex|oct|dec|ws|setfill|setprecision|setw|fixed|scientific)|vgui_macro_warning'; }
    elsif ($j eq 'vcl_iterator.h') { next if ($f =~ m!\brpl/rrel/rrel_util\.h$!); $i='vcl_(iterator_traits|(|reverse_|(i|o)stream(|buf)_|(back_|front_|)insert_)iterator|(|back_|front_)inserter|(input|output|forward|bidirectional|random_access)_iterator_tag|advance|distance)'; }
    elsif ($j eq 'vcl_limits.h') { $i='vcl_(numeric_limits|float_round_style|float_denorm_style)'; }
    elsif ($j eq 'vcl_list.h') { $i='vcl_(list|swap)'; }
    elsif ($j eq 'vcl_locale.h') { $i='vcl_(use_facet|has_facet|isspace|isprint|iscntrl|isupper|islower|isalpha|isdigit|ispunct|isxdigit|isalnum|isgraph|toupper|tolower|ctype|codecvt_base|(codecvt|collate|(num|money)punct|time_(get|put)|messages)(|_byname)|(num|money)(_get|_put))'; }
    elsif ($j eq 'vcl_map.h') { $i='vcl_(map|multimap|swap)'; }
    elsif ($j eq 'vcl_memory.h') { $i='vcl_(allocator|raw_storage_iterator|get_temporary_buffer|return_temporary_buffer|uninitialized_copy|uninitialized_fill|uninitialized_fill_n|auto_ptr)'; }
    elsif ($j eq 'vcl_new.h') { $i='new'; }
    elsif ($j eq 'vcl_numeric.h') { $i='vcl_(accumulate|inner_product|partial_sum|adjacent_difference)'; }
    elsif ($j eq 'vcl_ostream.h') { $i='vcl_((basic_||w)ostream|endl|ends|flush)'; }
    elsif ($j eq 'vcl_queue.h') { $i='vcl_(|priority_)queue'; }
    elsif ($j eq 'vcl_set.h') { $i='vcl_(set|multiset|swap)'; }
    elsif ($j eq 'vcl_sstream.h') { $i='vcl_((basic_||w)stringbuf|(|i|o)stringstream)'; }
    elsif ($j eq 'vcl_stack.h') { $i='vcl_stack'; }
    elsif ($j eq 'vcl_stlfwd.h') { next; }
    elsif ($j eq 'vcl_stdexcept.h') { $i='vcl_(logic_error|domain_error|invalid_argument|length_error|out_of_range|runtime_error|range_error|overflow_error|underflow_error)'; }
    elsif ($j eq 'vcl_streambuf.h') { $i='vcl_(basic_|)streambuf'; }
    elsif ($j eq 'vcl_string.h') { $i='vcl_(char_traits|(basic_||w)string|swap|getline)'; }
    elsif ($j eq 'vcl_strstream.h') { $i='vcl_(|i|o)strstream'; }
    elsif ($j eq 'vcl_typeinfo.h') { $i='typeid|vcl_(type_info|bad_cast|bad_typeid)'; }
    elsif ($j eq 'vcl_utility.h') { $i='vcl_(pair|make_pair)'; }
    elsif ($j eq 'vcl_valarray.h') { $i='vcl_(valarray|slice|slice_array|gslice|gslice_array|mask_array|indirect_array|abs|acos|asin|atan|atan2|cos|cosh|exp|log|log10|pow|sin|sinh|sqrt|tan|tanh)'; }
    elsif ($j eq 'vcl_vector.h') { $i='vcl_(vector|swap)'; }
    # VBL
    elsif ($j eq 'vbl/vbl_bounding_box.h') { $i.='(|_base)'; }
    elsif ($j eq 'vbl/vbl_qsort.h') { $i.='(|_(double|int|)(a|de)scending|_helper)'; }
    elsif ($j eq 'vbl/vbl_sort.h') { $i.='_((double|int|)(a|de)scending|helper)'; }
    # VBL-IO
    elsif ($j eq 'vbl/io/vbl_io_smart_ptr.h') { $i.='|_IO_INSTANTIATE.*_sptr'; }
    # VUL
    elsif ($j eq 'vul/vul_arg.h') { $i.='(|_parse|_include|_display_usage_and_exit|_info_list)'; }
    elsif ($j eq 'vul/vul_file.h') { $i.='(|_exists|_is_directory|_size|_extension)'; }
    elsif ($j eq 'vul/vul_get_timestamp.h') { $i.='|vul_get_time_as_string'; }
    elsif ($j eq 'vul/vul_ios_state.h') { $i.='_saver'; }
    elsif ($j eq 'vul/vul_string.h') { $i.='(_c_|_)((up|down)case|capitalize|(|left_|right_)trim|reverse|atoi|atof|bool|expand_var)'; }
    # VPL
    elsif ($j eq 'vpl/vpl.h') { $i.='_(getcwd|mkdir|rmdir|chdir|unlink|sleep|usleep|putenv|getpid)'; }
    # VSL
    elsif ($j eq 'vsl/vsl_binary_io.h') { $i='vsl_b_(read|write|[io]f?stream)'; }
    elsif ($j eq 'vsl/vsl_block_binary.h') { $i.='_(read|write)'; }
    elsif ($j eq 'vsl/vsl_binary_loader.h') { next if ($f =~ m!/Templates/(\S+\~-|vbl_io_smart_ptr\+\S+)\.cxx$!); $i.='|vsl_b_(read|write)|vsl_delete_all_loaders'; }
    elsif ($j eq 'vsl/vsl_binary_explicit_io.h') { $i='vsl_(convert_[a-z_]+|swap_bytes|swap_bytes_to_buffer|b_(read|write)_[a-z_]+)'; }
    elsif ($j eq 'vsl/vsl_complex_io.h') { $i='VNL_IO_[A-Z]+_INSTANTIATE.vcl_complex|vsl_b_(read|write)'; }
    elsif ($j eq 'vsl/vsl_indent.h') { $i.='(|_inc|_dec|_set_tab|_tab|_clear|_clear_all_data)'; }
    elsif ($j eq 'vsl/vsl_quick_file.h') { $i.='_(load|save)'; }
    elsif ($j eq 'vsl/vsl_stream.h') { $i.='_summary(|_t)'; }
    # VGL
    elsif ($j eq 'vgl/vgl_area.h') { $i.='(|_enforce_orientation|_signed)|vgl_centroid'; }
    elsif ($j eq 'vgl/vgl_clip.h') { $i.='(|_type|_line[a-z_]+)'; }
    elsif ($j eq 'vgl/vgl_convex.h') { $i.='(_hull)'; }
    elsif ($j eq 'vgl/vgl_closest_point.h') { $i.='(|s|_origin|_to_linesegment|_to_(|non_)closed_polygon)'; }
    elsif ($j eq 'vgl/vgl_distance.h') { $i.='(|_origin|(|2)_to_linesegment|_to_(|non_)closed_polygon)'; }
    elsif ($j eq 'vgl/vgl_lineseg_test.h') { $i.='(_point|_line|_lineseg)'; }
    elsif ($j eq 'vgl/vgl_triangle_test.h') { $i.='_(discriminant|inside)'; }
    elsif ($j eq 'vgl/vgl_triangle_3d.h') { $i.='_([a-z]+_intersection|distance|coplanar|area|aspect_ratio|coincident_edges|test_inside(|_simple)|(shortest|longest)_side|closest_point)'; }
    elsif ($j eq 'vgl/algo/vgl_homg_operators_2d.h') { $i.='|vnl_double_3x3[^\000]*vgl_homg_point_2d|cond_matrix . x'; }
    elsif ($j eq 'vgl/algo/vgl_homg_operators_3d.h') { $i.='|vnl_double_4x4[^\000]*vgl_homg_point_3d|p_matrix_ \* X'; }
    elsif ($j eq 'vgl/algo/vgl_rtree_c.h') { $i='vgl_rtree_point_box_2d|vgl_rtree_box_box_2d|vgl_bbox_2d|vgl_rtree_polygon_probe'; }
    elsif ($j eq 'vgl/xio/vgl_xio_point_2d.h') { $i='x_write'; }
    # VIL & VIL1
    elsif ($j =~ m'vil1/vil1_\d+bit\.h$') { $i.='(|_(read|write)_(big|little)_endian)'; }
    elsif ($j =~ m'vil/vil_bi(lin|cub)_interp\.h$') { $i.='(|_safe|_unsafe|_raw|_safe_extend)'; }
    elsif ($j eq 'vil1/vil1_clamp.h') { $i.='(|_pixel)'; }
    elsif ($j eq 'vil/vil_clamp.h') { $i.='(|_below|_image_resource)'; }
    elsif ($j eq 'vil/vil_color_table.h') { $i='color_value|color_theme'; }
    elsif ($j =~ m'(vil/algo|vil1)/vil1?_colour_space.h') { $i.='_(RGB|HSV|YUV)_to_(YUV|YIQ|HSV|RGB)'; }
    elsif ($j eq 'vil/vil_config.h') { $i='HAS_[A-Z]+'; }
    elsif ($j eq 'vil/vil_convert.h') { $i.='_((cast|round)(|_pixel)|(rgb|planes)_to_grey|stretch_range\S*|to_[a-z_]+)'; }
    elsif ($j eq 'vil1/vil1_convolve.h') { $i.='_(signal_[12]d|1d_[xy]|separable|boundary_option|trim|[a-z]+_extend)'; }
    elsif ($j eq 'vil/vil_copy.h') { $i.='(|_deep|_to_window|_reformat)'; }
    elsif ($j eq 'vil/vil_exception.h') { $i.='(_error|_warning|(|_assignment)_pixel_formats_incompatible|_image_io)'; }
    elsif ($j eq 'vil/vil_fill.h') { $i.='(|_line|_row|_col|_mask|_disk)'; }
    elsif ($j eq 'vil/vil_flip.h') { $i.='_(ud|lr)'; }
    elsif ($j eq 'vil1/vil1_image_as.h') { $i.='(|(_rgb_|_)(byte|uint16|int|float|double))'; }
    elsif ($j eq 'vil/vil_image_resource.h') { $i.='(|_sptr)'; }
    elsif ($j eq 'vil/vil_image_resource_sptr.h') { $i='vil_image_resource(|_sptr)'; }
    elsif ($j eq 'vil/vil_blocked_image_resource.h') { $i.='(|_sptr)|blocked_image_resource'; }
    elsif ($j eq 'vil/vil_pyramid_image_resource.h') { $i.='(|_sptr)'; }
    elsif ($j eq 'vil/vil_pyramid_image_resource_sptr.h') { $i='vil_pyramid_image_resource(|_sptr)'; }
    elsif ($j eq 'vil/vil_image_view.h') { $i.='(|_deep_equality)'; }
    elsif ($j eq 'vil/vil_image_view_base.h') { $i.='(|_sptr)'; }
    elsif ($j eq 'vil1/vil1_interpolate.h') { $i.='_(nearest|bilinear(|_grad)|bicubic)'; }
    elsif ($j eq 'vil/vil_load.h') { $i.='(|_image_resource(|_raw))'; }
    elsif ($j eq 'vil/vil_math.h') { $i.='_([a-z_]+)'; }
    elsif ($j eq 'vil/vil_memory_chunk.h') { $i.='(|_sptr)'; }
    elsif ($j eq 'vil1/vil1_memory_image.h') { $i.='(|_format)'; }
    elsif ($j eq 'vil/vil_nearest_interp.h') { $i.='(|_safe|_safe_extend)'; }
    elsif ($j eq 'vil/vil_nearest_neighbour_interp.h') { $i.='(|_safe|_safe_extend)'; }
    elsif ($j eq 'vil/vil_new.h') { $i.='(_blocked|_cached|_pyramid)?_image_(resource(|_of_view|_interleaved)|facade|(list_)?from_base|view_i_j_plane|view_plane_i_j)'; }
    elsif ($j =~ m'vil1?/vil1?_pixel\.h$') { $i.='_format(|_t|_component_format)'; }
    elsif ($j =~ m'vil1?/vil1?_pixel_format\.h$') { $i.='(|_of|_component_format|_sizeof_components|_num_components)|\w+(\.|-\>)pixel_format\(|VIL_PIXEL_FORMAT_\w+'; }
    elsif ($j =~ m'vil1?/vil1?_property\.h$') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'vil/vil_print.h') { $i.='(|_value|_all)'; }
    elsif ($j eq 'vil/vil_rotate.h') { $i.='(_image)'; }
    elsif ($j eq 'vil/vil_save.h') { $i.='(|_image_resource|_guess_file_format)'; }
    elsif ($j eq 'vil1/vil1_smooth.h') { $i.='_(gaussian|byte_separable_symmetric)'; }
    elsif ($j =~ m'vil/vil_stream_(read|write)\.h$') { $i.='_(big|little)_endian_\w+'; }
    elsif ($j eq 'vil/vil_transform.h') { $i.='(|2)'; }
    elsif ($j eq 'vil/vil_view_as.h') { $i.='(|_planes|_rgb)|vil_view_(real|imag)_part'; }
    elsif ($j eq 'vil1/vil1_vil.h') { $i='vil1_(to_|from_|)vil_image_(view|resource)'; }
    elsif ($j eq 'vil1/vil1_warp.h') { $i.='(|_mapping|_interpolation_type|_output_driven)'; }
    # VIL/FILE_FORMATS
    elsif ($j eq 'vil/file_formats/vil_dicom_header.h') { $i.='(_type|_endian|_image_type|_info|_format)|VIL_DICOM_HEADER_\w+'; }
    elsif ($j =~ m'vil/file_formats/vil_nitf_') {} # keep $i
    elsif ($j =~ m'vil1?/(|file_formats/)vil1?_jpeglib\.h$') { $i='jpeg(|1|2)_[a-z_]+'; }
    elsif ($j eq 'vil/file_formats/vil_pyramid_image_list.h') { $i='vil_pyramid_image_list(|_format)'; }
    elsif ($j =~ m'vil/file_formats/(.*)_image\.h$') { $i=$1.'(_image|_file_format)'; }
    elsif ($j =~ m'vil1?/file_formats/(.*)\.h$') { $i=$1.'(|_image|_file_format)'; }
    # VIL/ALGO
    elsif ($j eq 'vil/algo/vil_cartesian_differential_invariants.h') { $i.='_3'; }
    elsif ($j eq 'vil/algo/vil_convolve_1d.h') { $i='vil_convolve_(1d|edge_1d|boundary_option)'; }
    elsif ($j eq 'vil/algo/vil_exact_distance_transform.h') { $i.='_([a-z_]+)'; }
    elsif ($j eq 'vil/algo/vil_find_peaks.h') { $i='vil_(find_peaks_3x3|is_peak_3x3)'; }
    elsif ($j eq 'vil/algo/vil_find_4con_boundary.h') { $i.='(_below|_above)_threshold'; }
    elsif ($j eq 'vil/algo/vil_flood_fill.h') { $i.='(_row|4|8)'; }
    elsif ($j eq 'vil/algo/vil_histogram.h') { $i.='(|_byte)|VIL_HISTOGRAM_INSTANTIATE'; }
    elsif ($j eq 'vil/algo/vil_exp_filter_1d.h') { $i='vil_exp_filter_(1d|i|j)'; }
    elsif ($j eq 'vil/algo/vil_exp_grad_filter_1d.h') { $i='vil_exp_grad_filter_(1d|i|j)'; }
    elsif ($j eq 'vil/algo/vil_fft.h') { $i.='(|_2d_fwd|_2d_bwd)'; }
    elsif ($j eq 'vil/algo/vil_find_plateaus.h') { $i.='_3x3|vil_is_plateau_3x3'; }
    elsif ($j eq 'vil/algo/vil_gauss_filter.h') { $i.='_(1d|2d|5tap(|_params)|gen_ntap)'; }
    elsif ($j eq 'vil/algo/vil_gauss_reduce.h') { $i.='(|_params|_general|(|_121|_2_3)(|_1plane))'; }
    elsif ($j eq 'vil/algo/vil_orientations.h') { $i.='(|_at_edges|_from_sobel)'; }
    elsif ($j eq 'vil/algo/vil_quad_distance_function.h') { $i.='(|_1D)|vil_update_parabola_set|vil_(sample_|)quad_envelope(|_with_pos)'; }
    elsif ($j eq 'vil/algo/vil_region_finder.h') { $i.='(|_connectivity)'; }
    elsif ($j eq 'vil/algo/vil_suppress_non_max.h') { $i='vil_(is_peak|suppress_non_max)_3x3'; }
    elsif ($j eq 'vil/algo/vil_suppress_non_plateau.h') { $i.='_3x3'; }
    elsif ($j eq 'vil/algo/vil_threshold.h') { $i.='_(below|above|inside|outside)'; }
    # VIL/IO
    elsif ($j eq 'vil/io/vil_io_memory_chunk.h') { $i.='|vsl_b_write|VIL_IO_SMART_PTR_INSTANTIATE.vil_memory_chunk'; }
    elsif ($j eq 'vil1/io/vil1_io_rgb.h') { $i.='|vsl_b_write|VIL1_IO_MEMORY_IMAGE_OF_INSTANTIATE.vil1_rgb'; }
    # VNL
    elsif ($j eq 'vnl/algo/vnl_algo_fwd.h') { $i='vnl_(svd|qr|matrix_inverse|symmetric_eigensystem|cholesky|complex_eigensystem|conjugate_gradient|cpoly_roots|lbfgs|levenberg_marquardt)'; }
    elsif ($j eq 'vnl/algo/vnl_chi_squared.h') { $i.='_[a-z]+'; }
    elsif ($j eq 'vnl/algo/vnl_fft.h') { $i.='(|_(|set)gpfa)'; }
    elsif ($j eq 'vnl/algo/vnl_netlib.h') { $i='vnl_netlib_(svd|qrdc|qrsl)_(proto|params)|v3p_netlib_(cg|simpru|zgeev|rpoly|dchscdf|dpofa|dposl|dpoco|dpodi|dgpfa|rsg|dgges|lbfgs|lmdif|lsqr|qrdc|qrsl|rs|rg|dnlaso|svdc|setulb)_'; }
    elsif ($j eq 'vnl/algo/vnl_symmetric_eigensystem.h') { $i.='(|_compute)'; }
    elsif ($j eq 'vnl/algo/vnl_discrete_diff.h') { $i.='(_sym|_fwd|_test_lsf)'; }
    elsif ($j eq 'vnl/algo/vnl_solve_qp.h') { $i.='_(zero_sum|no_neg_sum_one|with_(equality|non_neg)_constraints)'; }
    elsif ($j eq 'vnl/algo/vnl_svd.h') { $i.='(|_inverse)'; }
    elsif ($j eq 'vnl/vnl_bignum_traits.h') { $i='vnl_bignum'; }
    elsif ($j eq 'vnl/vnl_rational_traits.h') { $i='vnl_rational'; }
    elsif ($j eq 'vnl/vnl_complex.h') { $i='vcl_complex'; }
    elsif ($j eq 'vnl/vnl_cross.h') { $i='vnl_cross_[23]d'; }
    elsif ($j eq 'vnl/vnl_erf.h') { $i='vnl_erfc?'; }
    elsif ($j eq 'vnl/vnl_error.h') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'vnl/vnl_finite.h') { $i.='_int(|_poly)'; }
    elsif ($j eq 'vnl/vnl_inverse.h') { $i.='(|_transpose)'; }
    elsif ($j eq 'vnl/vnl_gamma.h') { $i='vnl_((|log_)gamma(|_[pq])|cum_prob_chi2)'; }
    elsif ($j eq 'vnl/vnl_math.h') { $i='vnl_(math(|_[a-z_]+)|huge_val)'; }
    elsif ($j eq 'vnl/vnl_matlab_print.h') { $i.='|MATLABPRINT'; }
    elsif ($j eq 'vnl/vnl_matlab_print2.h') { $i='vnl_matlab_print|VNL_MATLAB_PRINT2_INSTANTIATE'; }
    elsif ($j eq 'vnl/vnl_matlab_read.h') { $i.='(|hdr)'; }
    elsif ($j eq 'vnl/vnl_sparse_matrix.h') { $i.='(|_pair)'; }
    elsif ($j eq 'vnl/vnl_T_n.h') { $i.='_[a-z_]*'; }
    elsif ($j eq 'vnl/vnl_sample.h') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'vnl/vnl_tag.h') { $i.='_[a-z]+'; }
    elsif ($j eq 'vnl/vnl_matrix.h') { $i.='|frobenius_norm'; }
    elsif ($j eq 'vnl/vnl_vector.h') { $i.='|get_row'; }
    elsif ($j eq 'vnl/vnl_matrix_fixed_ref.h') { $i.='(|_const)'; }
    elsif ($j eq 'vnl/vnl_vector_fixed_ref.h') { $i.='(|_const)'; }
    elsif ($j eq 'vnl/vnl_config.h') { $i='VNL_CONFIG_(CHECK_BOUNDS|LEGACY_METHODS|THREAD_SAFE|ENABLE_SSE2)'; }
    # VGUI
    elsif ($j eq 'vgui/vgui_adaptor.h') { $i='(vgui|get)_(adaptor|event)'; }
    elsif ($j eq 'vgui/vgui_color_text.h') { $i='text_to_color|(red|green|blue)_value'; }
    elsif ($j eq 'vgui/vgui_command.h') { $i.='(|_[a-z_]+)|VGUI_COMMAND_SIMPLE_INSTANTIATE'; }
    elsif ($j eq 'vgui/vgui_find.h') { $i.='_[a-z_]+name'; }
    elsif ($j eq 'vgui/vgui_grid_tableau.h') { $i.='(|_data)'; }
    elsif ($j eq 'vgui/vgui_macro.h') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'vgui/vgui_menu.h') { $i.='(|_item)'; }
    elsif ($j eq 'vgui/vgui_pixel.h') { $i.='_([rgba1568]*|rgbfloat)'; }
    elsif ($j eq 'vgui/vgui_rubberband_tableau.h') { $i='vgui_rubberband(_tableau(|_new|_sptr)|(|_easy2D)_client)'; }
    elsif ($j eq 'vgui/vgui_shell_tableau.h') { $i.='(|_bindings)'; }
    elsif ($j eq 'vgui/vgui_soview2D.h') { $i.='(|_point|_circle|_lineseg|_linestrip|_polygon|_group|_image)'; }
    elsif ($j eq 'vgui/vgui_statusbar.h') { $i.='|get_statusbar\(\)->'; }
    elsif ($j eq 'vgui/vgui_style.h') { $i.='(|_equal)'; }
    elsif ($j eq 'vgui/vgui_tag.h') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'vgui/vgui_tableau_sptr.h') { $i.='(|_t)|get_tableau'; }
    elsif ($j eq 'vgui/internals/vgui_rasterpos.h') { $i.='.*'; }
    elsif ($j eq 'vgui/internals/vgui_simple_field.h') { $i='vgui_(simple|bool|int|long|float|double)_field'; }
    # VIDL
    elsif ($j eq 'vidl_vil1/vidl_vil1_codec.h') { $i.='|coder_->'; }
    elsif ($j eq 'vidl_vil1/vidl_vil1_frame.h') { $i.='|get_view'; }
    # VIPL
    elsif ($j eq 'vipl/filter/vipl_filter_abs.h') { $i.='|FILTER_IMPTR_(INC|DEC)_REFCOUNT'; }
    elsif ($j =~ m'vipl/vipl_with_vbl_array_2d/accessors/vipl_accessors_(vbl_array_2d)\.h') { $i=$1; }
    elsif ($j eq 'vepl/vepl_monadic.h') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'vepl/vepl_dyadic.h') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'vepl2/vepl2_monadic.h') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'vepl2/vepl2_dyadic.h') { $i.='(|_[a-z_]+)'; }
    # VDGL
    elsif ($j eq 'vdgl/vdgl_digital_curve.h') { $i.='|cast_to_vdgl_digital_curve\(\)|get_interpolator\(\)'; }
    elsif ($j eq 'vdgl/vdgl_edgel_chain.h') { $i.='|get_edgel_chain\(\)|vbl_smart_ptr.txx'; }
    elsif ($j eq 'vdgl/vdgl_interpolator.h') { $i.='|get_interpolator\(\)|vbl_smart_ptr.txx'; }
    elsif ($j eq 'vdgl/vdgl_interpolator_sptr.h') { $i='vdgl_interpolator(|_sptr)'; }
    # VSOL
    elsif ($j eq 'vsol/vsol_point_2d.h') { $i.='|cast_to_point\(\)|p[01]\(\)'; }
    elsif ($j eq 'vsol/vsol_point_3d.h') { $i.='|cast_to_point\(\)'; }
    elsif ($j eq 'vsol/vsol_spatial_object_2d.h') { $i.='|cast_to_spatial_object\(\)'; }
    elsif ($j eq 'vsol/vsol_spatial_object_3d.h') { $i.='|cast_to_spatial_object\(\)'; }
    elsif ($j eq 'vsol/vsol_curve_2d.h') { $i.='|cast_to_curve\(\)'; }
    elsif ($j eq 'vsol/vsol_curve_3d.h') { $i.='|cast_to_curve\(\)'; }
    elsif ($j eq 'vsol/vsol_digital_curve_2d.h') { $i.='|cast_to_digital_curve\(\)'; }
    elsif ($j eq 'vsol/vsol_digital_curve_3d.h') { $i.='|cast_to_digital_curve\(\)'; }
    # VTOL
    elsif ($j eq 'vtol/vtol_vertex_2d.h') { $i.='|cast_to_vertex_2d\(\)'; }
    elsif ($j eq 'vtol/vtol_edge_2d.h') { $i.='|cast_to_edge_2d\(\)'; }
    elsif ($j eq 'vtol/vtol_face_2d.h') { $i.='|cast_to_face_2d\(\)'; }
    elsif ($j eq 'vtol/vtol_intensity_face.h') { $i.='(|_sptr)'; }
    elsif ($j eq 'vtol/vtol_zero_chain.h') { $i.='|outside_boundary_zero_chains\(\)'; }
    elsif ($j eq 'vtol/vtol_topology_object.h') { $i.='|cast_to_topology_object\(\)|(topology|vertex|(|zero_|one_|two_)chain|edge|face|block)_list'; }
    elsif ($j eq 'vtol/vtol_dtd.h') { $i.='([0123])'; }
    elsif ($j eq 'vtol/vtol_list_functions.h') { $i='tagged_union|(SEL|COPY)_(SUP|INF)'; }
    elsif ($j eq 'vtol/vtol_macros.h') { $i='(SEL|COPY)_(SUP|INF)'; }
    # BDGL
    elsif ($j =~ m'bdgl/bdgl_curve_(tracker|matcher|matching|tracking|clustering)\.h$') { $i.='(|_params)'; }
    elsif ($j eq 'bdgl/bdgl_tracker_curve.h') { $i.='|match_data|[sg]et_best_match_(prev|next)\(\)'; }
    elsif ($j eq 'bdgl/utils.h') { $i='fixAngleMPiPi|fixAngleZTPi|angleDiff'; }
    elsif ($j eq 'bvgl/bvgl_change_obj.h') { $i.='|vbl_smart_ptr\.txx'; }
    # GEVD
    elsif ($j eq 'gevd/gevd_pixel.h') { $i='(byte|char|short|float|ptr)Pixel'; }
    # MBL
    elsif ($j eq 'mbl/mbl_cloneable_ptr.h') { $i.='|mbl_cloneable_nzptr|MBL_CLONEABLE_PTR_INSTANTIATE'; }
    elsif ($j eq 'mbl/mbl_cloneables_factory.h') { $i.='|MBL_CLONEABLES_FACTORY_INSTANTIATE'; }
    elsif ($j eq 'mbl/mbl_combination.h') { $i.='(_begin|_next)'; }
    elsif ($j eq 'mbl/mbl_config.h') { $i='MBL_CONFIG_(BUILD_NAME|TEST_SAVE_MEASUREMENT_ROOT)'; }
    elsif ($j eq 'mbl/mbl_exception.h') { $i.='_(error|warning|abort|(read_props_|parse_block_|)parse_error|no_name_in_factory|missing_property|unused_props|throw_os_error)'; }
    elsif ($j eq 'mbl/mbl_gamma.h') { $i='mbl_(gamma_[pq]|erf)'; }
    elsif ($j eq 'mbl/mbl_log.h') { $i='mbl_log(ger(|_root)|_\w+)'; }
    elsif ($j eq 'mbl/mbl_matrix_products.h') { $i='mbl_matrix_product(|_a_bt|_at_b|_adb)'; }
    elsif ($j eq 'mbl/mbl_matxvec.h') { $i.='_(prod|add)_[a-z_]+'; }
    elsif ($j eq 'mbl/mbl_read_props.h') { $i.='(|_type|_ws|_print|_merge|_look_for_unused_props)'; }
    elsif ($j eq 'mbl/mbl_read_multi_props.h') { $i.='(|_type|_ws|_print|_merge|_look_for_unused_props)'; }
    elsif ($j eq 'mbl/mbl_test.h') { $i.='_(summaries_are_equal|save_measurement)'; }
    elsif ($j eq 'mbl/mbl_stl.h') { $i.='_(increments(|_n)|sequence(|_n)|clean|copy_if|select(1st|2nd)|add2nd|index_functor|output_t1)'; }
    elsif ($j eq 'mbl/mbl_stl_pred.h') { $i.='_(is_a|is_near|str_contains|iter_deref_order|pair_(|iter_)(|key_|value_)order|(|binary_)index_adapter(|_n))'; }
    elsif ($j eq 'vnl/io/vnl_io_vector.h') { $i.='|MBL_FILE_DATA_[A-Z]+_INSTANTIATE.vnl_vector'; }
    # MIL
    elsif ($j eq 'mil/mil_bilin_interp_2d.h') { $i='mil(|_safe(|_extend))_bilin_interp_2d'; }
    elsif ($j eq 'mil/mil_convert_vil.h') { $i.='_[gc][mv]2[gc][mv]'; }
    # VIMT
    elsif ($j eq 'vimt/vimt_bilin_interp.h') { $i.='(|_safe)'; }
    elsif ($j eq 'vimt/vimt_convert.h') { $i.='(_cast|_round|_stretch_range)'; }
    elsif ($j eq 'vimt/algo/vimt_find_peaks.h') { $i='vimt_(is_peak(|_3x3)|find_(image|world)_peaks(|_3x3)|find_max)'; }
    elsif ($j eq 'vimt/algo/vimt_find_troughs.h') { $i='vimt_(is_trough_3x3|find_(image|world)_troughs_3x3)'; }
    elsif ($j eq 'vimt/vimt_resample_bilin.h') { $i.='(|_smoothing|_edge_extend)'; }
    elsif ($j eq 'vimt/vimt_vil_v2i.h') { $i.='(_image|_format)'; }
    elsif ($j eq 'vimt/vimt_load.h') { $i.='(|_transform)'; }
    elsif ($j eq 'vimt3d/vimt3d_image_3d.h') { $i.='|vimt3d_centre_image_at_origin|world_bounding_box'; }
    elsif ($j eq 'vimt3d/vimt3d_load.h') { $i.='(|_transform)'; }
    elsif ($j eq 'vimt3d/vimt3d_resample_trilinear.h') { $i.='(|_scale_2)'; }
    elsif ($j eq 'vimt3d/vimt3d_trilin_interp.h') { $i.='_(safe|raw)'; }
    elsif ($j eq 'vimt3d/vimt3d_vil3d_v3i.h') { $i.='(_image|_format)'; }
    # VPDFL
    elsif ($j eq 'vpdfl/vpdfl_prob_chi2.h') { $i='vpdfl_(cum_prob_chi2|chi2_for_cum_prob)'; }
    # PDF1D
    elsif ($j eq 'pdf1d/pdf1d_prob_chi2.h') { $i='pdf1d_(cum_prob_chi2|chi2_for_cum_prob)'; }
    # RREL
    elsif ($j eq 'rrel/rrel_misc.h') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'rrel/rrel_muse_table.h') { $i.='(|_entry)|rrel_muse_key_type'; }
    elsif ($j eq 'rrel/rrel_util.h') { $i.='(|_[a-z_]+)'; }
    # RSDL
    elsif ($j eq 'rsdl/rsdl_dist.h') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'rsdl/rsdl_kd_tree.h') { $i='rsdl_kd_(node|heap_entry|tree)'; }
    # RGRL
    elsif ($j eq 'rgrl/rgrl_converge_status.h') { $i.='(|_sptr)|final_status\(\)'; }
    elsif ($j eq 'rgrl/rgrl_estimator.h') { $i='rgrl(|_(non|)linear)_estimator|rgrl_est_compute_weighted_centres|rgrl_est_matches_residual_number'; }
    elsif ($j eq 'rgrl/rgrl_feature.h') { $i.='(|_caster|_sptr)'; }
    elsif ($j eq 'rgrl/rgrl_feature_set.h') { $i.='(|_label)'; }
    elsif ($j eq 'rgrl/rgrl_fwd.h') { $i='rgrl_\w+'; }
    elsif ($j eq 'rgrl/rgrl_macros.h') { $i='(Debug|Warning)(|Func)Macro(|_abv)|rgrl_type_macro|IsTypeMacro'; }
    elsif ($j eq 'rgrl/rgrl_mask.h') { $i.='(|_[a-z_]+)'; }
    elsif ($j eq 'rgrl/rgrl_match_set.h') { $i.='(|_[a-z_]+_iterator)'; }
    elsif ($j eq 'rgrl/rgrl_scale_estimator.h') { $i.='(|_(un|)wgted)'; }
    elsif ($j eq 'rgrl/rgrl_transformation.h') { $i.='(|_sptr)'; }
    elsif ($j eq 'rgrl/rgrl_util.h') { $i.='(|_[a-z_]+)'; }
    # BGUI
    elsif ($j eq 'bgui/bgui_vsol_soview2D_point.h') { $i.='(|_[a-z_]+)'; }
    # SPECIAL CASES
    if ($j =~ m'(vsl/vsl_[a-z]+_io|v[bginu]l1?/io/v[bginu]l1?_io_[a-z123_]+)\.h') { $i.='|vsl_(b_(read|write)|print_summary)'; }
    next if ($j eq 'vsol/vsol_curve.h' && $f =~ m'Templates/vbl_smart_ptr\+vtol_edge-\.cxx$');
    next if ($j eq 'vsol/vsol_point.h' && $f =~ m'Templates/vbl_smart_ptr\+vtol_edge-\.cxx$');
    next if ($j eq 'vsol/vsol_region.h' && $f =~ m'Templates/vbl_smart_ptr\+vtol_face-\.cxx$');
    next if ($j eq 'vsol/vsol_curve_2d.h' && $f =~ m'Templates/vbl_smart_ptr\+vtol_edge_2d-\.cxx$');
    next if ($j eq 'vsol/vsol_point_2d.h' && $f =~ m'Templates/vbl_smart_ptr\+vtol_edge_2d-\.cxx$');
    next if ($j eq 'vsol/vsol_region_2d.h' && $f =~ m'Templates/vbl_smart_ptr\+vtol_face_2d-\.cxx$');
    # FINALLY PRINT MESSAGE, IF APPLICABLE
#   warn "\$j=$j\t\$i=$i\t\$ii=$ii\n";
    &msg(1, "should not have #include <$j>", 1)
      unless ($fl =~ m!$j\>[^\003]*\b$i\b! ||
              $f =~ m!/$ii\.! ||
              $f eq 'vxl_copyright.h' ||
              $f eq 'vxl_version.h' ||
              $f.$j =~ m!vxl_echo\.cxx(vxl_version|vxl_copyright)\.h! ||
              $f =~ m!\btests/test_include\.cxx$!);
  }
  &msg(1, "should have \#include <vcl_cassert.h>")
    if (! $found_cassert && $file =~ m!\n\s*assert\s*\(!);
  &msg(1, "should have \#include <vcl_iostream.h> or <vcl_iosfwd.h>")
    if (! $found_iostream && $f =~ m!\.h$! && $f !~ m!vcl_! && $f !~ m!core/vgui/vgui_macro.h$! && $f !~ m!core/vil/file_formats/vil_nitf2.h$! &&
        $f !~ m!core/vul/vul_ios_state.h$! && $fl =~ m!\bvcl_(cin|cout|cerr|clog|(i|o)stream|endl|ends|flush|stream(pos|buf|size))\b!);

  &msg(1, "suspicious $1")
    if ($f !~ m!\bvcl/\S*vcl_\S+\.(h|txx)$! &&
        $file =~ m!^\s*(\#\s*include\s*\"([^\"]*)/[^\"]*\")! &&
        $2 ne "internals" && $2 ne ".." && $2 ne "../accessors" && $2 ne "os_unix" && $2 ne "vc70" &&
        $1 ne "# include  \"emulation/vcl_limits.cxx\"");
  if ($cpp_file && $f !~ m!\bvcl/\S*vcl_\S+\.(h|txx)$! &&
      $file =~ m!\#\s*include\s*\<(assert|ctype|errno|float|iso646|limits|locale|math|setjmp|signal|stdarg|stddef|stdio|stdlib|string|time|wchar|wctype)\.h\>!) {
    $t=$1;
    &msg(1, "replace #include <$t.h> by #include <vcl_c$t.h>")
      unless (($f =~ m!\bcore/vnl/vnl_math\.cxx$! && $t eq "math") ||
              ($f =~ m!\bvcl/tests/test_driver\.cxx$! && $t eq "math") ||
              ($f =~ m!\bcore/testlib/testlib_main\.cxx$! && $t eq "math") ||
              ($f =~ m!\bcore/vnl/vnl_sample\.cxx$! && $t eq "stdlib") ||
              ($f =~ m!\bcore/vnl/vnl_math\.cxx$! && $t eq "float") ||
              ($f =~ m!\bcore/vpl/os_unix/vpl\.cxx$! && $t eq "stdlib") ||
              ($f =~ m!\bcmake/config/vxl_platform_tests\.cxx$!) ||
              ($f =~ m!\bvidl/vidl_v4l_istream\.h$! && $t eq "errno") ||
              ($f =~ m!\bcore/vul/vul_temp_filename\.cxx$! && $t eq "stdio") ||
              ($f =~ m!\bcore/vul/vul_redirector\.cxx$! && $t eq "stddef"));
  }
  &msg(1, "local $2 should come before global $1")
    if ($file =~ m!(\#\s*include\s*\<[^\>]*\>).*(\#\s*include\s*\"[^\"]*\")!);

# 8. //: inside a comment block, or \file not after //:
  &msg(1, "\\file is not preceded by //:")
    if ($file =~ m!\n\s*(//[^:]|[^\s/]).*\n *// *\\file\b!);
  $file =~ s!//\s*[-=_]{40,}\n!//\n!g;
  &msg(1, "contains //: inside a comment block")
    if ($file =~ m!\n\s*//[ :].*\n *//:!);

# 9. Comments: long /* ... */ and old-style // -- docs; RCS indications; mistypings
  $file =~ s! +\n!\n!g;
  $file =~ s!/\*!\001!g; $file =~ s!/\001!//\*!g;
  $file =~ s!\*/!\002!g;
  $file =~ s!(\"[^\001\n\"]{0,15})\001([^\001\n\"]{0,15}\")!$1/\*$2!g;
  $file =~ s!(\"[^\002\n\"]{0,15})\002([^\002\n\"]{0,15}\")!$1\*/$2!g;
  $file =~ s!\001\*!/\*\*!g; # Doxygen style comments
# if ($file =~ m!//\s*[a-zA-Z_0_9]*\s*--\s+(\S*)! && $1 ne "JLM")
# {
#   &msg(1, "contains old style // -- docs")
#     unless ($f =~ m!vcl/vcl_complex_fwd\.h$! || $f =~ m!win32-vc60/vcl_complex\.h$! || $f =~ m!vgui/vgui_glut\.h$!);
# }
  &msg(1, "contains long /*...*/ comments")
    if ($cpp_file && $file =~ s!\001[^\001\002]{121,}\002!!g &&
        $f !~ m!\bvidl_vil1/vidl_vil1_mpegcodec\.cxx$! &&
        $f !~ m!\bmsm/tools/msm_draw_shape_modes.cxx$! && $f !~ m!\bmsm/tools/msm_build_shape_model.cxx$! &&
        $f !~ m!\bvul/vul_url\.cxx$! && $f !~ m!\bvcl/gtkgl/! && $f !~ m!\bcontrib/rpl/rtvl/! &&
        $f !~ m!\bvul/tests/test_file_iterator\.cxx$! && $f !~ m!\bmsm/tools/msm_(plot_aligned_shapes|get_shape_params).cxx$!);
  if ($file =~ m!\n\s*//\s*vcl_c(out|err)\s*\<\<.*(\n\s*//.*){5,}! && $file !~ m!//\s*\\code!)
  {
    $tmp=$file; $tmp =~ s!\n\s*//\s*vcl_c(out|err)\s*\<\<.*(\n\s*//.*){5,}[^\000]*!!; $tmp =~ s![^\n]*!!g; $tmp=length($tmp)+2;
    &msg($tmp, "consider commenting out code sections with #if 0 or #ifdef DEBUG");
  }
  # RCS indications
  &msg(1, "contains RCS indication $1")
    if ($file =~ m!(\$RCSfile|\$(Author|Revision|Date): .* \$)!);
  #typos
  &msg(1, "probably a typo: $1")
    if ($printed && $file =~ m!\b(
      aapl[iy]\w*
    | accom[^mp]\w*
    | abcis\w*
    | abounds
    | abstrace
    | accp\w+
    | accc\w+
    | accell\w+
    | accessabl\w+
    | accross
    | accura[^ct]\w*
    | acuta\w*
    | acylc\w*
    | adaptati[^no]\S*
    | addion\w*
    | adress\w*
    | adust\w*
    | \w*(sss|ettt)\w*
    | agress\w*
    | alement
    | aligm\w+
    | alife
    | alll\w*
    | allocta\w*
    | alow\w*
    | alredy
    | alterd
    | alternativ[^e]\w*
    | ambiguo[^u]\w*
    | anay\w*
    | angluar
    | anj\b
    | anonyn\w+
    | ansiot\w+
    | anwer\w*
    | appart\w*
    | appearea\w+
    | appere?a\w*
    | aapply
    | appling
    | appropriatly
    | appropi\w*
    | approria\w*
    | appy\w*
    | appi\w+
    | arang\S+
    | arbitar\S+
    | aready
    | argree
    | arguemen\S*
    | argume[^n]\S*
    | arpund
    | artifact\w*
    | artitra\w*
    | assemb[^l]\S*
    | assignement
    | authentification
    | assignmen[^t]\w*
    | averat\w*
    | \w+mentt\b
    | attib\w+
    | autor\b
    | auxil[^i]\S*
    | auxiliar\b
    | avai\B[^l]\w+
    | availabli\w+
    | aver\B[^a]\w+
    | avialab\w+
    | aving
    | ayn\S+
    | axamin\w*
    | azimutha[^l]
    | backword\w*
    | bandwith
    | becausee
    | becuase
    | begg?ining
    | beahv\w*
    | bellow
    | bewt?een
    | blcok\w*
    | bloack\w*
    | blted
    | boarder\w*
    | bondar\S*
    | boolian\w*
    | bootsr\w*
    | borgefor\b
    | botton
    | bounary
    | boundarys
    | bounday\w*
    | bount\w*
    | brackett\w+
    | brighness
    | Bucther
    | buiding
    | bufer
    | calclua\w+
    | calculal\w+
    | callled
    | cal.culat\w+
    | caninical
    | ca.noni\w+
    | centern
    | centriod\S*
    | (un)?cert(i|ai)ni\S*
    | chac\S*
    | chanag\S*
    | changeb\S*
    | characterit\S*
    | chilr\S*
    | chlid\S*
    | chilr\S*
    | choosen\w*
    | cic[^ae]\S*
    | cirl\w+
    | cir[^c]\S\w+
    | \w+clas\b
    | classifer
    | clok\w*
    | closet
    | cluser
    | coeffic[^i]\S*
    | coefi\w+
    | cofigure
    | collectsion
    | collison\w*
    | collinar
    | coli\w{4,}
    | colum[^n]
    | columnn[^u]
    | coma\S*
    | comil[ie]\S*
    | comming
    | comparis[^o]\S*
    | compatibil[^i]\S*
    | compatiblit\w*
    | compent
    | compilant
    | componant
    | compone[^n]\w*
    | compuat\w*
    | compure
    | comute\w*
    | condt\S+
    | congug\S*
    | conju[^gnr]\S*
    | conrete
    | consecua\w+
    | concensus\w*
    | consisten\b
    | consit\S*
    | (con|de)structer\w*
    | (con|de)struct\B[^_oeis]\S*
    | (con|de)strut\S*
    | (con|de)stuct\S*
    | (con|de)truct\S*
    | deconstru\w*
    | constrainted
    | containg
    | containins
    | containt\w*
    | continou\S*
    | contrain\S+
    | contor
    | continguous
    | constrainted
    | \w*continut\w*
    | contol
    | controled
    | convenia\w*
    | converst\w*
    | coordi[^n]\S*
    | co-oef\w*
    | cooresp\w*
    | coppie\w*
    | coput\w+
    | core[rs]\S+
    | correll\w*
    | correlta\S+
    | corr[a-dfghj-np-tv-z]\w{3,}\b
    | correpond\w*
    | correspo[^n]\S+
    | corrosp\S+
    | creats
    | croped
    | currenly
    | currop\w+
    | dafault
    | dammage
    | decend\S*
    | decribe\w*
    | (de)?compos[^aei]\S*
    | defau[^l]\S*
    | defence\w*
    | defintion\w*
    | deger\w+
    | degner\w+
    | delarat\w+
    | delimet\w+
    | dence
    | deneger\S*
    | \w*depen[^d]\S*
    | \w*dependen[^ct]\S*
    | dderiva\w*
    | dervie\w*
    | deriviat\w*
    | descreas\w*
    | descret\w*
    | desct\w*
    | desinat\w*
    | despatch
    | des[^t]?ruc\w*
    | distruc\w*
    | detem\w+
    | deterim\w+
    | deterrm\w*
    | developem\w+
    | devid\w+
    | differenta\w+
    | differn\w+
    | difu\w+
    | dignos\w*
    | digi?tial
    | diif\w+
    | dimens\B[^i]\w+
    | dimensi[^o]\S*
    | dimensionn\S*
    | \w*drect\S*
    | direciton
    | directely
    | discri[bp]\w+
    | disting[ui]sh
    | distribt\w*
    | documentat[^i]\w*
    | documenti[^n]\w*
    | documen[^t-]\S*
    | doen
    | drivat\w*
    | dunp\w*
    | eariler
    | effecien\w*
    | efficiv\S*
    | effic[^ai]\S*
    | eigenval[a-rtv-z]\S*
    | elig\B[^i]\w+
    | elemin\S+
    | ellimi\S+
    | elm[ei]\S+
    | emelem\w+
    | emtpy
    | encasul\S*
    | encapsu[^l]\S*
    | encounterd
    | enquiries
    | entropys
    | epipl\S+
    | epsi\B[^l]\w+
    | equa\B[^tl]\w*
    | equivalan\w*
    | eq[a-tv-z]\w{5,}
    | esti[^m]\S*
    | estim\B[^a]\S*
    | Eucid\w*
    | Eucl[^i_]\S*
    | Euclid[ia]\S*
    | evalu\B[^a]\w+
    | examp\B[^l]\w*
    | excee[^d]\w*
    | exect\w*
    | exisi\w+
    | existency\w*
    | expalin
    | experime[^n]\w*
    | expici\w+
    | explicite\w*
    | expres\B[^s]\S*
    | expri\S*
    | extrac[^t]\w*
    | exr\w{3,}
    | featu[^r]\w*
    | finsh\w*
    | fisrt
    | filname
    | flaot\S*
    | follow\B[^_eisu]\w*
    | followi[^n]\w*
    | fomat
    | forbit\w*
    | forgroun\w*
    | formating
    | fractino
    | frequence
    | from[en]\b
    | fucnti\w*
    | fuincti\w*
    | funcio\w*
    | functo[^r]
    | funct[^io]\S*
    | funtion\w*
    | [a-z]+full\b
    | \w+eratd\b
    | \w+ateing
    | gaussai\w*
    | gauu\w*
    | gecentr\w*
    | geodedic\w*
    | geograf\w*
    | gloa\w+
    | gluing
    | goins
    | graid\S*
    | grapi\S*
    | growni\S*
    | guass\S*
    | gua?rran\S*
    | gauran\S*
    | hasnt
    | heigth
    | heir\S+
    | hierarc[^h]\S*
    | hiera[^r]\S*
    | hiear\S*
    | heigth
    | hight
    | highligh[^t]\S*
    | histogr[^a]\S*
    | hostogr\S*
    | homgra\S*
    | homograp[^h]\S*
    | homogr[^a]\S*
    | horizan\S*
    | (non|un)?homege\S*
    | (non|un)?homog[a-df-qs-z]\S*
    | (non|un)?homogeni[^sz]\S*
    | (non|un)?homogen[^ei]\S*
    | identife\S*
    | identia\S*
    | idex\w*
    | \S+ifed\b
    | immita\S*
    | impemen\w*
    | implemen[^t]\S*
    | implementat[^i]\S*
    | implen\S*
    | implme\S*
    | imput\S*
    | inciden\b
    | incredibably
    | inculd\S*
    | indentic\S*
    | independant
    | indeces
    | indexs
    | indicies
    | indivi[^d]\S*
    | individ[^u]\S*
    | \w+iua\S*
    | infered\w*
    | infinitismal\w*
    | inheranc\S*
    | inhert\S*
    | inifo\w*
    | (un)?inita\w*
    | initi[^a]\w*
    | initialli\S+
    | \w+iztio\S*
    | iniv\S*
    | inkno\S*
    | innac\S*
    | \w+alll\S*
    | inplem\S*
    | insead
    | instanc[^e]\S*
    | instanta\S*
    | instantian\w*
    | intanc\w*
    | intanti\w*
    | integrant\w*
    | itege?ra\w*
    | integet
    | integrant
    | intell[^i]\w*
    | intensit[^iy]\S*
    | intera[tl]\S*
    | inte[^glmnrsx]\S*
    | interes[^t]\S*
    | interfacess\S*
    | interopo\S*
    | interprett\S*
    | intersted\w*
    | intersct\S*
    | intesec\w*
    | interse[^c]\S*
    | intesi\S*
    | intris\S*
    | intrinsi[^c]\S*
    | invalide\S*
    | inti[^m]\w*
    | intos
    | itegeral
    | iter\B[^_a\d]\S*
    | jocob\S*
    | judicous
    | junnc\S*
    | kernal
    | karnel
    | keybord
    | lable
    | lamba\b
    | latti\S*
    | learnt
    | lenght
    | lenth
    | likely\w\S*
    | lik[^aei]\S*
    | lookat
    | magin\S*
    | magnit[^u]\S*
    | Mahalobis
    | maint[^ae]\S*
    | mainta[^i]\S*
    | manane\S*
    | manipl\S*
    | mantai\S*
    | mapable
    | Marquard\b
    | matric\b
    | matricies
    | maxiu\S*
    | maxin[au]\w*
    | maximas\b
    | maxim[^aiu]\S*
    | maximu[^m]
    | maxmim\w*
    | measur[^ei]\S*
    | mechnai\w*
    | mediod\S*
    | memeb\S*
    | memoty\w*
    | meridan\w*
    | milti\S*
    | mili[^t]\S*
    | minmu\S*
    | mienim\S*
    | minimia\S*
    | minimu[^m]\S*
    | minimumm\S*
    | mi[mn]in[ai]\S*
    | minimas\b
    | minium
    | minumum
    | miscel[^l]\S*
    | \w+lanous\S*
    | missclas\w*
    | \w+tionss
    | mulit\S*
    | mullt\S*
    | multip[^alr]\S*
    | munu
    | natua\S*
    | necc\S*
    | neces\B[^s]\S*
    | necessarly
    | neigb\S*
    | neigh\B[^b_]\S*
    | neighbo\B[^ur]\S*
    | neihb\w+
    | neumer\S*
    | \w+ifiy\S*
    | \w*[^n]\Bnnn+\B[^n]
    | nois[^eiy]\S*
    | noncovex\w*
    | noral\S*
    | normalista\S*
    | numbel
    | \w+n;t
    | nubme\S*
    | numebe?r\S*
    | objects\'s
    | obje[^c]\S*
    | obser[^v]\S*
    | obtatain\w*
    | obtian\S*
    | occur[a-qt-z]\S*
    | ocuppa\w*
    | octo[^b]\s*
    | ommit\S*
    | onthe
    | oor
    | openned
    | openning
    | oper\B[^a]\S*
    | orgin\S*
    | orienta[^lt]\S*
    | orthog\B[^_ro]\S*
    | ortog\S*
    | osft\S*
    | ouput
    | ouside
    | outputing
    | paincip\S*
    | parabal\S*
    | paralle\b
    | parallelo\S*
    | parallal
    | paralle\b
    | parama?t\S*
    | parameteric
    | paramete[^r]\S*
    | parem\S*
    | parap[^h]\S*
    | parbol
    | partcular\w*
    | patten\b
    | pefor\S*
    | perf\B[^eiou]\S*
    | perim[a-df-z]\S*
    | perps\S*
    | perpendicl\S*
    | philosophia\S*
    | plataf\S*
    | planary
    | poin\b
    | poitner
    | polyon
    | Pontyon
    | poyl\w+
    | \w+ntin\b
    | pois[^os]\S*
    | possiblit\S*
    | posi[^tx]\S*
    | posti[^n]\S*
    | pote[^n]\S*
    | \w*requist\S*
    | preceeding\w*
    | predicit\S*
    | prefering\w*
    | preform\S*
    | prefered
    | preturb\S*
    | previos\S*
    | prevous\S*
    | pricipal\w*
    | \w+mobably\b
    | \w+itys\b
    | probabii\S*
    | probabiliy\w*
    | probabily\b
    | probabl[^ey]\S*
    | probabilt\w*
    | probabli\w*
    | probil\S*
    | probly
    | procce\S*
    | proces[^s]
    | progam\S*
    | programat\w*
    | properit\S*
    | propog\S*
    | protocal
    | psuedo\S*
    | purspos\S*
    | purpous\S*
    | qualtit\w*
    | quateri\S*
    | raturn\w*
    | reatur\S*
    | receip[^t]
    | reciv\S*
    | recomme[^n]\w*
    | recrus\S*
    | rectan[^g]\S*
    | recursivv\S*
    | (re)?determing
    | redunden\S*
    | refering
    | referan\S*
    | refern\S*
    | \w+straions?
    | regu[^l]\S*
    | relac\S*
    | relase\w*
    | releiv\S*
    | releven[tc]\S*
    | (re)?nomal\S*
    | rep[eo]n\w{4,}
    | repeatl\S*
    | represe[^n]\S*
    | reps\w{2,}
    | requr\S*
    | reslt\S*
    | resgard\S*
    | resore\S*
    | respose\w*
    | resturn\w*
    | retang\w+
    | rotaion\w*
    | rotot\S*
    | retr(ei|iv)\S*
    | salienct\S*
    | salieny
    | samp[a-kmnp-rt-z]\w*
    | \w+itons?\b
    | scond\S*
    | segeme\S*
    | selectd
    | selecton\w*
    | seperat\w*
    | servera\S*
    | serali[zs]a\S*
    | seting
    | severl\S*
    | sigl\S*
    | signif[^i]\S*
    | significan[^tc]\S*
    | simularly
    | simulat[^eio]\S*
    | simplie[rd]
    | singlt\S*
    | singlet[^oh]\S*
    | smalles\b
    | smoothes
    | somwhere
    | somethings
    | souc\S*
    | specifin\S*
    | sqa\S*
    | squen\S*
    | stablis\S*
    | staig\S*
    | stampes\S*
    | steram\S*
    | straigt\S*
    | stong\S*
    | storeag\S*
    | stru[ct]u\S*
    | structtu\S*
    | sturc\w*
    | subsit\S*
    | subra\S*
    | substra\S*
    | \w*subtitu\w*
    | successfuly
    | succes[^s]\S*
    | suffies
    | superseeded
    | supp\B[^elor]\S*
    | supper\w+
    | supres\S*
    | superce\w*
    | syme\S*
    | symmet[^r]\S*
    | symmt\w+
    | syste[^m]\S*
    | syte\S*
    | \w*tablea[^nu]\S*
    | tableu\S*
    | talbo\S*
    | talbeau\S*
    | tech[a-mo-z]\S*
    | teh
    | templatiz\w*
    | tesselat\S*
    | thand\b
    | thickenes\S*
    | thoru\S*
    | ths\s
    | thsi\b
    | threhol\S*
    | threshol[^d]
    | throun\S*
    | throught
    | treshold\S*
    | trh\S*
    | togg[^l]\S*
    | toler[^a]\S*
    | toration\S*
    | toupl\S*
    | traac\S*
    | tragen\S*
    | trainig\S*
    | tranform\w*
    | tran[a-prt-z]\S*
    | trasform\w*
    | transfor[^m]\w*
    | transor\S*
    | transf[a-df-hj-np-z]\S*
    | transfor[^m]\w*
    | trave[^lr]\S*
    | traver[^s]\S*
    | triangl[^e]\S*
    | unec\S+
    | (un)?certainit\w*
    | unhomogen\w*
    | unsymmetr\w+
    | updatet
    | (un)?useab\S*
    | useful[a-km-z]\S*
    | utilite\S*
    | \w+itit
    | \w+tatat
    | varient
    | vaule\S*
    | valu[^ae]\S*
    | vecor\S*
    | vetc?or\S*
    | vecotor\S*
    | verifys
    | verf\S*
    | verical\w*
    | verion\S*
    | verson\S*
    | vertics
    | verticies
    | vertexes
    | vetical
    | virutal
    | vishual
    | visibli\S*
    | vitural
    | vlo\S*
    | wast\b
    | whan
    | weigth\S*
    | wether
    | \S*wehre
    | wheather
    | whises
    | whou\S*
    | wich
    | wierd
    | wil\b
    | wiht
    | wtih
    | widht
    | withing
    | wrapi\S*
    | writted
    | writting
    | xist\w+
    | yei\S*
    | [a-z]*([a-z])\1\1[a-z]*\b
    )!ix
        && $1 !~ '^[A-Z]+$' && $1 !~ m/^(systep=|InitAll|iterT|neigh[IT]|glCall)/ && $1 ne 'pointin' && $1 ne 'isfull' && $1 ne 'Plataforma' && $1 ne 'valush' && $1 ne 'appicon' && $1 ne 'systep' && $1 ne 'IntInfo' && $1 ne 'InitInstance' && $1 ne 'posinf,' && $1 ne 'ssss' && $1 ne 'sss' && $1 ne 'ttt' && $1 ne 'sssHdddmmss' && $1 ne 'sampNumCoef' && $1 ne 'vlow' && $1 !~ m!ClassSel|classSo|\bcorrs_!);

# 10. spurious #pragma interface or #pragma implementation
  &msg(1, "contains $1 without #ifdef VCL_NEEDS_PRAGMA_INTERFACE")
    if ($file !~ m!\#ifdef VCL_NEEDS_PRAGMA_INTERFACE\n(\#pragma (interface|implementation)).*\n\#endif\n! &&
        $file =~ m!(\#\s*pragma\s+(interface|implementation))\b!);

# Now remove comments and string constants before checking further:
  $file_s = "\n" . $file;
  # continuation lines:
  $file_s =~ s!\\\n!!g;
  $file_s =~ s!\n\#if\s+0\s*\n.*?\n\#endif\s*\n!\n!g;
  # remove string constants, incl. multiline string constants with "correct syntax":
  $file_s =~ s!\'\"\'!!g;
  $file_s =~ s!([^\\])(\\\")+!$1!g;
  $file_s =~ s!\".*?\"!\003!g;
  # replace :: by \005 and -> by \006 (useful later)
  $file_s =~ s!::!\005!g;
  $file_s =~ s!->!\006!g;
  # remove // comments
  $file_s =~ s!//.*\n!\n!g;
  # remove /* ... */ comments
  $file_s =~ s!(\001|/\*)[^\001\002]*\002!!g;
# &msg(1, "contains nested comments")
#   if ($file_s =~ m![\001\002]!);

# 11. Multi-line string constant
  &msg(1, "contains multi-line string constant")
    if ($file_s =~ m!\"!);

# 12. Inclusion guard and file name
  if ($file_s =~ m!^\s*\#ifndef\s+(\S+)\s*\n\#define\s+\1\s*(\s.*)?\n!)
  {
    $guard = $1;
    if (defined($inclusion_guards{"$guard"}) && $f ne $inclusion_guards{"$guard"})
    {
      &msg(1, "has the same inclusion guard as " . $inclusion_guards{"$guard"} . "");
    }
    else
    {
      $inclusion_guards{"$guard"} = "$f";
    }
    &msg(1, "last line: change $2 to $guard")
      if ($file =~ m!\#endif\s*(//|/\*)\s*(\S+)\s*(\*/)?$! && $2 ne $guard);
    undef $guard;
  }
  else
  {
    &msg(1, "has no (valid) inclusion guard")
      if ($cpp_file && $f =~ m!\.(txx|h)$! &&
          $f !~ m!vcl/vcl_typeinfo\.h$! &&
          $f !~ m!copyright\.h$! &&
          $f !~ m!/resource\.h$!i &&
          $file_s ne "\n");
  }

  if ($file =~ m!//\s*This\s+is\s+([^\s]+)\n!)
  {
    $filename = $1; chop($pwd = `pwd`);
    $file_ = $f; $file_ = "$pwd/$f" unless $f =~ m!^/!;
    while ($file_ =~ m!/\.\./!) { $file_ =~ s![^/]+/\.\./!!g; }
    while ($file_ =~ m!/\./!) { $file_ =~ s!/\./!/!g; }
    $file_ =~ s!(/contrib/.*)/core/!$1/CORE/!;
    $file_ =~ s!^.*/(config|vcl|v3p|core|contrib)/!$1/!;
    $file_ =~ s!^contrib/!!; $file_ =~ s!/CORE/!/core/!;
    &msg(1, "has // This is $filename, should be $file_")
      unless ($filename eq $file_ ||
              'brl/'.$filename eq $file_ ||
              'gel/mrc/'.$filename eq $file_ ||
              ($file_ =~ m!/bocl\b! && $file_ =~ m!$filename$!) ||
              ($filename eq "contrib/$file_" && !$printed));
  }

# 13. Constants pi, e, euler written as 3.1415..., 2.71828..., 0.5772...
  %math_cst = ('3\.141[56]' => 'pi',
               '1\.570[78]' => 'pi_over_2',
               '0\.785[34]' => 'pi_over_4',
               '0\.01745'   => 'pi_over_180',
               '0\.3183'    => 'one_over_pi',
               '6\.283[12]' => '2*pi',
               '0\.6366'    => 'two_over_pi',
               '57\.29[56]' => 'deg_per_rad',
               '1\.128[34]' => 'two_over_sqrtpi',
               '0\.3989'    => 'one_over_sqrt2pi',
               '0\.5772'    => 'euler',
               '2\.718[23]' => 'e',
               '1\.442[67]' => 'log2e',
               '0\.434[23]' => 'log10e',
               '0\.6931'    => 'ln2',
               '2\.302[56]' => 'ln10',
               '1\.4142'    => 'sqrt2',
               '2\.4142'    => '1+sqrt2',
               '0\.577[34]' => 'sqrt1_3',
               '0\.7071'    => 'sqrt1_2');
  foreach $cst (keys %math_cst) {
    $name = $math_cst{$cst};
    if (substr($cst,0,1) eq '0') { substr($cst,0,1) = '((\B|\b0)'; } else { $cst = '\b(' . $cst; }
    $cst .= '\d*)\b';
    &msg(1, "should maybe use vnl_math::$name instead of $1")
      if ($f !~ m!\b(v[cuibg]l|v3p|vidl)\b/! && $f !~ m!\bcore/vnl/vnl_math\.! &&
          ! ( $name eq 'e'                && $f =~ m!\bvgui/tests/test_popup\.cxx$! ) &&
          ! ( $name eq 'log10e'           && $f =~ m!\bvnl/algo/vnl_rnpoly_solve\.cxx$! ) &&
          ! ( $name eq 'log10e'           && $f =~ m!\bvpgl/algo/tests/test_camera_bounds\.cxx$! ) &&
          ! ( $name eq 'sqrt2'            && $f =~ m!\brpl/rrel/rrel_misc\.cxx$! ) &&
          ! ( $name eq 'sqrt1_2'          && $f =~ m!\bgel/gevd/gevd_float_operators\.cxx$! ) &&
          ! ( $name eq 'sqrt1_2'          && $f =~ m!\bgel/mrc/vpgl/tests/test_affine_camera\.cxx$! ) &&
          ! ( $name eq 'pi'               && $f =~ m!\bbsta/algo/tests/test_von_mises_update\.cxx$! ) &&
          ! ( $name eq 'pi_over_4'        && $f =~ m!\bvpgl/vsph/tests/test_spherical_coord\.cxx$! ) &&
          ! ( $name eq 'one_over_sqrt2pi' && $f =~ m!\bbsta/bsta_von_mises\.txx$! ) &&
          $cpp_file && $file_s =~ m!$cst! );
  }

# 14. Instantiation macro stuff
  &msg(1, "definition of $1 ends with ;")
    if ($file_s =~ m!\#define\s+(\S*INSTANTIATE[^\s\(\)]*).+;\s*\n!);
  &msg(1, "definition of $1 does not start with a space")
    if ($file_s =~ m!\#define\s+(\S*INSTANTIATE[^\s\(\)]*)\s*\([^)]*\)\S!);
  &msg(1, "definition of $1 has no space before > in $2")
    if ($file_s =~ m!\#define\s+(\S*INSTANTIATE[^\s\(\)]*).+(\<[^<>\n]*[A-Za-z_]\w*\>)!
        && length($2) < 16 && $2 ne "<float>" && $2 ne "<double>" && $2 ne "<T,n>" && $2 ne "<N>" && $2 ne "<double, N, N>");
# Presence of VCL_*_INSTANTIATE in *.cxx files outside Templates directories
  &msg(1, "$1 may only be used in Templates subdirectories")
    if ($f !~ m!/Templates/! &&
        $f !~ m!vcl/tests/test_rel_ops\.cxx$! &&
        $f !~ m!core/vsl/tests/test_polymorphic_io\.cxx$! &&
        $f !~ m!core/vbl/tests/vbl_test_classes\.cxx$! &&
        $f !~ m!core/vbl/examples/vbl_smart_ptr_example\.cxx$! &&
        $f !~ m!oxl/apps/glmovie/glmovie.cxx$! &&
        $file_s =~ m!\n\s*(VCL_[_A-Z]*INSTANTIATE[_A-Z]*)! &&
        "$1" ne "VCL_INSTANTIATE_INLINE");
# Check correct file name of *.cxx files in Templates directories
  $file_s =~ s!VCL_DO_NOT_INSTANTIATE!VCL_do_not_INSTANTIATE!g;
  if ($f =~ m!/Templates/!) { while ($file_s =~ s!\btypedef\s+([^;]*)\s(\w+)\s*\;!!) { $A=$1; $B=$2; $file_s =~ s!\b$B\b!$A!g; } }
  if ($f =~ m!/Templates/! &&
      $f !~ m!vcl/Templates/(complex|string)-instances\.cxx$! &&
      $f !~ m!core/vnl/algo/Templates/fsm_pack\.cxx$! &&
      $f !~ m!core/vbl/examples/Templates/smartptr-instances\.cxx$! &&
      $f !~ m!core/vnl/Templates/vnl_matrix_fixed_pairwise_ops\.cxx$! &&
      $f !~ m!bsta/algo/Templates/bsta_parzen_updater.bsta_parzen_sphere.float! &&
      $f !~ m!bvpl/util/Templates/bvxm_voxel_x.bvpl_pair! &&
      $f !~ m!rgtl/Templates/rgtl_sqt_(cell_geometry|space)\+\d\._-! &&
      $file_s =~ m!\b(\w*)_INSTANTIATE\s*\((.*)\)!)
  {
    $class=$1; $class =~ tr/A-Z/a-z/; $class="$class<$2>";
    $class =~ s!\bvcl_(swap|containable)\s*\<!vcl_algorithm\<!g;
    $class =~ s!\bvcl_sort\s*\<[^,]+\,!vcl_algorithm\<!g;
    $class =~ s!\bvcl_find(_if)?\s*\<\s*vcl_(vector|list)\s*\<([^\005]+)\005\s*(const_)?iterator.+!vcl_algorithm\<$3!g;
#   while ($file_s =~ s!\btypedef\s+([^;]*)\s(\w+)\s*\;!!)
#   { $A=$1; $B=$2; $B =~ s!([][{}()|*+/\\])!\\$1!g; $class =~ s!\b$B\b!$A!g; }
#   $class =~ s!\bconst\b!!g;
    $class =~ s!\s!!g;
    $class =~ s!\bconstchar!const_char!g; $class =~ s!(\w)const([^r])!$1_const$2!g;
    $class =~ s!\,\s*vcl_less\<[^<>]+\<[^<>]+\>[^<>]*\>!!g;
    $class =~ s!\,\s*vcl_less\<[^<>]+\>!!g;
    $class =~ s!\,(.*)_sptr\,\1\005compare!!g;
    $class =~ s!(vbl_io_sparse_array)_base\<!$1\<!g;
    $class =~ s!(vgl_intersection)_box\<!$1\<!g;
    $class =~ s!\005!+-!g; $class =~ tr/<,*>/+.~-/; # \005 is ::
    $class_q = $class; $class_q =~ s!([.+~-])!\\$1!g;
    $class =~ s!unsigned(int|short|long|char)!u$1!g;$class =~ s!unsigned!uint!g;
    $class =~ s!signed(int|short|long|char)!s$1!g;  $class =~ s!signed!sint!g;
    $class =~ s!longd!long_d!g;
    $class =~ s!vxl_(s?byte|u?int)!$1!g;
    $class =~ s!^brdb_value\+(.*)\.\003\-!brdb_value_t+$1-!;
    $class =~ s!^bbgm_image\+!bbgm_image_of+!;
    $class_r = $class; $class_r =~ s!([.+~-])!\\$1!g;
    $class_s = $class_q; $class_s =~ s!signed!signed_!g; $class_s =~ s!long!long_!g;
    &msg(1, "should be renamed to $class.cxx")
      if ($f !~ m!/$class_q\.(cxx|cc|C)$! &&
          $f !~ m!/$class_r\.(cxx|cc|C)$! &&
          $f !~ m!/$class_s\.(cxx|cc|C)$!);
  }

# 15. Missing vcl_
  foreach $wd (qw(abort exit))
  {
    if ($cpp_file && $file_s =~ m!\b$wd\s*(\s*)\(!)
    {
      &msg(1, "$wd$1() must be vcl_$wd()")
        unless ($f =~ m!\bcmake/config/vxl_platform_tests\.cxx$! ||
                $f =~ m!/bwm_tableau_mgr\.(cxx|h)$! ||
                $f =~ m!/bwm(_wx)?_menu\.h$!);
    }
  }

  foreach $wd (qw(complex real imag conj arg polar min max abs acos asin atan atan2 ceil cos cosh exp fabs floor fmod frexp ldexp log log10 modf pow sin sinh sqrt tan tanh perror printf fprintf sprintf scanf fscanf sscanf fopen fclose fread fwrite memchr memcpy memcmp memmove memset qsort strcat strncat strcpy strncpy strchr strcmp strncmp strcoll strcspn strerror strlen strpbrk strrchr strspn strstr strtok strxfrm isspace isprint iscntrl isupper islower isalpha isgraph isdigit ispunct isxdigit isalnum isgraph toupper tolower))
  {
    &msg(1, "$wd$1() must be vcl_$wd()")
      if ($cpp_file &&
          "$f.$wd" !~ m!\bvul_timer\.(h|cxx)\.real$! &&
          "$f.$wd" !~ m!\bvnl_quaternion\.h\.real$! &&
          "$f.$wd" !~ m!\bvnl/tests/test_complex\.cxx\.acos$! &&
          "$f.$wd" !~ m!\bmbl_arb_length_int\.h\.abs$! &&
          "$f.$wd" !~ m!\bmbl_log\.h\.log$! &&
          "$f.$wd" !~ m!\bvnl_(bignum|rational|decnum)\.h\.abs$! &&
          "$f.$wd" !~ m!\bvnl/(vnl_rational\.h|vnl_decnum\.h|tests/test_rational\.cxx)\.(ceil|floor)$! &&
          "$f.$wd" !~ m!\bvnl_(finite|decnum)\.h\.(exp|log|pow)$! &&
          "$f.$wd" !~ m!\bvil1?_rgb\.(h|txx)\.(min|max)$! &&
          "$f.$wd" !~ m!\bvbl_bounding_box\.(h|txx)\.(min|max)$! &&
          "$f.$wd" !~ m!\bvnl_sse\.h\.(min|max)$! &&
          "$f.$wd" !~ m!\bvgel/kl/base\.h\.(min|max)$! &&
          "$f.$wd" !~ m!\bmbl_stats_1d\.h\.(min|max)$! &&
          "$f.$wd" !~ m!\brgrl_spline\.cxx\.(ceil|floor|min|max)$! &&
          "$f.$wd" !~ m!\brgrl/tests/test_spline\.cxx\.(ceil|floor)$! &&
          "$f.$wd" !~ m!\bmvl/HomgConic\.(h|cxx)\.polar$! &&
          "$f.$wd" !~ m!\bbdgl_curve_clustering\.(cxx|h)\.(min|max)$! &&
          "$f.$wd" !~ m!\bbsta_histogram\.h\.(min|max)$! &&
          "$f.$wd" !~ m!\bbvxm_lidar_processor\.cxx\.(min|max)$! &&
          "$f.$wd" !~ m!\bbbgm_view_maker\.h\.(min|max)$! &&
          "$f.$wd" !~ m!\bbvpl_kernel_factory\.h\.(min|max)$! &&
          "$f.$wd" !~ m!\bvidl_pixel_format\.h\.(min|max)$! &&
          "$f.$wd" !~ m!\bmbl_sample_stats_1d\.h\.(min|max)$! &&
          "$f.$wd" !~ m!\bmbl/tools/sample_stats\.cxx\.(min|max)$! &&
          "$f.$wd" !~ m!\bbvpl/kernels/bvpl_kernel\.h\.(min|max)$! &&
          "$f.$wd" !~ m!\balgo/vnl_rn?poly_(solve|roots)\.h\.(real|imag)$! &&
          "$f"     !~ m!\bcmake/config/vxl_platform_tests\.cxx$! &&
          $file_s =~ m![^.\005\006]\b$wd(\s*)\(! ); # \005 is :: and \006 is ->
  }
  foreach $wd (qw(cin cout cerr clog endl ends flush ios istream ostream fstream ifstream ofstream strstream ostrstream streambuf streamoff streamsize fpos streampos stringstream))
  {
    &msg(1, "$wd must be vcl_$wd")
      if ($cpp_file && $f !~ m!\bvcl/Templates/stream-instances\.cxx$! &&
          $f !~ m!\bvcl/tests/test_driver\.cxx$! &&
          $f !~ m!\bcmake/config/vxl_platform_tests\.cxx$! &&
          $file_s =~ m![^ .]\s*\b$wd\b\s*[^ (]! );
  }
  foreach $wd (qw(basefield floatfield adjustfield fmtflags seekdir))
  {
    &msg(1, "$wd must be vcl_ios_$wd")
      if ($cpp_file && $file_s =~ m![^ .]\s*\b$wd\b\s*[^ (]!);
  }
  foreach $wd (qw(beg cur end))
  {
    &msg(1, "$wd must be vcl_ios_$wd")
      if ($cpp_file &&
          ($wd !~ m!end! ||
           ($f !~ m!\boxp/oxp_mpeg_codec\.cxx$! &&
            $f !~ m!\bvil3d_slice_list\.cxx$! &&
            $f !~ m!\bvgui_dir_dialog\.cxx$! &&
            $f !~ m!\b(rrel/rrel_util|rsdl/rsdl_borgefors)\.txx$! ) ) &&
          $file_s =~ m!,\s*$wd\s*\)! );
  }
  foreach $wd (qw(boolalpha noboolalpha showbase noshowbase showpoint noshowpoint showpos noshowpos skipws noskipws uppercase nouppercase))
  {
    &msg(1, "$wd must be vcl_ios_$wd")
      if ($cpp_file && $file_s =~ m![^ .]\s*\b$wd\b\s*[^ (]!);
    &msg(1, "$wd() must be vcl_$wd()")
      if ($cpp_file && $file_s =~ m!\b$wd\s*\(!);
  }
  foreach $wd (qw(internal left right))
  {
    &msg(1, "$wd must be vcl_ios_$wd")
      if ($cpp_file &&
          ($wd !~ m!(left|right)! ||
           ($f !~ m!\bpdf1d_pdf\.cxx$! &&
            $f !~ m!\bvnl_matrix(|_fixed(|_ref))\.txx|algo/vnl_complex_eigensystem\.cxx$! &&
            $f !~ m!\b(vsl_conic_points|gevd_float_operators|vcsl_tutor)\.cxx$! &&
            $f !~ m!\bvtol_extract_topology\.(h|cxx|txx)$! &&
            $f !~ m!\brgrl_invariant_match\.(cxx|h)$! &&
            $f !~ m!\brsdl_(bins_2d|kd_tree)\.h$! &&
            $f !~ m!\bbgui3d_algo\.(h|cxx)$! &&
            $f !~ m!\bbgui3d_examiner_tableau\.cxx$! &&
            $f !~ m!\brgtl_octree_objects\.txx$! &&
            $f !~ m!\brgtl_sqt_objects\.txx$! &&
            $f !~ m!\brsdl/(rsdl_kd_tree|tests/test_bins_2d|tests/test_kd_tree)\.cxx$! &&
            $f !~ m!\bclsfy/clsfy_binary_tree_builder\.cxx$! &&
            $f !~ m!\bclsfy/clsfy_binary_tree\.cxx$! &&
            $f !~ m!\bclsfy/clsfy_binary_tree_builder\.cxx$! ) ) &&
          $f !~ m!\bimesh/algo/imesh_kd_tree\.h$! &&
          $file_s =~ m![^ .>]\s*\b$wd\s*[|),]! );
    &msg(1, "vcl_ios_$wd must be used together with vcl_ios_adjustfield")
      if ($cpp_file &&
          $file_s =~ m!\bvcl_ios_$wd\s*[^ ,]! &&
          $f !~ m!\bvul/tests/test_ios_state\.cxx$! &&
          $f !~ m!\bmul/mbl/mbl_progress_time\.cxx$! &&
          $file_s !~ m!(vcl_resetiosflags|\.\s*unsetf)\s*\((vcl_ios_(internal|left|right)\s*\|\s*)*vcl_ios_$wd\s*(\|\s*vcl_ios_(internal|left|right)\s*)*\)! );
    &msg(1, "$wd() must be vcl_$wd()")
      if ($cpp_file &&
          ($f !~ m!\boxl/oxp/vsl_conic_points\.cxx$! || $wd !~ m!(left|right)! ) &&
          $f !~ m!\bbgui3d_(algo|examiner_tableau)\.cxx$! &&
          $file_s =~ m!\b$wd\s*\(!);
  }
  foreach $wd (qw(dec hex oct))
  {
    &msg(1, "$wd must be vcl_ios_$wd")
      if ($cpp_file && $file_s =~ m!\b$wd\s*[|),]!);
    &msg(1, "vcl_ios_$wd must be used together with vcl_ios_basefield")
      if ($cpp_file && $file_s =~ m!\bvcl_ios_$wd\s*[^ ,]! &&
          $file_s !~ m!(vcl_resetiosflags|\.\s*unsetf)\s*\((vcl_ios_(dec|hex|oct)\s*\|\s*)*vcl_ios_$wd\s*(\|\s*vcl_ios_(dec|hex|oct)\s*)*\)!);
    &msg(1, "$wd() must be vcl_$wd()")
      if ($cpp_file && $file_s =~ m!\b$wd\s*\(!);
  }
  foreach $wd (qw(scientific fixed))
  {
    &msg(1, "$wd must be vcl_ios_$wd")
      if ($cpp_file &&
          ($f !~ m!\b(vpdfl/vpdfl_pc_gaussian_builder|bgui_bargraph_clipon_tableau)\.! || $wd !~ m!^fixed$!) &&
          $file_s =~ m!\b$wd\s*[|),]!);
    &msg(1, "vcl_ios_$wd must be used together with vcl_ios_floatfield")
      if ($cpp_file && $file_s =~ m!\bvcl_ios_$wd\s*[^ ,]! &&
          ($f !~ m!\bvpdfl/vpdfl_pc_gaussian_builder\.! || $wd !~ m!^fixed$!) &&
          $file_s !~ m!(vcl_resetiosflags|\.\s*unsetf)\s*\((vcl_ios_(scientific|fixed)\s*\|\s*)*vcl_ios_$wd\s*(\|\s*vcl_ios_(scientific|fixed)\s*)*\)!);
    &msg(1, "$wd() must be vcl_$wd()")
      if ($cpp_file && $file_s =~ m!\b$wd\s*\(!);
  }
  foreach $wd (qw(size_t ptrdiff_t clock_t time_t))
  {
    &msg(1, "$wd must be vcl_$wd")
      if ($cpp_file && $file_s =~ m!\b$wd\b! && $f !~ m!\bvnl/vnl_numeric_traits\.h$!);
  }
  foreach $wd (qw(iterator_traits back_insert_iterator front_insert_iterator insert_iterator input_iterator_tag output_iterator_tag forward_iterator_tag bidirectional_iterator_tag random_access_iterator_tag))
  {
    &msg(1, "$wd must be vcl_$wd")
      if ($cpp_file && $f !~ m!\bvcl/.*\bvcl_iterator\.(h|txx)$! && $file_s =~ m!\b$wd\b!);
  }

# 16. Multiple empty lines, empty line before } or after {, return (...), indentation,
#   if/for/while/else without space, variable names starting with underscore
#   (mentioned only if something else is already printed, or when -f given)
  &msg(1, "contains multiple (>2) empty lines")
    if ($printed && $file =~ m!\n\n\n\n!);
  &msg(1, "has lines ending in spaces")
    if ($printed && $has_end_spaces);
  &msg(1, "has empty lines before closing brace")
    if ($printed && $file =~ m!\n\n[ \t]*\};*\s*\n!);
  &msg(1, "has empty lines after opening brace")
    if ($printed && $file =~ m!\n[ \t]*\{\s*\n\n!);
  &msg(1, "has empty lines after function header")
    if ($printed && $file =~ m!\n[ \t]*\n\{!);
  &msg(1, "Replace \"$1 (0)\" by \"$1 (false)\"")
    if ($printed && $cpp_file && $file =~ m!\b(if|while)\s*\(\s*0\s*\)!);
  &msg(1, "Replace \"$1 (1)\" by \"$1 (true)\"")
    if ($printed && $cpp_file && $file =~ m!\b(if|while)\s*\(\s*1\s*\)!);
  $f_=$fl;
  while ($printed && $f_ =~ s!\n([^()\'\";\n]*\( *)((\([^();\n]*\))*[^();\n]+(\([^();\n]*\)[^();\n]*)*)\n( +)([+-] *)!\n$5$6!)
  {
    $line="$1$2"; $first=$2; $post="$5"; $ppost="$6"; $pre="$1"; $pre =~ s!.! !g; $ppost =~ s!.! !g;
    &msg(1, "incorrect indentation in line following \"$line\"")
      unless ($pre eq $post || $pre eq $post.$ppost || $line =~ m!_INSTANTIATE_! || $line =~ m!\<\<! || $first eq "//");
  }
  $f_=$fl; $f_ =~ s!\"[^\n\"]*\"!Q!g; $f_ =~ s!\'\\?.\'!Q!g; $f_ =~ s!\<\<!\007!g;
  while ($printed && $f_ =~ s!\n([^\007;{}\#\n]*)(\007[^;\n]*)\n( +)\007!\n$3\007!)
  {
    $line="$1$2"; $pre="$1"; $post="$3"; next if ($pre =~ m!^\s*$!);
    $line =~ s!\007!\<\<!g; $pre =~ s!.! !g;
    &msg(1, "incorrect indentation in line following \"$line\"")
      unless ($pre eq $post);
  }
  if ($printed && $file =~ m!\n( *)(\S+).*\n(\1 +)\{ *\n\3 ! && $2 !~ m!\#(if|ifdef|else|endif)!) {
    $tmp=$file; $tmp =~ s!\n( *)\S.*\n(\1 +)\{ *\n\2 [^\000]*!!; $tmp =~ s![^\n]*!!g; $tmp=length($tmp)+3;
    &msg($tmp, "excess indentation in code block around line $tmp");
  }
  &msg(1, "consider placing \"else\" on a separate line")
    if ($printed && $file =~ m!\} *else\b!);
  undef $f_;
  &msg("/$1", "$1 not preceded by space")
    if ($printed && $file =~ m!\n(public|private|protected)\s*\:!);
  &msg("/$1", "$1 preceded by more than one space")
    if ($printed && $file =~ m!  (public|private|protected)\s*\:!);
  &msg(1, "No empty line between two function bodies")
    if ($printed && $file =~ m!\n};? *\n([a-zA-Z]+)! && $1 ne "typedef");
  &msg(1, "Consider placing opening brace of function body on new line")
    if ($printed && $file =~ m!\n([a-zA-Z]\S*).* (\S+) *\{ *\n! && $1 ne "extern" && $1 ne "struct" && $2 ne "=");
  &msg("/$1", "$1 not followed by space")
    if ($printed && $file =~ m!\b(for|if|while|switch)\(!);
  &msg('return', "return value in brackets")
    if ($printed && $file =~ m!\breturn\s*\([^;()]*(\([^;()]*\)[^;()]*)*\)\s*;!);
  &msg('delete', "delete value in brackets")
    if ($printed && $file =~ m!\n [^\n]*\bdelete\s*\([^;()]*(\([^;()]*\)[^;()]*)*\)\s*;!);
  $file =~ s!^\#.*!!g; $file =~ s!\n\#.*!!g;
  &msg("/$2", "$2 starts with underscore")
    if ($cpp_file && $printed && $file_s =~ m!([^\"\# ] *\b|^)(_[a-z]\w*)(.)! && '$2$3' ne '_fmemset(' && '$2$3' ne '_declspec(' && $2 ne '_finddata_t' && $2 ne '_aligned_malloc');

# 17. too long { ... } section with the "{" not on the start of a line
  &msg(1, "has a block of more than 52 lines with the opening brace not on a line by itself")
    if ($printed && $file =~ m!\S *\{ *\n( +)\S.*\n(\1.*\n){52}!);
}

sub msg
{
  my ($linenum,$message,$quiet) = @_;
  if ($emacs)  { print "$f:$linenum:\t\# $message"; }
  elsif ($vim) { print "vim +$linenum $f\t\# $message"; }
  else         { print "$f\t\# $message"; }
  $printed = 1 unless (defined($quiet) || $brief);
}
