File Coverage

blib/lib/Debug/Show.pm
Criterion Covered Total %
statement 48 49 97.9
branch 5 6 83.3
condition 2 6 33.3
subroutine 10 11 90.9
pod 2 2 100.0
total 67 74 90.5


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Debug::Show - display variables helpfully for debugging
4              
5             =head1 SYNOPSIS
6              
7             use Debug::Show qw(debug=hide); # normally
8             use Debug::Show qw(debug=show); # while debugging
9              
10             debug $foo, $bar->{baz};
11              
12             =head1 DESCRIPTION
13              
14             This module provides a facility for displaying variable values for
15             debugging purposes. Statements in the code determine what values are
16             displayed. Whether the statements actually cause debugging output depends
17             on the manner in which C was invoked, so the debug statements
18             can remain permanently in the code, normally inactive. When inactive,
19             the debug statements impose no runtime overhead.
20              
21             When the debug statements are active, each value displayed is labelled
22             with the expression used to generate it. This saves the bother of
23             manually applying labels.
24              
25             =cut
26              
27             package Debug::Show;
28              
29 2     2   52315 { use 5.006; }
  2         8  
  2         91  
30 2     2   12 use warnings;
  2         3  
  2         67  
31 2     2   11 use strict;
  2         9  
  2         102  
32              
33 2     2   2307 use B::CallChecker 0.000 qw(cv_set_call_checker ck_entersub_args_proto);
  2         50179  
  2         293  
34             BEGIN {
35             # B::Generate provides a broken version of B::COP->warnings, which
36             # makes B::Deparse barf [rt.cpan.org #70396], and of B::SVOP->sv,
37             # which makes B::Concise emit rubbish [rt.cpan.org #70398].
38             # This works around it by restoring the non-broken versions,
39             # provided that B::Generate hasn't already been loaded. If it
40             # was loaded by someone else, better hope they worked around it
41             # the same way.
42 2     2   10 require B;
43 2         5 my $cop_warnings = \&B::COP::warnings;
44 2         6 my $svop_sv = \&B::SVOP::sv;
45 2         1803 require B::Generate;
46 2     2   19 no warnings "redefine";
  2         4  
  2         131  
47 2         7637 *B::COP::warnings = $cop_warnings;
48 2         9 *B::SVOP::sv = $svop_sv;
49 2         114 B::Generate->VERSION(1.33);
50             }
51 2     2   18 use Carp qw(croak);
  2         4  
  2         1845  
