0e1d22444e638c1dd059e1cbde4c0b8847dd26b2
[p5sagit/p5-mst-13.2.git] / ext / B / B / Debug.pm
1 package B::Debug;
2
3 our $VERSION = '1.04';
4
5 use strict;
6 use B qw(peekop class walkoptree walkoptree_exec
7          main_start main_root cstring sv_undef @specialsv_name);
8
9 my %done_gv;
10
11 sub B::OP::debug {
12     my ($op) = @_;
13     printf <<'EOT', class($op), $$op, ${$op->next}, ${$op->sibling}, $op->ppaddr, $op->targ, $op->type;
14 %s (0x%lx)
15         op_next         0x%x
16         op_sibling      0x%x
17         op_ppaddr       %s
18         op_targ         %d
19         op_type         %d
20 EOT
21     if ($] > 5.009) {
22         printf <<'EOT', $op->opt, $op->static;
23         op_opt          %d
24         op_static       %d
25 EOT
26     } else {
27         printf <<'EOT', $op->seq;
28         op_seq          %d
29 EOT
30     }
31     printf <<'EOT', $op->flags, $op->private;
32         op_flags        %d
33         op_private      %d
34 EOT
35 }
36
37 sub B::UNOP::debug {
38     my ($op) = @_;
39     $op->B::OP::debug();
40     printf "\top_first\t0x%x\n", ${$op->first};
41 }
42
43 sub B::BINOP::debug {
44     my ($op) = @_;
45     $op->B::UNOP::debug();
46     printf "\top_last\t\t0x%x\n", ${$op->last};
47 }
48
49 sub B::LOOP::debug {
50     my ($op) = @_;
51     $op->B::BINOP::debug();
52     printf <<'EOT', ${$op->redoop}, ${$op->nextop}, ${$op->lastop};
53         op_redoop       0x%x
54         op_nextop       0x%x
55         op_lastop       0x%x
56 EOT
57 }
58
59 sub B::LOGOP::debug {
60     my ($op) = @_;
61     $op->B::UNOP::debug();
62     printf "\top_other\t0x%x\n", ${$op->other};
63 }
64
65 sub B::LISTOP::debug {
66     my ($op) = @_;
67     $op->B::BINOP::debug();
68     printf "\top_children\t%d\n", $op->children;
69 }
70
71 sub B::PMOP::debug {
72     my ($op) = @_;
73     $op->B::LISTOP::debug();
74     printf "\top_pmreplroot\t0x%x\n", ${$op->pmreplroot};
75     printf "\top_pmreplstart\t0x%x\n", ${$op->pmreplstart};
76     printf "\top_pmnext\t0x%x\n", ${$op->pmnext};
77     printf "\top_pmregexp->precomp\t%s\n", cstring($op->precomp);
78     printf "\top_pmflags\t0x%x\n", $op->pmflags;
79     $op->pmreplroot->debug;
80 }
81
82 sub B::COP::debug {
83     my ($op) = @_;
84     $op->B::OP::debug();
85     my $cop_io = class($op->io) eq 'SPECIAL' ? '' : $op->io->as_string;
86     printf <<'EOT', $op->label, $op->stashpv, $op->file, $op->cop_seq, $op->arybase, $op->line, ${$op->warnings}, cstring($cop_io);
87         cop_label       %s
88         cop_stashpv     %s
89         cop_file        %s
90         cop_seq         %d
91         cop_arybase     %d
92         cop_line        %d
93         cop_warnings    0x%x
94         cop_io          %s
95 EOT
96 }
97
98 sub B::SVOP::debug {
99     my ($op) = @_;
100     $op->B::OP::debug();
101     printf "\top_sv\t\t0x%x\n", ${$op->sv};
102     $op->sv->debug;
103 }
104
105 sub B::PVOP::debug {
106     my ($op) = @_;
107     $op->B::OP::debug();
108     printf "\top_pv\t\t%s\n", cstring($op->pv);
109 }
110
111 sub B::PADOP::debug {
112     my ($op) = @_;
113     $op->B::OP::debug();
114     printf "\top_padix\t\t%ld\n", $op->padix;
115 }
116
117 sub B::NULL::debug {
118     my ($sv) = @_;
119     if ($$sv == ${sv_undef()}) {
120         print "&sv_undef\n";
121     } else {
122         printf "NULL (0x%x)\n", $$sv;
123     }
124 }
125
126 sub B::SV::debug {
127     my ($sv) = @_;
128     if (!$$sv) {
129         print class($sv), " = NULL\n";
130         return;
131     }
132     printf <<'EOT', class($sv), $$sv, $sv->REFCNT, $sv->FLAGS;
133 %s (0x%x)
134         REFCNT          %d
135         FLAGS           0x%x
136 EOT
137 }
138
139 sub B::RV::debug {
140     my ($rv) = @_;
141     B::SV::debug($rv);
142     printf <<'EOT', ${$rv->RV};
143         RV              0x%x
144 EOT
145     $rv->RV->debug;
146 }
147
148 sub B::PV::debug {
149     my ($sv) = @_;
150     $sv->B::SV::debug();
151     my $pv = $sv->PV();
152     printf <<'EOT', cstring($pv), length($pv);
153         xpv_pv          %s
154         xpv_cur         %d
155 EOT
156 }
157
158 sub B::IV::debug {
159     my ($sv) = @_;
160     $sv->B::SV::debug();
161     printf "\txiv_iv\t\t%d\n", $sv->IV;
162 }
163
164 sub B::NV::debug {
165     my ($sv) = @_;
166     $sv->B::IV::debug();
167     printf "\txnv_nv\t\t%s\n", $sv->NV;
168 }
169
170 sub B::PVIV::debug {
171     my ($sv) = @_;
172     $sv->B::PV::debug();
173     printf "\txiv_iv\t\t%d\n", $sv->IV;
174 }
175
176 sub B::PVNV::debug {
177     my ($sv) = @_;
178     $sv->B::PVIV::debug();
179     printf "\txnv_nv\t\t%s\n", $sv->NV;
180 }
181
182 sub B::PVLV::debug {
183     my ($sv) = @_;
184     $sv->B::PVNV::debug();
185     printf "\txlv_targoff\t%d\n", $sv->TARGOFF;
186     printf "\txlv_targlen\t%u\n", $sv->TARGLEN;
187     printf "\txlv_type\t%s\n", cstring(chr($sv->TYPE));
188 }
189
190 sub B::BM::debug {
191     my ($sv) = @_;
192     $sv->B::PVNV::debug();
193     printf "\txbm_useful\t%d\n", $sv->USEFUL;
194     printf "\txbm_previous\t%u\n", $sv->PREVIOUS;
195     printf "\txbm_rare\t%s\n", cstring(chr($sv->RARE));
196 }
197
198 sub B::CV::debug {
199     my ($sv) = @_;
200     $sv->B::PVNV::debug();
201     my ($stash) = $sv->STASH;
202     my ($start) = $sv->START;
203     my ($root) = $sv->ROOT;
204     my ($padlist) = $sv->PADLIST;
205     my ($file) = $sv->FILE;
206     my ($gv) = $sv->GV;
207     printf <<'EOT', $$stash, $$start, $$root, $$gv, $file, $sv->DEPTH, $padlist, ${$sv->OUTSIDE}, $sv->OUTSIDE_SEQ;
208         STASH           0x%x
209         START           0x%x
210         ROOT            0x%x
211         GV              0x%x
212         FILE            %s
213         DEPTH           %d
214         PADLIST         0x%x
215         OUTSIDE         0x%x
216         OUTSIDE_SEQ     %d
217 EOT
218     $start->debug if $start;
219     $root->debug if $root;
220     $gv->debug if $gv;
221     $padlist->debug if $padlist;
222 }
223
224 sub B::AV::debug {
225     my ($av) = @_;
226     $av->B::SV::debug;
227     my(@array) = $av->ARRAY;
228     print "\tARRAY\t\t(", join(", ", map("0x" . $$_, @array)), ")\n";
229     printf <<'EOT', scalar(@array), $av->MAX, $av->OFF;
230         FILL            %d
231         MAX             %d
232         OFF             %d
233 EOT
234     printf <<'EOT', $av->AvFLAGS if $] < 5.009;
235         AvFLAGS         %d
236 EOT
237 }
238
239 sub B::GV::debug {
240     my ($gv) = @_;
241     if ($done_gv{$$gv}++) {
242         printf "GV %s::%s\n", $gv->STASH->NAME, $gv->SAFENAME;
243         return;
244     }
245     my ($sv) = $gv->SV;
246     my ($av) = $gv->AV;
247     my ($cv) = $gv->CV;
248     $gv->B::SV::debug;
249     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;
250         NAME            %s
251         STASH           %s (0x%x)
252         SV              0x%x
253         GvREFCNT        %d
254         FORM            0x%x
255         AV              0x%x
256         HV              0x%x
257         EGV             0x%x
258         CV              0x%x
259         CVGEN           %d
260         LINE            %d
261         FILE            %s
262         GvFLAGS         0x%x
263 EOT
264     $sv->debug if $sv;
265     $av->debug if $av;
266     $cv->debug if $cv;
267 }
268
269 sub B::SPECIAL::debug {
270     my $sv = shift;
271     print $specialsv_name[$$sv], "\n";
272 }
273
274 sub compile {
275     my $order = shift;
276     B::clearsym();
277     if ($order && $order eq "exec") {
278         return sub { walkoptree_exec(main_start, "debug") }
279     } else {
280         return sub { walkoptree(main_root, "debug") }
281     }
282 }
283
284 1;
285
286 __END__
287
288 =head1 NAME
289
290 B::Debug - Walk Perl syntax tree, printing debug info about ops
291
292 =head1 SYNOPSIS
293
294         perl -MO=Debug[,OPTIONS] foo.pl
295
296 =head1 DESCRIPTION
297
298 See F<ext/B/README>.
299
300 =head1 AUTHOR
301
302 Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
303
304 =cut