-#!/usr/local/bin/perl
-eval 'exec perl -S $0 ${1+"$@"}'
- if 0;
-
-use Config;
-if ($^O eq 'VMS') {
- $diagnostics::PODFILE = VMS::Filespec::unixify($Config{'privlibexp'}) .
- '/pod/perldiag.pod';
-}
-else { $diagnostics::PODFILE= $Config{privlibexp} . "/pod/perldiag.pod"; }
-
package diagnostics;
-require 5.001;
-use English;
-use Carp;
=head1 NAME
=head2 The C<diagnostics> Pragma
This module extends the terse diagnostics normally emitted by both the
-perl compiler and the perl interpeter, augmenting them with the more
+perl compiler and the perl interpreter, augmenting them with the more
explicative and endearing descriptions found in L<perldiag>. Like the
other pragmata, it affects the compilation phase of your program rather
than merely the execution phase.
any other diagnostics. The $diagnostics::PRETTY variable can generate nicer
escape sequences for pagers.
+Warnings dispatched from perl itself (or more accurately, those that match
+descriptions found in L<perldiag>) are only displayed once (no duplicate
+descriptions). User code generated warnings ala warn() are unaffected,
+allowing duplicate user messages to be displayed.
+
=head2 The I<splain> Program
While apparently a whole nuther program, I<splain> is actually nothing
insurmountable.
The C<-pretty> directive is called too late to affect matters.
-You have to to this instead, and I<before> you load the module.
+You have to do this instead, and I<before> you load the module.
BEGIN { $diagnostics::PRETTY = 1 }
I could start up faster by delaying compilation until it should be
-needed, but this gets a "panic: top_level"
-when using the pragma form in 5.001e.
+needed, but this gets a "panic: top_level" when using the pragma form
+in Perl 5.001e.
While it's true that this documentation is somewhat subserious, if you use
a program named I<splain>, you should expect a bit of whimsy.
=head1 AUTHOR
-Tom Christiansen F<E<lt>tchrist@mox.perl.comE<gt>>, 25 June 1995.
+Tom Christiansen <F<tchrist@mox.perl.com>>, 25 June 1995.
=cut
+use 5.005_64;
+use Carp;
+
+$VERSION = v1.0;
+
+use Config;
+($privlib, $archlib) = @Config{qw(privlibexp archlibexp)};
+if ($^O eq 'VMS') {
+ require VMS::Filespec;
+ $privlib = VMS::Filespec::unixify($privlib);
+ $archlib = VMS::Filespec::unixify($archlib);
+}
+@trypod = (
+ "$archlib/pod/perldiag.pod",
+ "$privlib/pod/perldiag-$Config{version}.pod",
+ "$privlib/pod/perldiag.pod",
+ "$archlib/pods/perldiag.pod",
+ "$privlib/pods/perldiag-$Config{version}.pod",
+ "$privlib/pods/perldiag.pod",
+ );
+# handy for development testing of new warnings etc
+unshift @trypod, "./pod/perldiag.pod" if -e "pod/perldiag.pod";
+($PODFILE) = ((grep { -e } @trypod), $trypod[$#trypod])[0];
+
$DEBUG ||= 0;
my $WHOAMI = ref bless []; # nobody's business, prolly not even mine
-$OUTPUT_AUTOFLUSH = 1;
+$| = 1;
local $_;
unless (caller) {
$standalone++;
require Getopt::Std;
- Getopt::Std::getopts('pdvf:') || die "Usage: $0 [-v] [-p] [-f splainpod]";
+ Getopt::Std::getopts('pdvf:')
+ or die "Usage: $0 [-v] [-p] [-f splainpod]";
$PODFILE = $opt_f if $opt_f;
$DEBUG = 2 if $opt_d;
$VERBOSE = $opt_v;
$transmo = <<EOFUNC;
sub transmo {
- local \$^W = 0; # recursive warnings we do NOT need!
+ #local \$^W = 0; # recursive warnings we do NOT need!
study;
EOFUNC
}
next;
}
- $header = $1;
- if ($header =~ /%[sd]/) {
+ # strip formatting directives in =item line
+ ($header = $1) =~ s/[A-Z]<(.*?)>/$1/g;
+
+ if ($header =~ /%[csd]/) {
$rhs = $lhs = $header;
#if ($lhs =~ s/(.*?)%d(?!%d)(.*)/\Q$1\E\\d+\Q$2\E\$/g) {
if ($lhs =~ s/(.*?)%d(?!%d)(.*)/\Q$1\E\\d+\Q$2\E/g) {
#$lhs =~ s/\377([^\377]*)$/\Q$1\E\$/;
$lhs =~ s/\377([^\377]*)$/\Q$1\E/;
$lhs =~ s/\377//g;
+ $lhs =~ s/\.\*\?$/.*/; # Allow %s at the end to eat it all
}
- $transmo .= " s{^$lhs}\n {\Q$rhs\E}\n\t&& return 1;\n";
+ $lhs =~ s/\\%c/./g;
+ $transmo .= " s{^$lhs}\n {\Q$rhs\E}s\n\t&& return 1;\n";
} else {
$transmo .= " m{^\Q$header\E} && return 1;\n";
}
- print STDERR "Already saw $header" if $msg{$header};
+ print STDERR "$WHOAMI: Duplicate entry: \"$header\"\n"
+ if $msg{$header};
$msg{$header} = '';
}
if ($standalone) {
if (!@ARGV and -t STDIN) { print STDERR "$0: Reading from STDIN\n" }
- while ($error = <>) {
+ while (defined ($error = <>)) {
splainthis($error) || print THITHER $error;
}
exit;
} else {
- $old_w = 0; $oldwarn = ''; $olddie = '';
+ #$old_w = 0;
+ $oldwarn = ''; $olddie = '';
}
sub import {
shift;
- $old_w = $^W;
+ #$old_w = $^W;
$^W = 1; # yup, clobbered the global variable; tough, if you
# want diags, you want diags.
return if $SIG{__WARN__} eq \&warn_trap;
sub disable {
shift;
- $^W = $old_w;
+ #$^W = $old_w;
return unless $SIG{__WARN__} eq \&warn_trap;
$SIG{__WARN__} = $oldwarn;
$SIG{__DIE__} = $olddie;
sub splainthis {
local $_ = shift;
+ local $\;
### &finish_compilation unless %msg;
s/\.?\n+$//;
my $orig = $_;
# return unless defined;
- if ($exact_duplicate{$_}++) {
- return 1;
- }
s/, <.*?> (?:line|chunk).*$//;
$real = s/(.*?) at .*? (?:line|chunk) \d+.*/$1/;
s/^\((.*)\)$/$1/;
- return 0 unless &transmo;
+ if ($exact_duplicate{$orig}++) {
+ return &transmo;
+ }
+ else {
+ return 0 unless &transmo;
+ }
$orig = shorten($orig);
if ($old_diag{$_}) {
autodescribe();
exists $HTML_Escapes{$1}
? do { $HTML_Escapes{$1} }
: do {
- warn "Unknown escape: $& in $_";
+ warn "Unknown escape: E<$1> in $_";
"E<$1>";
}
}
sub shorten {
my $line = $_[0];
- if (length $line > 79) {
+ if (length($line) > 79 and index($line, "\n") == -1) {
my $space_place = rindex($line, ' ', 79);
if ($space_place != -1) {
substr($line, $space_place, 1) = "\n\t";
}
-# have to do this: RS isn't set until run time, but we're executing at compile time
+# have to do this: RS isn't set until run time, but we're executing at compiletime
$RS = "\n";
1 unless $standalone; # or it'll complain about itself