use diagnostics; # compile-time enable use diagnostics -verbose; enable diagnostics; # run-time enable disable diagnostics; # run-time disable
This pragma expands the normal, terse diagnostics and suppresses duplicate warnings. It augments the short versions with the more explicative and endearing descriptions found in Chapter 33. Like other pragmas, it also affects the compilation phase of your program, not just the run phase.
When you use diagnostics
at the start of your
program, this automatically enables Perl's -w
command-line switch by setting $^W
to 1. The
remainder of your whole compilation will then be subject to enhanced
diagnostics. These still go out on STDERR
.
Because of the interaction between run-time and compile-time
issues, and because it's probably not a good idea anyway, you may not
use no diagnostics
to turn them off at compile
time. However, you may control their behavior at run time using the
disable
and enable
methods.
(Make sure you do the use
first, or else you won't
be able to get at the methods.)
The -verbose
flag first prints out the
perldiag manpage's introduction before
any other diagnostics are issued. The
$diagnostics::PRETTY
variable can be set (before
the use
) to generate nicer escape sequences for
pagers like less (1) or
more (1):
BEGIN { $diagnostics::PRETTY = 1 } use diagnostics;
Warnings dispatched from Perl and detected by this pragma are
each displayed only once. This is useful when you're caught in a loop
that's generating the same warning (like uninitialized value) over and
over again. Manually generated warnings, such as those stemming from
calls to warn
or carp
, are
unaffected by this duplicate detection mechanism.
Here are some examples of using the
diagnostics
pragma. The following file is certain
to trigger a few errors at both run time and compile time:
use diagnostics; print NOWHERE "nothing "; print STDERR " This message should be unadorned. "; warn " This is a user warning"; print " DIAGNOSTIC TESTER: Please enter a <CR> here: "; my $a, $b = scalar <STDIN>; print " "; print $x/$y;
Here's the output:
Parentheses missing around "my" list at diagtest line 6 (#1) (W parenthesis) You said something like my $foo, $bar = @_; when you meant my ($foo, $bar) = @_; Remember that "my", "our", and "local" bind tighter than comma. Name "main::NOWHERE" used only once: possible typo at diagtest line 2 (#2) (W once) Typographical errors often show up as unique variable names. If you had a good reason for having a unique name, then just mention it again somehow to suppress the message. The our declaration is provided for this purpose. Name "main::b" used only once: possible typo at diagtest line 6 (#2) Name "main::x" used only once: possible typo at diagtest line 8 (#2) Name "main::y" used only once: possible typo at diagtest line 8 (#2) Filehandle main::NOWHERE never opened at diagtest line 2 (#3) (W unopened) An I/O operation was attempted on a filehandle that was never initialized. You need to do an open() or a socket() call, or call a constructor from the FileHandle package. This message should be unadorned. This is a user warning at diagtest line 4. DIAGNOSTIC TESTER: Please enter a <CR> here: Use of uninitialized value in division (/) at diagtest line 8 (#4) (W uninitialized) An undefined value was used as if it were already defined. It was interpreted as a "" or a 0, but maybe it was a mistake. To suppress this warning assign a defined value to your variables. Illegal division by zero at diagtest line 8 (#5) (F) You tried to divide a number by 0. Either something was wrong in your logic, or you need to put a conditional in to guard against meaningless input. Uncaught exception from user code: Illegal division by zero at diagtest line 8.
Diagnostic messages derive from the
perldiag.pod file. If an extant
$SIG{__WARN__}
handler is discovered, this will
still be honored, but only after the
diagnostics::splainthis
function (the pragma's
$SIG{__WARN__}
interceptor) has had its way with
your warnings. Perl does not currently support stacked handlers, so
this is the best we can do for now. There is a
$diagnostics::DEBUG
variable you may set if you're
desperately curious about what sorts of things are being
intercepted:
BEGIN { $diagnostics::DEBUG = 1 } use diagnostics;