$s = <<'EOF';
  perl_checker
  
Quick Start
To use perl_checker, simply use "perl_checker a_file.pl"
To use under emacs, simply add the following line to your .emacs, 
then when you visit a perl file, you can use Ctrl-Return to run perl_checker
on this file
  (global-set-key [(control return)] (lambda () (interactive) (save-some-buffers 1) (compile (concat "perl_checker --restrict-to-files " (buffer-file-name (current-buffer))))))
To use with vim, use something like:
  perl_checker --restrict-to-files scanner.pm > errors.err ; vim -c ':copen 4' -c ':so /usr/share/vim/ftplugin/perl_checker.vim' -q
where /usr/share/vim/ftplugin/perl_checker.vim is
" Error formats
setlocal efm=
  \%EFile\ \"%f\"\\,\ line\ %l\\,\ characters\ %c-%*\\d:,
  \%EFile\ \"%f\"\\,\ line\ %l\\,\ character\ %c:%m,
  \%+EReference\ to\ unbound\ regexp\ name\ %m,
  \%Eocamlyacc:\ e\ -\ line\ %l\ of\ \"%f\"\\,\ %m,
  \%Wocamlyacc:\ w\ -\ %m,
  \%-Zmake%.%#,
  \%C%m
Goals of perl_checker
-  for beginners in perl:
  based on what the programmer is writing,
 
  -  suggest better or more standard ways to do the same
  
-  detect wrong code
  
 => a kind of automatic teacher
 
-  for senior programmers:
  detect typos, unused variables, check number
  of parameters, global analysis to check method calls...
-  enforce the same perl style by enforcing a subset of perl of features.
     In perl There is more than one way to do it. 
     In perl_checker's subset of Perl, there is not too many ways to do it.
     This is especially useful for big projects.
     (NB: the subset is chosen to keep a good expressivity)
- perl_checker use its own OCaml-written parser.
  This parser only handle a subset of perl, 
    whereas one of PPI's goal is to be able to parse non finished perl documents.
  perl_checker is a checker: it is not a big deal to die horribly on a weird perl expression, it tells the programmer what to write instead.
   The issue is that perl_checker includes inter-modules analysis, and it implies being able to parse non-perl_checker compliant modules.
   A solution for this is perl_checker fake modules. No perfect solution though.
 
- PPI doesn't handle operator priorities: 1 + 2 << 3 is parsed as
    - PPI: a list [ Number(1), Operator(+), Number(2), Operator(<<), Number(3) ]
        
- perl_checker: a tree Operator(<<, [ Operator(+, [ Number(1), Number(2) ]), Number(3) ])
    
 This limits perlcritic checks to a syntax level.
- perl_checker is much faster (more than 100 times) (ML pattern matching rulez)
- perl_checker checks a lot more things than perlcritic: undeclared variables, unknown functions, unknown methods...
- and of course perl_checker checks are different from the Conways's Perl Best Practices
Get it
tarball
SVN source
MDK::Common tarball
Implemented features
 - detect some Perl traps
 
- some Perl expressions are stupid, and one gets a warning when running
 them with perl -w. The drawback of perl -w is the lack of
 code coverage, it only detects expressions which are evaluated.
 TESTS=various_errors.t
 
- context checks
 
- Perl has types associated with variables names, the so-called "context".
 Some expressions mixing contexts are stupid, perl_checker detects them.
 TESTS=context.t
 
- suggest simpler expressions
 
- when there is a simpler way to write an expression, suggest it. It can
 also help detecting errors.
 TESTS=suggest_better.t
 
- function call check
 
- detection of unknown functions or mismatching prototypes (warning: since
  perl is a dynamic language, some spurious warnings may occur when a function
  is defined using stashes).
 TESTS=prototype.t
 
- method call check
 
- detection of unknown methods or mismatching prototypes. perl_checker
 doesn't have any idea what the object type is, it simply checks if a method
 with that name and that number of parameters exists.
 TESTS=method.t
 
- return value check
 
- dropping the result of a functionnally pure function is stupid.
 using the result of a function returning void is stupid too.
 
 (nb: perl_checker enforces && and || are used as boolean operators 
      whereas and and or are used for control flow)
 TESTS=return_value.t
- white space normalization
 
- enforce a similar coding style. In many languages you can find a coding
 style document (eg: the GNU one).
 TESTS=force_layout.t
 
- disallow complex expressions
 
- perl_checker try to ban some weird-not-used-a-lot features.
 TESTS=syntax_restrictions.t
 
Todo
Functionalities that would be nice:
 -  add flow analysis
 
-  maybe a "soft typing" type analysis
 
-  detect places where imperative code can be replaced with
   functional code (already done for some simple loops)
 
-  check the number of returned values when checking prototype compliance
EOF
my $_rationale = <<'EOF';Rationale
Perl is a big language, there is ThereIsMoreThanOneWayToDoIt.
It has advantages but also some drawbacks for team project:
 -  it is hard to learn every special rules. Automatically enforced syntax
 coding rules help learning incrementally
EOF
use lib ('test', '..');
use read_t;
sub get_example {
    my ($file) = @_;
    my @tests = read_t::read_t("test/$file");
    $file =~ s|test/||;
    qq(
 \n) .
      join('', map { 
	  my $lines = join("
 ", map { "" . html_quote($_) . "" } @{$_->{lines}});
	  my $logs = join("
 ", map { html_quote($_) } @{$_->{logs}});
	  $logs ? "| \n" . $lines . " | " . $logs . " |  \n" : '';
      } @tests) .
      "
 \n";
}
sub anchor_to_examples {
    my ($s) = @_;
    $s =~ s!TESTS=(\S+)!(examples)!g;
    $s;
}
sub fill_in_examples {
    my ($s) = @_;
    $s =~ s!TESTS=(\S+)!get_example($1)!ge;
    $s;
}
$s =~ s!Implemented features(.*)!
        "Implemented features" . anchor_to_examples($1) .
        "Examples" . fill_in_examples($1) .
        ""!se;
print $s;
sub html_quote {
    local $_ = $_[0];
    s/</g;
    s/>/>/g;
    s/^(\s*)/" " x length($1)/e;
    $_;
}