NAME
Devel::DumpTrace - Evaluate and print out each line before it is executed.
VERSION
0.06
SYNOPSIS
perl -d:DumpTrace program.pl
perl -d:DumpTrace=verbose program.pl
perl -d:DumpTrace=quiet program.pl
perl -d:DumpTrace::PPI program.pl
DESCRIPTION
Devel::Trace, this module will cause a message to be printed to standard error for each line of source code that is executed. In addition, this module will attempt to identify variable names in the source code and substitute the values of those variables. In this way you can say the path of execution through your program as well as see the value of your variables at each step of the program.
For example, if your program looks like this:
#!/usr/bin/perl
# a demonstration of Devel::DumpTrace
$a = 1;
$b = 3;
$c = 2 * $a + 7 * $b;
@d = ($a, $b, $c + $b);
then the DumpTrace
output will look like:
$ perl -d:DumpTrace demo.pl
>>>>> demo.pl:3: $a:1 = 1;
>>>>> demo.pl:4: $b:3 = 3;
>>>>> demo.pl:5: $c:23 = 2 * $a:1 + 7 * $b:3;
>>>>> demo.pl:6: @d:(1,3,26) = ($a:1, $b:3, $c:23 + $b:3);
There are also more verbose modes which will produce even more detailed output:
$ perl -d:DumpTrace=verbose demo.pl
>> demo.pl:3:
>>> $a = 1;
>>>>> 1 = 1;
-------------------------------------------
>> demo.pl:4:
>>> $b = 3;
>>>>> 3 = 3;
-------------------------------------------
>> demo.pl:5:
>>> $c = 2 * $a + 7 * $b;
>>>> $c = 2 * 1 + 7 * 3;
>>>>> 23 = 2 * 1 + 7 * 3;
-------------------------------------------
>> demo.pl:6:
>>> @d = ($a, $b, $c + $b);
>>>> @d = (1, 3, 23 + 3);
>>>>> (1,3,26) = (1, 3, 23 + 3);
-------------------------------------------
See $Devel::DumpTrace::TRACE
under the "VARIABLES" section for more details about the different levels of verbosity.
There is also a Devel::DumpTrace::PPI module in this distribution which relies on PPI to understand the source code.
See the "BUGS AND LIMITATIONS" section for important, er, limitations of this module.
SUBROUTINES/METHODS
None of interest.
VARIABLES
$Devel::DumpTrace::TRACE
Controls whether and how much output is produced by this module. Setting $Devel::DumpTrace::TRACE
to zero will disable the module. Since this module can produce a lot of output and has other overhead that can considerably slow down your program, you may find it useful to toggle this variable for critical sections of your code rather than leave it set for the entire program. For example:
BEGIN { $Devel::DumpTrace::TRACE = 0 }
&some_non_critical_code();
$Devel::DumpTrace::TRACE = 'normal';
&the_critial_code_you_want_to_debug();
$Devel::DumpTrace::TRACE = 0;
&some_more_non_critical_code();
or to enable tracing in a local
block:
{
local $Devel::DumpTrace::TRACE = 1;
&the_critical_code;
}
In general higher values of $Devel::DumpTrace::TRACE
will cause more output to be produced. Let's consider this simple program to see how the different $Devel::DumpTrace::TRACE
settings affect the output:
@a = (1 .. 40);
$b = $a[4];
$Devel::DumpTrace::TRACE
== 1-
is the quietest mode. One line of output for each statement evaluated. The name of each variable in the source code and its value are included in the same line of output. Values of long scalars, long arrays, or long hash tables are heavily abbreviated:
$ perl -d:DumpTrace=1 littledemo.pl >>>>> littledemo.pl:1: @a:(1,2,3,4,5,6,...,40) = (1 .. 40); >>>>> littledemo.pl:2: $b:5 = $a:(1,2,3,4,5,6,...,40)[4];
$Devel::DumpTrace::TRACE
== 2-
uses a single line of output for each statement evaluated. The name of each variable in the source code and its source code are included in the same line of output. Values of long scalar, arrays, and hashes are less heavily abbreviated.
$ perl -I. -d:DumpTrace=2 littledemo.pl >>>>> littledemo.pl:1: @a:(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17, \ 18,19,20,21,22,23,24,25,26,27,...,40) = (1 .. 40); >>>>> littledemo.pl:2: $b:5 = $a:(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \ 16,17,18,19,20,21,22,23,24,25,26,27,...,40)[4];
$Devel::DumpTrace::TRACE
== 3-
produces one line of output for each statement evaluated. The name of each variable in the source code and its source code are included in the same line of output. Values of long scalar, arrays, and hashes are not abbreviated at all. This is the default setting for the module.
$ perl -I. -d:DumpTrace=3 littledemo.pl >>>>> littledemo.pl:1: @a:(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17, \ 18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39, \ 40) = (1 .. 40); >>>>> littledemo.pl:2: $b:5 = $a:(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \ 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37, \ 38,39,40)[4];
$Devel::DumpTrace::TRACE
== 4-
produces up to four lines of output for each statement evaluated:
the source (file and line number) of the statement being evaluated
the origianl source code for the statement being evaluated
a valuation of the code before the statement has been evaluated by the Perl interpreter.
a valuation of the code after the statement has been evaluated by the Perl interpreter
A separator line will also be displayed between statements. Long scalar, arrays, and hashes may be abbreviated. Example output:
$ perl -d:DumpTrace=4 littledemo.pl >> littledemo.pl:1: >>> @a = (1 .. 40); >>>>> (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, \ 21,22,23,24,25,26,27,...,40) = (1 .. 40); ------------------------------------------- >> littledemo.pl:2: >>> $b = $a[4] + $a[5]; >>>> $b = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, \ 20,21,22,23,24,25,26,27,...,40)[4]; >>>>> 5 = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, \ 20,21,22,23,24,25,26,27,...,40)[4]; -------------------------------------------
$Devel::DumpTrace::TRACE
== 5-
Like
$TRACE
4, but long scalars, arrays, and hashes are not abbreviated.$ perl -I. -d:DumpTrace=5 littledemo.pl >> littledemo.pl:1: >>> @a = (1 .. 40); >>>>> (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21, \ 22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40) = (1 .. 40); ------------------------------------------- >> littledemo.pl:2: >>> $b = $a[4] + $a[5]; >>>> $b = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, \ 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40)[4]; >>>>> 5 = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, \ 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40)[4];
As these demos suggest, you can pass the $TRACE
variable through the command line using the syntax -d:DumpTrace=level
. In place of a number, you may also use the keywords quiet
or verbose
which will set the $TRACE
variable to 1 and 5, respectively.
By default Devel::DumpTrace
does not evaluate statements in any "system" modules, which are defined as any module from a file that resides under an absolute path in your system's @INC
list of directories. If the $TRACE
variable is set to a value larger than 100, then this module will drill down into such modules. See also "EXCLUDE_PKG" and "INCLUDE_PKG" for another way to exercise control over what packages this module will explore.
For convenience, the $Devel::DumpTrace::TRACE
variable is aliased to the $Devel::Trace::TRACE
variable. This way you can enable settings in your program that can be used by both Devel::Trace and Devel::DumpTrace
.
$Devel::DumpTrace::XTRACE_FH
By default, all output from the Devel::DumpTrace
module is written to standard error. This behavior can be changed by setting $Devel::DumpTrace::XTRACE_FH
to the desired I/O handle:
BEGIN {
# if Devel::DumpTrace is loaded, direct output to xtrace-output.txt
if ($INC{'Devel/DumpTrace.pm'}) {
open $Devel::DumpTrace::XTRACE_FH, '>', '/path/xtrace-output.txt';
}
}
The output stream for the Devel::DumpTrace
module can also be controlled with the environment variable XTRACE_FH
. If this variable is set to STDOUT
, then output will be directed to standard output. If this variable contains another value that looks like a filename, this module will open a file with that name and write the trace output to that file.
$Devel::DumpTrace::ARRAY_ELEM_SEPARATOR = ','
$Devel::DumpTrace::HASH_ENTRY_SEPARATOR = ';'
$Devel::DumpTrace::HASH_PAIR_SEPARATOR = '=>'
The Devel::DumpTrace
module uses the preceding default values as delimiters when creating string representations of arrays, hashes, and array/hash references. If you wish to use different delimiters for whatever reason (maybe your arrays have a lot of elements with commas in them), you can change these values.
$Devel::DumpTrace::XEVAL_SEPARATOR = ':'
In normal (non-verbose) mode, Devel::DumpTrace
will display this token between the name of a variable and its value (e.g., $c:23
). The default token is a colon (:
), but you may change it by changing the value of the variable $Devel::DumpTrace::XEVAL_SEPARATOR
.
%Devel::DumpTrace::EXCLUDE_PKG, %Devel::DumpTrace::INCLUDE_PKG
Sets of packages that this module will never/always explore. These settings take precedence over the setting of the $Devel::DumpTrace::TRACE
variable, and the settings of %Devel::DumpTrace::INCLUDE_PKG
take precendence over the settings of %Devel::DumpTrace::EXCLUDE_PKG
(that is, a package that is specified in both %EXCLUDE_PKG
and %INCLUDE_PKG
will be included).
CONFIGURATION AND ENVIRONMENT
Devel::DumpTrace
uses the XTRACE_FH
and XTRACE_LEVEL
environment variables to configure some package variables. See "VARIABLES".
INCOMPATIBILITIES
None known.
EXPORT
Nothing is or can be exported from this module.
DIAGNOSTICS
Nothing interesting.
DEPENDENCIES
Devel::DumpTrace
requires the PadWalker and Scalar::Util modules.
BUGS AND LIMITATIONS
Parser limitations
The parser used by this module to identify Perl variables in the source code is quite crude. It is hoped that the parser is "good enough" for a majority of uses for this module; but there are many known cases where the output will be incorrect or misleading, including:
Statements with chained assignments; complex assignment expressions (*)
($a,$b) = ('','bar');
$a = $b = 'foo';
>>>>> 'foo' = 'bar' = 'foo';
$rin=$ein=3;
>> select $rout=$in,undef,$eout=$ein,0;
>>> select $rout=3,undef,undef=3,0;
>>>>> select 3=3,undef,undef=3,0;
Everything to the right of the first assignment operator in a statement is evaluated before the statement is executed.
Multiple statements on one line
$b = 7;
$a=4; $b=++$a;
>>>>> 4 = 4; 7 = 4;
$a=4; $b=++$a;
>>>>> 5 = 4; 5 = 5;
All statements on a line are evaluated, not just the statement currently being executed.
Multiple lines for one statement (*)
$a = ($b + $c # ==> oops, all this module sees is
+ $d + $e); # $a = ($b + $c
Only the first line of code in an expression is evaluated.
String literals that contain variable names (*)
print STDERR "\$x is $x\n"; # ==> print STDERR "\4 is 4\n";
$email = 'mob@cpan.org'; # ==> $email = 'mob().org'
The parser is not sophisticated enough to tell whether a sigil is inside non-interpolated quotes.
Lexical decalaration and assignment in same statement is not evaluated
my $q = 5; # ==> >>>>> my <undef> = 5;
This fails because the module uses a snapshot of the lexical variable pad before the statement is executed. Therefore the pad does not yet contain the variable that is being declared. After execution, the module examines the old snapshot, which still does not contain the new variable.
For some of these limitations, there are easy workarounds (break up chained assignments, put all statements on separate lines, etc.) if you think the extra information provided by this module is worth the effort to make your code more friendly for this module.
Implicit $_
, @_
(*)
It would be nice if this module could detect when Perl was implicitly using some variables and display the implicit variable.
/expression/; # should be $_ =~ /expression/
my $self = shift; # should be my $self = shift @_;
That is not currently a capability of this module.
Special Perl variables are not recognized (*)
$a = join $/, 'foo', 'bar'; # ==> $a = join $/, 'foo', 'bar'
Special variables with pure alphanumeric names like @ARGV
, $_
, and $1
will still be interpolated. Do see "caller" in perlfunc for some important caveats about how @_
is represented by this module.
Displayed value of @_
variable is unreliable
The displayed value of @_
inside a subroutine is subject to some of the issues described in "caller" in perlfunc:
... be aware that setting @DB::args is best effort, intended for
debugging or generating backtraces, and should not be relied upon
... a side effect of the current implementation means that effects
of shift @_ can normally be undone (but not pop @_ or other splicing,
and not if a reference to @_ has been taken, and subject to the caveat
about reallocated elements), so @DB::args is actually a hybrid of the
current state and initial state of @_ . Buyer beware.
That is, the displayed value of @_
inside a subroutine may be corrupted. Different versions of Perl may have different behavior.
(*) - Devel::DumpTrace::PPI uses PPI and can address some of these limitations.
Other bugs or feature requests
Please report any other bugs or feature requests to bug-devel-xtrace at rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Devel-DumpTrace. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Devel::DumpTrace
You can also look for information at:
RT: CPAN's request tracker
AnnoCPAN: Annotated CPAN documentation
CPAN Ratings
Search CPAN
SEE ALSO
perl5db.pl, as used by the Perl debugger.
Devel::DumpTrace::PPI is part of this distribution and provides similar functionality using PPI to parse the source code.
Devel::TraceVars is a very similar effort to Devel::DumpTrace
, but this module handles arrays, hashes, references, objects, lexical our
variables, and addresses more edge cases.
AUTHOR
Marty O'Brien, <mob at cpan.org>
LICENSE AND COPYRIGHT
Copyright 2010-2011 Marty O'Brien.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.