Commit | Line | Data |
a798dbf2 |
1 | package B::Debug; |
28b605d8 |
2 | |
7cd4b8a8 |
3 | our $VERSION = '1.11'; |
28b605d8 |
4 | |
a798dbf2 |
5 | use strict; |
7cd4b8a8 |
6 | require 5.006; |
a798dbf2 |
7 | use B qw(peekop class walkoptree walkoptree_exec |
93f00e88 |
8 | main_start main_root cstring sv_undef); |
7cd4b8a8 |
9 | use Config; |
10 | my (@optype, @specialsv_name); |
93f00e88 |
11 | require B; |
12 | if ($] < 5.009) { |
13 | require B::Asmdata; |
14 | B::Asmdata->import qw(@optype @specialsv_name); |
15 | } else { |
16 | B->import qw(@optype @specialsv_name); |
17 | } |
18 | my $have_B_Flags; |
7cd4b8a8 |
19 | if (!$ENV{PERL_CORE}){ # avoid CORE test crashes |
20 | eval { require B::Flags and $have_B_Flags++ }; |
c1307613 |
21 | } |
a798dbf2 |
22 | my %done_gv; |
23 | |
c1307613 |
24 | sub _printop { |
25 | my $op = shift; |
26 | my $addr = ${$op} ? $op->ppaddr : ''; |
27 | $addr =~ s/^PL_ppaddr// if $addr; |
28 | return sprintf "0x%x %s %s", ${$op}, ${$op} ? class($op) : '', $addr; |
29 | } |
30 | |
a798dbf2 |
31 | sub B::OP::debug { |
32 | my ($op) = @_; |
c1307613 |
33 | printf <<'EOT', class($op), $$op, $op->ppaddr, _printop($op->next), _printop($op->sibling), $op->targ, $op->type; |
a798dbf2 |
34 | %s (0x%lx) |
a798dbf2 |
35 | op_ppaddr %s |
c1307613 |
36 | op_next %s |
37 | op_sibling %s |
a798dbf2 |
38 | op_targ %d |
39 | op_type %d |
7252851f |
40 | EOT |
7cd4b8a8 |
41 | if ($] > 5.009) { |
85594c31 |
42 | printf <<'EOT', $op->opt; |
2814eb74 |
43 | op_opt %d |
7252851f |
44 | EOT |
45 | } else { |
46 | printf <<'EOT', $op->seq; |
47 | op_seq %d |
48 | EOT |
49 | } |
93f00e88 |
50 | if ($have_B_Flags) { |
51 | printf <<'EOT', $op->flags, $op->flagspv, $op->private, $op->privatepv; |
52 | op_flags %d %s |
53 | op_private %d %s |
54 | EOT |
55 | } else { |
56 | printf <<'EOT', $op->flags, $op->private; |
a798dbf2 |
57 | op_flags %d |
58 | op_private %d |
59 | EOT |
93f00e88 |
60 | } |
a798dbf2 |
61 | } |
62 | |
63 | sub B::UNOP::debug { |
64 | my ($op) = @_; |
65 | $op->B::OP::debug(); |
c1307613 |
66 | printf "\top_first\t%s\n", _printop($op->first); |
a798dbf2 |
67 | } |
68 | |
69 | sub B::BINOP::debug { |
70 | my ($op) = @_; |
71 | $op->B::UNOP::debug(); |
c1307613 |
72 | printf "\top_last \t%s\n", _printop($op->last); |
a798dbf2 |
73 | } |
74 | |
ee3e756d |
75 | sub B::LOOP::debug { |
76 | my ($op) = @_; |
77 | $op->B::BINOP::debug(); |
c1307613 |
78 | printf <<'EOT', _printop($op->redoop), _printop($op->nextop), _printop($op->lastop); |
79 | op_redoop %s |
80 | op_nextop %s |
81 | op_lastop %s |
ee3e756d |
82 | EOT |
83 | } |
84 | |
a798dbf2 |
85 | sub B::LOGOP::debug { |
86 | my ($op) = @_; |
87 | $op->B::UNOP::debug(); |
c1307613 |
88 | printf "\top_other\t%s\n", _printop($op->other); |
a798dbf2 |
89 | } |
90 | |
a798dbf2 |
91 | sub B::LISTOP::debug { |
92 | my ($op) = @_; |
93 | $op->B::BINOP::debug(); |
c03c2844 |
94 | printf "\top_children\t%d\n", $op->children; |
a798dbf2 |
95 | } |
96 | |
97 | sub B::PMOP::debug { |
98 | my ($op) = @_; |
99 | $op->B::LISTOP::debug(); |
7cd4b8a8 |
100 | printf "\top_pmreplroot\t0x%x\n", $] < 5.008 ? ${$op->pmreplroot} : $op->pmreplroot; |
a798dbf2 |
101 | printf "\top_pmreplstart\t0x%x\n", ${$op->pmreplstart}; |
7cd4b8a8 |
102 | printf "\top_pmnext\t0x%x\n", ${$op->pmnext} if $] < 5.009005; |
103 | if ($Config{'useithreads'}) { |
c1307613 |
104 | printf "\top_pmstashpv\t%s\n", cstring($op->pmstashpv); |
105 | printf "\top_pmoffset\t%d\n", $op->pmoffset; |
106 | } else { |
107 | printf "\top_pmstash\t%s\n", cstring($op->pmstash); |
108 | } |
93f00e88 |
109 | printf "\top_precomp\t%s\n", cstring($op->precomp); |
a798dbf2 |
110 | printf "\top_pmflags\t0x%x\n", $op->pmflags; |
7cd4b8a8 |
111 | printf "\top_reflags\t0x%x\n", $op->reflags if $] >= 5.009; |
112 | printf "\top_pmpermflags\t0x%x\n", $op->pmpermflags if $] < 5.009; |
113 | printf "\top_pmdynflags\t0x%x\n", $op->pmdynflags if $] < 5.009; |
114 | $op->pmreplroot->debug if $] < 5.008; |
a798dbf2 |
115 | } |
116 | |
117 | sub B::COP::debug { |
118 | my ($op) = @_; |
119 | $op->B::OP::debug(); |
6e6a1aef |
120 | my $cop_io = class($op->io) eq 'SPECIAL' ? '' : $op->io->as_string; |
127212b2 |
121 | printf <<'EOT', $op->label, $op->stashpv, $op->file, $op->cop_seq, $op->arybase, $op->line, ${$op->warnings}, cstring($cop_io); |
c1307613 |
122 | cop_label "%s" |
123 | cop_stashpv "%s" |
124 | cop_file "%s" |
a798dbf2 |
125 | cop_seq %d |
126 | cop_arybase %d |
127 | cop_line %d |
b295d113 |
128 | cop_warnings 0x%x |
6e6a1aef |
129 | cop_io %s |
a798dbf2 |
130 | EOT |
a798dbf2 |
131 | } |
132 | |
133 | sub B::SVOP::debug { |
134 | my ($op) = @_; |
135 | $op->B::OP::debug(); |
136 | printf "\top_sv\t\t0x%x\n", ${$op->sv}; |
137 | $op->sv->debug; |
138 | } |
139 | |
140 | sub B::PVOP::debug { |
141 | my ($op) = @_; |
142 | $op->B::OP::debug(); |
3267896c |
143 | printf "\top_pv\t\t%s\n", cstring($op->pv); |
a798dbf2 |
144 | } |
145 | |
7934575e |
146 | sub B::PADOP::debug { |
a798dbf2 |
147 | my ($op) = @_; |
148 | $op->B::OP::debug(); |
c1307613 |
149 | printf "\top_padix\t%ld\n", $op->padix; |
a798dbf2 |
150 | } |
151 | |
a798dbf2 |
152 | sub B::NULL::debug { |
153 | my ($sv) = @_; |
154 | if ($$sv == ${sv_undef()}) { |
155 | print "&sv_undef\n"; |
156 | } else { |
157 | printf "NULL (0x%x)\n", $$sv; |
158 | } |
159 | } |
160 | |
161 | sub B::SV::debug { |
162 | my ($sv) = @_; |
163 | if (!$$sv) { |
164 | print class($sv), " = NULL\n"; |
165 | return; |
166 | } |
167 | printf <<'EOT', class($sv), $$sv, $sv->REFCNT, $sv->FLAGS; |
168 | %s (0x%x) |
169 | REFCNT %d |
170 | FLAGS 0x%x |
171 | EOT |
172 | } |
173 | |
3267896c |
174 | sub B::RV::debug { |
175 | my ($rv) = @_; |
176 | B::SV::debug($rv); |
177 | printf <<'EOT', ${$rv->RV}; |
178 | RV 0x%x |
179 | EOT |
180 | $rv->RV->debug; |
181 | } |
182 | |
a798dbf2 |
183 | sub B::PV::debug { |
184 | my ($sv) = @_; |
185 | $sv->B::SV::debug(); |
186 | my $pv = $sv->PV(); |
187 | printf <<'EOT', cstring($pv), length($pv); |
188 | xpv_pv %s |
189 | xpv_cur %d |
190 | EOT |
191 | } |
192 | |
193 | sub B::IV::debug { |
194 | my ($sv) = @_; |
195 | $sv->B::SV::debug(); |
196 | printf "\txiv_iv\t\t%d\n", $sv->IV; |
197 | } |
198 | |
199 | sub B::NV::debug { |
200 | my ($sv) = @_; |
201 | $sv->B::IV::debug(); |
202 | printf "\txnv_nv\t\t%s\n", $sv->NV; |
203 | } |
204 | |
205 | sub B::PVIV::debug { |
206 | my ($sv) = @_; |
207 | $sv->B::PV::debug(); |
208 | printf "\txiv_iv\t\t%d\n", $sv->IV; |
209 | } |
210 | |
211 | sub B::PVNV::debug { |
212 | my ($sv) = @_; |
213 | $sv->B::PVIV::debug(); |
214 | printf "\txnv_nv\t\t%s\n", $sv->NV; |
215 | } |
216 | |
217 | sub B::PVLV::debug { |
218 | my ($sv) = @_; |
219 | $sv->B::PVNV::debug(); |
220 | printf "\txlv_targoff\t%d\n", $sv->TARGOFF; |
221 | printf "\txlv_targlen\t%u\n", $sv->TARGLEN; |
222 | printf "\txlv_type\t%s\n", cstring(chr($sv->TYPE)); |
223 | } |
224 | |
225 | sub B::BM::debug { |
226 | my ($sv) = @_; |
227 | $sv->B::PVNV::debug(); |
228 | printf "\txbm_useful\t%d\n", $sv->USEFUL; |
229 | printf "\txbm_previous\t%u\n", $sv->PREVIOUS; |
230 | printf "\txbm_rare\t%s\n", cstring(chr($sv->RARE)); |
231 | } |
232 | |
233 | sub B::CV::debug { |
234 | my ($sv) = @_; |
235 | $sv->B::PVNV::debug(); |
236 | my ($stash) = $sv->STASH; |
237 | my ($start) = $sv->START; |
238 | my ($root) = $sv->ROOT; |
239 | my ($padlist) = $sv->PADLIST; |
57843af0 |
240 | my ($file) = $sv->FILE; |
a798dbf2 |
241 | my ($gv) = $sv->GV; |
a3985cdc |
242 | printf <<'EOT', $$stash, $$start, $$root, $$gv, $file, $sv->DEPTH, $padlist, ${$sv->OUTSIDE}, $sv->OUTSIDE_SEQ; |
a798dbf2 |
243 | STASH 0x%x |
244 | START 0x%x |
245 | ROOT 0x%x |
246 | GV 0x%x |
57843af0 |
247 | FILE %s |
a798dbf2 |
248 | DEPTH %d |
7e107e90 |
249 | PADLIST 0x%x |
a798dbf2 |
250 | OUTSIDE 0x%x |
a3985cdc |
251 | OUTSIDE_SEQ %d |
a798dbf2 |
252 | EOT |
253 | $start->debug if $start; |
254 | $root->debug if $root; |
255 | $gv->debug if $gv; |
a798dbf2 |
256 | $padlist->debug if $padlist; |
257 | } |
258 | |
259 | sub B::AV::debug { |
260 | my ($av) = @_; |
261 | $av->B::SV::debug; |
93f00e88 |
262 | # tied arrays may leave out FETCHSIZE |
263 | my (@array) = eval { $av->ARRAY; }; |
a798dbf2 |
264 | print "\tARRAY\t\t(", join(", ", map("0x" . $$_, @array)), ")\n"; |
93f00e88 |
265 | my $fill = eval { scalar(@array) }; |
7cd4b8a8 |
266 | if ($Config{'useithreads'}) { |
93f00e88 |
267 | printf <<'EOT', $fill, $av->MAX, $av->OFF; |
7e107e90 |
268 | FILL %d |
a798dbf2 |
269 | MAX %d |
270 | OFF %d |
a798dbf2 |
271 | EOT |
93f00e88 |
272 | } else { |
273 | printf <<'EOT', $fill, $av->MAX; |
274 | FILL %d |
275 | MAX %d |
276 | EOT |
277 | } |
7cd4b8a8 |
278 | printf <<'EOT', $av->AvFLAGS if $] < 5.009; |
bb7c595b |
279 | AvFLAGS %d |
280 | EOT |
a798dbf2 |
281 | } |
7e107e90 |
282 | |
a798dbf2 |
283 | sub B::GV::debug { |
284 | my ($gv) = @_; |
285 | if ($done_gv{$$gv}++) { |
002b978b |
286 | printf "GV %s::%s\n", $gv->STASH->NAME, $gv->SAFENAME; |
a798dbf2 |
287 | return; |
288 | } |
289 | my ($sv) = $gv->SV; |
290 | my ($av) = $gv->AV; |
291 | my ($cv) = $gv->CV; |
292 | $gv->B::SV::debug; |
002b978b |
293 | printf <<'EOT', $gv->SAFENAME, $gv->STASH->NAME, $gv->STASH, $$sv, $gv->GvREFCNT, $gv->FORM, $$av, ${$gv->HV}, ${$gv->EGV}, $$cv, $gv->CVGEN, $gv->LINE, $gv->FILE, $gv->GvFLAGS; |
a798dbf2 |
294 | NAME %s |
295 | STASH %s (0x%x) |
296 | SV 0x%x |
297 | GvREFCNT %d |
298 | FORM 0x%x |
299 | AV 0x%x |
300 | HV 0x%x |
301 | EGV 0x%x |
302 | CV 0x%x |
303 | CVGEN %d |
304 | LINE %d |
b195d487 |
305 | FILE %s |
a798dbf2 |
306 | GvFLAGS 0x%x |
307 | EOT |
308 | $sv->debug if $sv; |
309 | $av->debug if $av; |
310 | $cv->debug if $cv; |
311 | } |
312 | |
313 | sub B::SPECIAL::debug { |
314 | my $sv = shift; |
315 | print $specialsv_name[$$sv], "\n"; |
316 | } |
317 | |
318 | sub compile { |
319 | my $order = shift; |
2b8dc4d2 |
320 | B::clearsym(); |
7ebf56ae |
321 | if ($order && $order eq "exec") { |
a798dbf2 |
322 | return sub { walkoptree_exec(main_start, "debug") } |
323 | } else { |
324 | return sub { walkoptree(main_root, "debug") } |
325 | } |
326 | } |
327 | |
328 | 1; |
7f20e9dd |
329 | |
330 | __END__ |
331 | |
332 | =head1 NAME |
333 | |
334 | B::Debug - Walk Perl syntax tree, printing debug info about ops |
335 | |
336 | =head1 SYNOPSIS |
337 | |
338 | perl -MO=Debug[,OPTIONS] foo.pl |
339 | |
340 | =head1 DESCRIPTION |
341 | |
c1307613 |
342 | See F<ext/B/README> and the newer L<B::Concise>, L<B::Terse>. |
343 | |
344 | =head1 OPTIONS |
345 | |
346 | With option -exec, walks tree in execute order, |
347 | otherwise in basic order. |
7f20e9dd |
348 | |
93f00e88 |
349 | =head1 Changes |
350 | |
7cd4b8a8 |
351 | 1.11 2008-07-14 rurban |
352 | avoid B::Flags in CORE tests not to crash on old XS in @INC |
353 | |
354 | 1.10 2008-06-28 rurban |
355 | require 5.006; Test::More not possible in 5.00505 |
356 | our => my |
0106d518 |
357 | |
7cd4b8a8 |
358 | 1.09 2008-06-18 rurban |
359 | minor META.yml syntax fix |
360 | 5.8.0 ending nextstate test failure: be more tolerant |
361 | PREREQ_PM Test::More |
362 | |
363 | 1.08 2008-06-17 rurban |
364 | support 5.00558 - 5.6.2 |
365 | |
366 | 1.07 2008-06-16 rurban |
367 | debug.t: fix strawberry perl quoting issue |
368 | |
369 | 1.06 2008-06-11 rurban |
93f00e88 |
370 | added B::Flags output |
371 | dual-life CPAN as B-Debug-1.06 and CORE |
372 | protect scalar(@array) if tied arrays leave out FETCHSIZE |
373 | |
374 | 1.05_03 2008-04-16 rurban |
375 | ithread fixes in B::AV |
376 | B-C-1.04_?? |
377 | |
378 | B-C-1.04_09 2008-02-24 rurban |
379 | support 5.8 (import Asmdata) |
380 | |
381 | 1.05_02 2008-02-21 rurban |
382 | added _printop |
383 | B-C-1.04_08 and CORE |
384 | |
385 | 1.05_01 2008-02-05 rurban |
386 | 5.10 fix for op->seq |
387 | B-C-1.04_04 |
388 | |
7f20e9dd |
389 | =head1 AUTHOR |
390 | |
391 | Malcolm Beattie, C<mbeattie@sable.ox.ac.uk> |
93f00e88 |
392 | Reini Urban C<rurban@cpan.org> |
7f20e9dd |
393 | |
7cd4b8a8 |
394 | =head1 LICENSE |
395 | |
396 | Copyright (c) 1996, 1997 Malcolm Beattie |
397 | Copyright (c) 2008 Reini Urban |
398 | |
399 | This program is free software; you can redistribute it and/or modify |
400 | it under the terms of either: |
401 | |
402 | a) the GNU General Public License as published by the Free |
403 | Software Foundation; either version 1, or (at your option) any |
404 | later version, or |
405 | |
406 | b) the "Artistic License" which comes with this kit. |
407 | |
408 | This program is distributed in the hope that it will be useful, |
409 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
410 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either |
411 | the GNU General Public License or the Artistic License for more details. |
412 | |
413 | You should have received a copy of the Artistic License with this kit, |
414 | in the file named "Artistic". If not, you can get one from the Perl |
415 | distribution. You should also have received a copy of the GNU General |
416 | Public License, in the file named "Copying". If not, you can get one |
417 | from the Perl distribution or else write to the Free Software Foundation, |
418 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. |
419 | |
7f20e9dd |
420 | =cut |