52              
53             our $VERSION = "0.000";
54              
55             =head1 FUNCTIONS
56              
57             These functions are not exported in the normal way. See below for how
58             to import. The functions may be referenced directly by fully qualified
59             name (e.g., C).
60              
61             =over
62              
63             =item debug_show(EXPR, ...)
64              
65             Display (via C) the values of all the argument expressions.
66             There may be any number of argument expressions. Each value is deeply
67             serialised (by means of C), and is labelled with source
68             for the expression that evaluated to it (generated by C).
69             All the expresssions are evaluated in scalar context, so say C<\%foo>
70             rather than C<%foo> if you want to display the contents of a hash.
71             The entire display consists of a single line.
72              
73             =cut
74              
75             my $dumper_initialised;
76             sub debug_show {
77 11 100   11 1 9707 unless($dumper_initialised) {
78 1         2848 require Data::Dumper;
79 1         7249 Data::Dumper->VERSION(2.11);
80 1         5 $dumper_initialised = 1;
81             }
82 11         25 my @part = ("###");
83 11         28 while(@_) {
84 14         129 my $label = shift(@_);
85 14         20 my $value = shift(@_);
86 14         224 my $dumper = Data::Dumper->new([$value]);
87 14         705 $dumper->Terse(1);
88 14         1689 $dumper->Indent(0);
89 14         124 $dumper->Useqq(1);
90 14         81 $dumper->Quotekeys(0);
91 14         68 $dumper->Sortkeys(1);
92 14         77 push @part, " ", $label, " = ", $dumper->Dump, ";";
93             }
94 11         339 push @part, "\n";
95 11         73 warn join("", @part);
96             }
97              
98             my $deparser_initialised;
99             cv_set_call_checker(\&debug_show, sub ($$$) {
100             my($entersubop, $namegv, undef) = @_;
101             unless($deparser_initialised) {
102             require B::Compiling;
103             B::Compiling->VERSION(0.01);
104             require B::Deparse;
105             B::Deparse->VERSION(0.64);
106             $deparser_initialised = 1;
107             }
108             my $deparser = B::Deparse->new;
109             # Beware, this knows too much about B::Deparse internals.
110             # Would prefer to have a proper interface to parse ops in
111             # (relative) isolation.
112             $deparser->{curcv} = $entersubop->find_cv;
113             $deparser->{curcop} = B::Compiling::PL_compiling();
114             my $foreop = $entersubop->first;
115             $foreop = $foreop->first if $foreop->sibling->isa("B::NULL");
116             my $n = 0;
117             until((my $argop = $foreop->sibling)->sibling->isa("B::NULL")) {
118             my $expr = eval {
119             local $SIG{__DIE__};
120             # The 50 here is a precedence value. This is a
121             # very high precedence, forcing any non-atomic
122             # expression to be parenthesised.
123             $deparser->indent($deparser->deparse($argop, 50));
124             } || "'???'";
125             print $@ if $@ ne "";
126             $expr =~ s/\n[\t ]*/ /g;
127             my $exprop = B::SVOP->new("const", 0, $expr);
128             $exprop->sibling($argop);
129             $foreop->sibling($exprop);
130             $foreop = $argop;
131             $n++;
132             }
133             return ck_entersub_args_proto($entersubop, $namegv, \("\$\$"x$n));
134             }, \!1);
135              
136             =item debug_hide(EXPR, ...)
137              
138             Do nothing. Calls to this function are excised at compile time, so
139             there is no overhead from evaluating the argument expressions or calling
140             the subroutine.
141              
142             =cut
143              
144 0     0 1 0 sub debug_hide { }
145              
146             cv_set_call_checker(\&debug_hide, sub ($$$) {
147             my($entersubop, undef, undef) = @_;
148             # B::Generate doesn't offer a way to explicitly free ops.
149             # We ought to be able to implicitly free $entersubop via constant
150             # folding, by something like
151             #
152             # return B::LOGOP->new("and", 0,
153             # B::SVOP->new("const", 0, !1),
154             # $entersubop);
155             #
156             # but empirically that causes memory corruption and it's not
157             # clear why. For the time being, leak $entersubop.
158             return B::SVOP->new("const", 0, !1);
159             }, \!1);
160              
161             =back
162              
163             =head1 PACKAGE METHOD
164              
165             This method is meant to be invoked on the C package.
166             It will normally be accessed through the C facility.
167              
168             =over
169              
170             =item Debug::Show->import("debug=show")
171              
172             Puts the subroutine L into the caller's namespace under
173             the name "C".
174              
175             =item Debug::Show->import("debug=hide")
176              
177             Puts the subroutine L into the caller's namespace under
178             the name "C".
179              
180             =cut
181              
182             sub import {
183 2 50 33 2   57 croak "bad importation from $_[0]"
      33        
184             unless @_ == 2 && ref($_[1]) eq "" &&
185             $_[1] =~ /\Adebug=(?:show|hide)\z/;
186 2     2   14 no strict "refs";
  2         5  
  2         247  
187 2 100       10 *{caller(0)."::debug"} =
  2         44  
188             $_[1] eq "debug=show" ? \&debug_show : \&debug_hide;
189             }
190              
191             =back
192              
193             =head1 BUGS
194              
195             The operation of this module depends on L. That module has
196             been found to interact badly with other C modules in some cases.
197             This module includes workarounds for known bugs, but others may lurk.
198              
199             Because the expression source in the output is generated by
200             L, it cannot be expected to match the original source
201             character-for-character. It will normally be equivalent source. In some
202             obscure cases the deparser generates incorrect output; that is a bug
203             in L. The kinds of expression that confuse the deparser
204             are relatively unlikely to occur with expressions being displayed for
205             debugging.
206              
207             The shenanigans that take place with the debug functions at compile time
208             will make L produce incorrect output for the debug statements.
209              
210             When hiding debug output, the ops corresponding to the debug expressions,
211             which ought to be freed, are instead leaked. This is because freeing
212             them has been observed to cause memory corruption. The cause of this
213             is currently unknown. The leakage should have negligible impact, unless
214             debug statements occur in code that is repeatedly generated dynamically.
215              
216             =head1 SEE ALSO
217              
218             L,
219             L
220              
221             =head1 AUTHOR
222              
223             Andrew Main (Zefram)
224              
225             =head1 COPYRIGHT
226              
227             Copyright (C) 2011 Andrew Main (Zefram)
228              
229             =head1 LICENSE
230              
231             This module is free software; you can redistribute it and/or modify it
232             under the same terms as Perl itself.
233              
234             =cut
235              
236             1;