line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test2::Util::Stash; |
2
|
158
|
|
|
158
|
|
1201
|
use strict; |
|
158
|
|
|
|
|
354
|
|
|
158
|
|
|
|
|
4690
|
|
3
|
158
|
|
|
158
|
|
774
|
use warnings; |
|
158
|
|
|
|
|
318
|
|
|
158
|
|
|
|
|
6510
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
our $VERSION = '0.000156'; |
6
|
|
|
|
|
|
|
|
7
|
158
|
|
|
158
|
|
932
|
use Carp qw/croak/; |
|
158
|
|
|
|
|
307
|
|
|
158
|
|
|
|
|
6721
|
|
8
|
158
|
|
|
158
|
|
992
|
use B; |
|
158
|
|
|
|
|
565
|
|
|
158
|
|
|
|
|
12110
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our @EXPORT_OK = qw{ |
11
|
|
|
|
|
|
|
get_stash |
12
|
|
|
|
|
|
|
get_glob |
13
|
|
|
|
|
|
|
get_symbol |
14
|
|
|
|
|
|
|
parse_symbol |
15
|
|
|
|
|
|
|
purge_symbol |
16
|
|
|
|
|
|
|
slot_to_sig sig_to_slot |
17
|
|
|
|
|
|
|
}; |
18
|
158
|
|
|
158
|
|
1186
|
use base 'Exporter'; |
|
158
|
|
|
|
|
447
|
|
|
158
|
|
|
|
|
41682
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
my %SIGMAP = ( |
21
|
|
|
|
|
|
|
'&' => 'CODE', |
22
|
|
|
|
|
|
|
'$' => 'SCALAR', |
23
|
|
|
|
|
|
|
'%' => 'HASH', |
24
|
|
|
|
|
|
|
'@' => 'ARRAY', |
25
|
|
|
|
|
|
|
); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my %SLOTMAP = reverse %SIGMAP; |
28
|
|
|
|
|
|
|
|
29
|
19
|
50
|
|
19
|
1
|
102
|
sub slot_to_sig { $SLOTMAP{$_[0]} || croak "unsupported slot: '$_[0]'" } |
30
|
4
|
50
|
|
4
|
1
|
30
|
sub sig_to_slot { $SIGMAP{$_[0]} || croak "unsupported sigil: $_[0]" } |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub get_stash { |
33
|
1054
|
|
33
|
1054
|
1
|
2036
|
my $package = shift || caller; |
34
|
158
|
|
|
158
|
|
1317
|
no strict 'refs'; |
|
158
|
|
|
|
|
488
|
|
|
158
|
|
|
|
|
18149
|
|
35
|
1054
|
|
|
|
|
1398
|
return \%{"${package}\::"}; |
|
1054
|
|
|
|
|
3229
|
|
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub get_glob { |
39
|
1059
|
|
|
1059
|
1
|
2196
|
my $sym = _parse_symbol(scalar(caller), @_); |
40
|
158
|
|
|
158
|
|
1133
|
no strict 'refs'; |
|
158
|
|
|
|
|
352
|
|
|
158
|
|
|
|
|
5761
|
|
41
|
158
|
|
|
158
|
|
1036
|
no warnings 'once'; |
|
158
|
|
|
|
|
454
|
|
|
158
|
|
|
|
|
148148
|
|
42
|
1059
|
|
|
|
|
1575
|
return \*{"$sym->{package}\::$sym->{name}"}; |
|
1059
|
|
|
|
|
3420
|
|
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
58
|
|
|
58
|
1
|
198
|
sub parse_symbol { _parse_symbol(scalar(caller), @_) } |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub _parse_symbol { |
48
|
2149
|
|
|
2149
|
|
3899
|
my ($caller, $symbol, $package) = @_; |
49
|
|
|
|
|
|
|
|
50
|
2149
|
100
|
|
|
|
4174
|
if (ref($symbol)) { |
51
|
1499
|
|
|
|
|
2238
|
my $pkg = $symbol->{package}; |
52
|
|
|
|
|
|
|
|
53
|
1499
|
100
|
100
|
|
|
4332
|
croak "Symbol package ($pkg) and package argument ($package) do not match" |
|
|
|
66
|
|
|
|
|
54
|
|
|
|
|
|
|
if $pkg && $package && $pkg ne $package; |
55
|
|
|
|
|
|
|
|
56
|
1498
|
|
66
|
|
|
3487
|
$symbol->{package} ||= $caller; |
57
|
|
|
|
|
|
|
|
58
|
1498
|
|
|
|
|
2869
|
return $symbol; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
650
|
50
|
|
|
|
1408
|
utf8::downgrade($symbol) if $] == 5.010000; # prevent crash on 5.10.0 |
62
|
650
|
50
|
|
|
|
4446
|
my ($sig, $pkg, $name) = ($symbol =~ m/^(\W?)(.*::)?([^:]+)$/) |
63
|
|
|
|
|
|
|
or croak "Invalid symbol: '$symbol'"; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Normalize package, '::' becomes 'main', 'Foo::' becomes 'Foo' |
66
|
650
|
100
|
|
|
|
1723
|
$pkg = $pkg |
|
|
100
|
|
|
|
|
|
67
|
|
|
|
|
|
|
? $pkg eq '::' |
68
|
|
|
|
|
|
|
? 'main' |
69
|
|
|
|
|
|
|
: substr($pkg, 0, -2) |
70
|
|
|
|
|
|
|
: undef; |
71
|
|
|
|
|
|
|
|
72
|
650
|
100
|
100
|
|
|
1766
|
croak "Symbol package ($pkg) and package argument ($package) do not match" |
|
|
|
66
|
|
|
|
|
73
|
|
|
|
|
|
|
if $pkg && $package && $pkg ne $package; |
74
|
|
|
|
|
|
|
|
75
|
649
|
|
100
|
|
|
2013
|
$sig ||= '&'; |
76
|
649
|
|
33
|
|
|
1664
|
my $type = $SIGMAP{$sig} || croak "unsupported sigil: '$sig'"; |
77
|
|
|
|
|
|
|
|
78
|
649
|
|
66
|
|
|
1521
|
my $real_package = $package || $pkg || $caller; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
return { |
81
|
649
|
|
|
|
|
5268
|
name => $name, |
82
|
|
|
|
|
|
|
sigil => $sig, |
83
|
|
|
|
|
|
|
type => $type, |
84
|
|
|
|
|
|
|
symbol => "${sig}${real_package}::${name}", |
85
|
|
|
|
|
|
|
package => $real_package, |
86
|
|
|
|
|
|
|
}; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub get_symbol { |
90
|
944
|
|
|
944
|
1
|
2200
|
my $sym = _parse_symbol(scalar(caller), @_); |
91
|
|
|
|
|
|
|
|
92
|
944
|
|
|
|
|
1750
|
my $name = $sym->{name}; |
93
|
944
|
|
|
|
|
1403
|
my $type = $sym->{type}; |
94
|
944
|
|
|
|
|
1346
|
my $package = $sym->{package}; |
95
|
944
|
|
|
|
|
1339
|
my $symbol = $sym->{symbol}; |
96
|
|
|
|
|
|
|
|
97
|
944
|
|
|
|
|
1699
|
my $stash = get_stash($package); |
98
|
944
|
100
|
|
|
|
2731
|
return undef unless exists $stash->{$name}; |
99
|
|
|
|
|
|
|
|
100
|
882
|
|
|
|
|
1486
|
my $glob = get_glob($sym); |
101
|
882
|
100
|
100
|
|
|
2061
|
return *{$glob}{$type} if $type ne 'SCALAR' && defined(*{$glob}{$type}); |
|
399
|
|
|
|
|
1853
|
|
|
787
|
|
|
|
|
2413
|
|
102
|
|
|
|
|
|
|
|
103
|
483
|
50
|
|
|
|
889
|
if ($] < 5.010) { |
104
|
0
|
0
|
|
|
|
0
|
return undef unless defined(*{$glob}{$type}); |
|
0
|
|
|
|
|
0
|
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
{ |
107
|
0
|
|
|
|
|
0
|
local ($@, $!); |
|
0
|
|
|
|
|
0
|
|
108
|
0
|
|
|
0
|
|
0
|
local $SIG{__WARN__} = sub { 1 }; |
|
0
|
|
|
|
|
0
|
|
109
|
0
|
0
|
|
|
|
0
|
return *{$glob}{$type} if eval "package $package; my \$y = $symbol; 1"; |
|
0
|
|
|
|
|
0
|
|
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
0
|
0
|
|
|
|
0
|
return undef unless defined *{$glob}{$type}; |
|
0
|
|
|
|
|
0
|
|
113
|
0
|
0
|
|
|
|
0
|
return *{$glob}{$type} if defined ${*{$glob}{$type}}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
114
|
0
|
|
|
|
|
0
|
return undef; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
483
|
|
|
|
|
1566
|
my $sv = B::svref_2object($glob)->SV; |
118
|
483
|
100
|
|
|
|
1699
|
return *{$glob}{$type} if $sv->isa('B::SV'); |
|
99
|
|
|
|
|
288
|
|
119
|
384
|
50
|
|
|
|
875
|
return undef unless $sv->isa('B::SPECIAL'); |
120
|
384
|
50
|
|
|
|
797
|
return *{$glob}{$type} if $B::specialsv_name[$$sv] ne 'Nullsv'; |
|
0
|
|
|
|
|
0
|
|
121
|
384
|
|
|
|
|
768
|
return undef; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub purge_symbol { |
125
|
88
|
|
|
88
|
1
|
452
|
my $sym = _parse_symbol(scalar(caller), @_); |
126
|
|
|
|
|
|
|
|
127
|
88
|
|
|
|
|
159
|
local *GLOBCLONE = *{get_glob($sym)}; |
|
88
|
|
|
|
|
186
|
|
128
|
88
|
|
|
|
|
239
|
delete get_stash($sym->{package})->{$sym->{name}}; |
129
|
88
|
|
|
|
|
216
|
my $new_glob = get_glob($sym); |
130
|
|
|
|
|
|
|
|
131
|
88
|
|
|
|
|
234
|
for my $type (qw/CODE SCALAR HASH ARRAY FORMAT IO/) { |
132
|
528
|
100
|
|
|
|
1070
|
next if $type eq $sym->{type}; |
133
|
440
|
|
|
|
|
1288
|
my $ref = get_symbol({type => $type, name => 'GLOBCLONE', sigil => $SLOTMAP{$type}}, __PACKAGE__); |
134
|
440
|
100
|
|
|
|
1199
|
next unless $ref; |
135
|
21
|
|
|
|
|
44
|
*$new_glob = $ref; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
88
|
|
|
|
|
732
|
return *GLOBCLONE{$sym->{type}}; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
1; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
__END__ |