File Coverage

blib/lib/B/Walker.pm
Criterion Covered Total %
statement 24 89 26.9
branch 0 40 0.0
condition 0 15 0.0
subroutine 8 21 38.1
pod 0 13 0.0
total 32 178 17.9


line stmt bran cond sub pod time code
1             package B::Walker;
2             our $VERSION = 0.11;
3              
4 1     1   19 use 5.006;
  1         3  
  1         39  
5 1     1   5 use strict;
  1         1  
  1         445  
6              
7             require Exporter;
8             our @ISA = qw(Exporter);
9             our @EXPORT_OK = qw(padname padval const_sv walk);
10              
11             our $CV;
12              
13             sub padname ($) {
14 0     0 0   my $targ = shift;
15 0           return $CV->PADLIST->ARRAYelt(0)->ARRAYelt($targ);
16             }
17              
18             sub padval ($) {
19 0     0 0   my $targ = shift;
20 0           return $CV->PADLIST->ARRAYelt(1)->ARRAYelt($targ);
21             }
22              
23             sub const_sv ($) {
24 0     0 0   my $op = shift;
25 0           my $sv = $op->sv;
26 0 0         $sv = padval($op->targ) unless $$sv;
27 0           return $sv;
28             }
29              
30             our $Level = 0;
31             our $Line;
32             our $Sub;
33             our $Opname;
34              
35             our %Ops;
36             our %BlockData;
37              
38             my %startblock = map { $_ => 1 }
39             qw(leave leaveloop leavesub leavesublv leavetry
40             grepwhile mapwhile scope);
41              
42             sub walk_root ($);
43             sub walk_root ($) {
44 0     0 0   my $op = shift;
45 0           my $ref = ref($op);
46 0 0         if ($ref eq "B::COP") {
47 0           $Line = $op->line;
48 0           return;
49             }
50 0           my $name = $op->name;
51 1     1   6 use B qw(ppname);
  1         2  
  1         219  
52 0 0         $name = ppname($op->targ) if $name eq "null";
53 0           local $Level = $Level + 1;
54 0 0         local %BlockData = %BlockData if $startblock{$name};
55 0 0         local $Opname = $name if $Ops{$name};
56 0 0 0       $Ops{$name}->($op) if $Ops{$name} and $Line;
57 0 0         if ($ref eq "B::PMOP") {
58 0           my $root = $op->pmreplroot;
59 0 0 0       if (ref($root) and $root->isa("B::OP")) {
60 0           walk_root($root);
61             }
62             }
63 1     1   6 use B qw(OPf_KIDS);
  1         2  
  1         399  
64 0 0         if ($op->flags & OPf_KIDS) {
65 0           for ($op = $op->first; $$op; $op = $op->sibling) {
66 0           walk_root($op);
67             }
68             }
69             }
70              
71             sub walk_cv ($);
72              
73             sub walk_av ($$) {
74 0     0 0   my ($name, $av) = @_;
75 0 0         return if ref($av) ne "B::AV";
76 0           local $Sub = $name;
77 0           walk_cv($_) for $av->ARRAY;
78             }
79              
80             sub walk_pad ($) {
81 0     0 0   my $pad = shift;
82 0 0         return unless $pad->can("ARRAY");
83 0           walk_av ANON => $pad->ARRAY;
84             }
85              
86             sub walk_cv ($) {
87 0     0 0   my $cv = shift;
88 0 0         return if ref($cv) ne "B::CV";
89 0 0 0       return if $cv->FILE and $cv->FILE ne $0;
90 0           local $CV = $cv;
91 0 0         walk_root($cv->ROOT) if ${$cv->ROOT};
  0            
92 0           walk_pad($cv->PADLIST);
93             }
94              
95             sub walk_blocks () {
96 1     1   5 use B qw(begin_av init_av);
  1         2  
  1         108  
97 0     0 0   walk_av "BEGIN" => begin_av;
98 0           walk_av "INIT" => init_av;
99             }
100              
101             sub walk_main () {
102 1     1   17 use B qw(main_cv main_root);
  1         2  
  1         283  
103 0     0 0   local $Sub = "MAIN";
104 0           local $CV = main_cv;
105 0 0         walk_root(main_root) if ${main_root()};
  0            
106 0           walk_cv(main_cv);
107             }
108              
109             sub walk_gv ($) {
110 0     0 0   my $gv = shift;
111 0           my $cv = $gv->CV;
112 0 0 0       return unless ( $$cv && ref($cv) eq "B::CV" );
113 0 0         return if $cv->XSUB;
114 0           local $Sub = $gv->SAFENAME;
115 0           $Line = $gv->LINE;
116 0           walk_cv($cv);
117             }
118              
119             sub walk_stash ($$);
120             sub walk_stash ($$) { # similar to B::walksymtable
121 0     0 0   my ($symref, $prefix) = @_;
122 0           while (my ($sym) = each %$symref) {
123 1     1   6 no strict 'refs';
  1         2  
  1         106  
124 0           my $fullname = "*main::". $prefix . $sym;
125 0 0         if ($sym =~ /::\z/) {
126 0           $sym = $prefix . $sym;
127 0 0 0       walk_stash(\%$fullname, $sym)
128             if $sym ne "main::" && $sym ne "::";
129             }
130             else {
131 1     1   6 use B qw(svref_2object);
  1         2  
  1         181  
132 0 0         walk_gv(svref_2object(\*$fullname))
133             if *$fullname{CODE};
134             }
135             }
136             }
137              
138             sub walk_subs () {
139 0     0 0   walk_stash \%::, '';
140             }
141              
142             sub walk () {
143 0     0 0   walk_blocks();
144 0           walk_main();
145 0           walk_subs();
146             }
147              
148             1;
149              
150             __END__