X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdiagnostics.pm;h=884ea3ca65540e2641f2d6c7569a0b3a84d01cc1;hb=413e5597fa15080977e13a1ad58f104914a75a31;hp=bbae58e12beda14156dea938fc2231067f6a89c2;hpb=4fdae80067c447c675a6ac92c7959d2206e207ba;p=p5sagit%2Fp5-mst-13.2.git diff --git a/lib/diagnostics.pm b/lib/diagnostics.pm old mode 100644 new mode 100755 index bbae58e..884ea3c --- a/lib/diagnostics.pm +++ b/lib/diagnostics.pm @@ -27,7 +27,7 @@ Aa a program: =head2 The C 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. Like the other pragmata, it affects the compilation phase of your program rather than merely the execution phase. @@ -44,13 +44,18 @@ These still go out B. Due to the interaction between runtime and compiletime issues, and because it's probably not a very good idea anyway, you may not use C to turn them off at compiletime. -However, you may control there behaviour at runtime using the +However, you may control their behaviour at runtime using the disable() and enable() methods to turn them off and on respectively. The B<-verbose> flag first prints out the L introduction before 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) 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 Program While apparently a whole nuther program, I is actually nothing @@ -145,7 +150,7 @@ Not being able to say "no diagnostics" is annoying, but may not be insurmountable. The C<-pretty> directive is called too late to affect matters. -You have to to this instead, and I you load the module. +You have to do this instead, and I you load the module. BEGIN { $diagnostics::PRETTY = 1 } @@ -158,43 +163,60 @@ a program named I, you should expect a bit of whimsy. =head1 AUTHOR -Tom Christiansen Ftchrist@mox.perl.comE>, 25 June 1995. +Tom Christiansen >, 25 June 1995. =cut -require 5.001; -use English; +use strict; +use 5.005_64; use Carp; +our $VERSION = v1.0; +our $DEBUG; +our $VERBOSE; +our $PRETTY; + use Config; +my($privlib, $archlib) = @Config{qw(privlibexp archlibexp)}; if ($^O eq 'VMS') { - $PODFILE = VMS::Filespec::unixify($Config{privlibexp}).'/pod/perldiag.pod'; -} -else { - $PODFILE = $Config{privlibexp} . "/pod/perldiag.pod"; + require VMS::Filespec; + $privlib = VMS::Filespec::unixify($privlib); + $archlib = VMS::Filespec::unixify($archlib); } +my @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"; +(my $PODFILE) = ((grep { -e } @trypod), $trypod[$#trypod])[0]; $DEBUG ||= 0; my $WHOAMI = ref bless []; # nobody's business, prolly not even mine -$OUTPUT_AUTOFLUSH = 1; - +local $| = 1; local $_; +my $standalone; +my(%HTML_2_Troff, %HTML_2_Latin_1, %HTML_2_ASCII_7); + CONFIG: { - $opt_p = $opt_d = $opt_v = $opt_f = ''; - %HTML_2_Troff = %HTML_2_Latin_1 = %HTML_2_ASCII_7 = (); - %exact_duplicate = (); + our $opt_p = our $opt_d = our $opt_v = our $opt_f = ''; - unless (caller) { + 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; $PRETTY = $opt_p; - } + } if (open(POD_DIAG, $PODFILE)) { warn "Happy happy podfile from real $PODFILE\n" if $DEBUG; @@ -203,11 +225,12 @@ CONFIG: { if (caller) { INCPATH: { - for $file ( (map { "$_/$WHOAMI.pm" } @INC), $0) { + for my $file ( (map { "$_/$WHOAMI.pm" } @INC), $0) { warn "Checking $file\n" if $DEBUG; if (open(POD_DIAG, $file)) { while () { - next unless /^__END__\s*# wish diag dbase were more accessible/; + next unless + /^__END__\s*# wish diag dbase were more accessible/; print STDERR "podfile is $file\n" if $DEBUG; last INCPATH; } @@ -256,6 +279,7 @@ if (eof(POD_DIAG)) { # etc ); +our %HTML_Escapes; *HTML_Escapes = do { if ($standalone) { $PRETTY ? \%HTML_2_Latin_1 : \%HTML_2_ASCII_7; @@ -266,20 +290,20 @@ if (eof(POD_DIAG)) { *THITHER = $standalone ? *STDOUT : *STDERR; -$transmo = <) { - #s/(.*)\n//; - #$header = $1; unescape(); if ($PRETTY) { @@ -303,33 +327,40 @@ EOFUNC } s/^/ /gm; $msg{$header} .= $_; + undef $for_item; } next; } - unless ( s/=item (.*)\s*\Z//) { + unless ( s/=item (.*?)\s*\z//) { if ( s/=head1\sDESCRIPTION//) { $msg{$header = 'DESCRIPTION'} = ''; + undef $for_item; } + elsif( s/^=for\s+diagnostics\s*\n(.*?)\s*\z// ) { + $for_item = $1; + } next; } # strip formatting directives in =item line - ($header = $1) =~ s/[A-Z]<(.*?)>/$1/g; + $header = $for_item || $1; + undef $for_item; + $header =~ s/[A-Z]<(.*?)>/$1/g; - if ($header =~ /%[sd]/) { - $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) { + if ($header =~ /%[csd]/) { + my $rhs = my $lhs = $header; + if ($lhs =~ s/(.*?)%d(?!%d)(.*)/\Q$1\E-?\\d+\Q$2\E/g) { $lhs =~ s/\\%s/.*?/g; } else { - # if i had lookbehind negations, i wouldn't have to do this \377 noise + # if i had lookbehind negations, + # i wouldn't have to do this \377 noise $lhs =~ s/(.*?)%s/\Q$1\E.*?\377/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 } + $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"; @@ -350,24 +381,23 @@ EOFUNC print STDERR $transmo if $DEBUG; eval $transmo; die $@ if $@; - $RS = "\n"; -### } +} if ($standalone) { if (!@ARGV and -t STDIN) { print STDERR "$0: Reading from STDIN\n" } - while (defined ($error = <>)) { + while (defined (my $error = <>)) { splainthis($error) || print THITHER $error; } exit; -} else { - $old_w = 0; $oldwarn = ''; $olddie = ''; -} +} + +my $olddie; +my $oldwarn; sub import { shift; - $old_w = $^W; - $^W = 1; # yup, clobbered the global variable; tough, if you - # want diags, you want diags. + $^W = 1; # yup, clobbered the global variable; + # tough, if you want diags, you want diags. return if $SIG{__WARN__} eq \&warn_trap; for (@_) { @@ -401,10 +431,9 @@ sub enable { &import } sub disable { shift; - $^W = $old_w; return unless $SIG{__WARN__} eq \&warn_trap; - $SIG{__WARN__} = $oldwarn; - $SIG{__DIE__} = $olddie; + $SIG{__WARN__} = $oldwarn || ''; + $SIG{__DIE__} = $olddie || ''; } sub warn_trap { @@ -445,19 +474,26 @@ sub death_trap { # into an indirect recursion loop }; +my %exact_duplicate; +my %old_diag; +my $count; +my $wantspace; 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/; + my $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(); @@ -500,7 +536,7 @@ sub unescape { exists $HTML_Escapes{$1} ? do { $HTML_Escapes{$1} } : do { - warn "Unknown escape: $& in $_"; + warn "Unknown escape: E<$1> in $_"; "E<$1>"; } } @@ -519,8 +555,5 @@ sub shorten { } -# have to do this: RS isn't set until run time, but we're executing at compile time -$RS = "\n"; - 1 unless $standalone; # or it'll complain about itself __END__ # wish diag dbase were more accessible