line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test2::Util::Stash; |
2
|
158
|
|
|
158
|
|
1045
|
use strict; |
|
158
|
|
|
|
|
338
|
|
|
158
|
|
|
|
|
4488
|
|
3
|
158
|
|
|
158
|
|
955
|
use warnings; |
|
158
|
|
|
|
|
330
|
|
|
158
|
|
|
|
|
6564
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
our $VERSION = '0.000155'; |
6
|
|
|
|
|
|
|
|
7
|
158
|
|
|
158
|
|
1226
|
use Carp qw/croak/; |
|
158
|
|
|
|
|
336
|
|
|
158
|
|
|
|
|
7365
|
|
8
|
158
|
|
|
158
|
|
991
|
use B; |
|
158
|
|
|
|
|
369
|
|
|
158
|
|
|
|
|
11288
|
|
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
|
|
1180
|
use base 'Exporter'; |
|
158
|
|
|
|
|
421
|
|
|
158
|
|
|
|
|
41377
|
|
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
|
101
|
sub slot_to_sig { $SLOTMAP{$_[0]} || croak "unsupported slot: '$_[0]'" } |
30
|
4
|
50
|
|
4
|
1
|
29
|
sub sig_to_slot { $SIGMAP{$_[0]} || croak "unsupported sigil: $_[0]" } |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub get_stash { |
33
|
1046
|
|
33
|
1046
|
1
|
2141
|
my $package = shift || caller; |
34
|
158
|
|
|
158
|
|
1263
|
no strict 'refs'; |
|
158
|
|
|
|
|
424
|
|
|
158
|
|
|
|
|
16084
|
|
35
|
1046
|
|
|
|
|
1470
|
return \%{"${package}\::"}; |
|
1046
|
|
|
|
|
3351
|
|
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub get_glob { |
39
|
1051
|
|
|
1051
|
1
|
2196
|
my $sym = _parse_symbol(scalar(caller), @_); |
40
|
158
|
|
|
158
|
|
1190
|
no strict 'refs'; |
|
158
|
|
|
|
|
446
|
|
|
158
|
|
|
|
|
6413
|
|
41
|
158
|
|
|
158
|
|
1013
|
no warnings 'once'; |
|
158
|
|
|
|
|
505
|
|
|
158
|
|
|
|
|
148998
|
|
42
|
1051
|
|
|
|
|
1568
|
return \*{"$sym->{package}\::$sym->{name}"}; |
|
1051
|
|
|
|
|
3378
|
|
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
50
|
|
|
50
|
1
|
179
|
sub parse_symbol { _parse_symbol(scalar(caller), @_) } |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub _parse_symbol { |
48
|
2125
|
|
|
2125
|
|
4015
|
my ($caller, $symbol, $package) = @_; |
49
|
|
|
|
|
|
|
|
50
|
2125
|
100
|
|
|
|
4259
|
if (ref($symbol)) { |
51
|
1491
|
|
|
|
|
2237
|
my $pkg = $symbol->{package}; |
52
|
|
|
|
|
|
|
|
53
|
1491
|
100
|
100
|
|
|
4442
|
croak "Symbol package ($pkg) and package argument ($package) do not match" |
|
|
|
66
|
|
|
|
|
54
|
|
|
|
|
|
|
if $pkg && $package && $pkg ne $package; |
55
|
|
|
|
|
|
|
|
56
|
1490
|
|
66
|
|
|
3500
|
$symbol->{package} ||= $caller; |
57
|
|
|
|
|
|
|
|
58
|
1490
|
|
|
|
|
4648
|
return $symbol; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
634
|
50
|
|
|
|
1409
|
utf8::downgrade($symbol) if $] == 5.010000; # prevent crash on 5.10.0 |
62
|
634
|
50
|
|
|
|
4415
|
my ($sig, $pkg, $name) = ($symbol =~ m/^(\W?)(.*::)?([^:]+)$/) |
63
|
|
|
|
|
|
|
or croak "Invalid symbol: '$symbol'"; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Normalize package, '::' becomes 'main', 'Foo::' becomes 'Foo' |
66
|
634
|
100
|
|
|
|
1669
|
$pkg = $pkg |
|
|
100
|
|
|
|
|
|
67
|
|
|
|
|
|
|
? $pkg eq '::' |
68
|
|
|
|
|
|
|
? 'main' |
69
|
|
|
|
|
|
|
: substr($pkg, 0, -2) |
70
|
|
|
|
|
|
|
: undef; |
71
|
|
|
|
|
|
|
|
72
|
634
|
100
|
100
|
|
|
1728
|
croak "Symbol package ($pkg) and package argument ($package) do not match" |
|
|
|
66
|
|
|
|
|
73
|
|
|
|
|
|
|
if $pkg && $package && $pkg ne $package; |
74
|
|
|
|
|
|
|
|
75
|
633
|
|
100
|
|
|
2027
|
$sig ||= '&'; |
76
|
633
|
|
33
|
|
|
1684
|
my $type = $SIGMAP{$sig} || croak "unsupported sigil: '$sig'"; |
77
|
|
|
|
|
|
|
|
78
|
633
|
|
66
|
|
|
1492
|
my $real_package = $package || $pkg || $caller; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
return { |
81
|
633
|
|
|
|
|
3626
|
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
|
936
|
|
|
936
|
1
|
2296
|
my $sym = _parse_symbol(scalar(caller), @_); |
91
|
|
|
|
|
|
|
|
92
|
936
|
|
|
|
|
1774
|
my $name = $sym->{name}; |
93
|
936
|
|
|
|
|
1445
|
my $type = $sym->{type}; |
94
|
936
|
|
|
|
|
1358
|
my $package = $sym->{package}; |
95
|
936
|
|
|
|
|
1376
|
my $symbol = $sym->{symbol}; |
96
|
|
|
|
|
|
|
|
97
|
936
|
|
|
|
|
1849
|
my $stash = get_stash($package); |
98
|
936
|
100
|
|
|
|
2388
|
return undef unless exists $stash->{$name}; |
99
|
|
|
|
|
|
|
|
100
|
874
|
|
|
|
|
1652
|
my $glob = get_glob($sym); |
101
|
874
|
100
|
100
|
|
|
2175
|
return *{$glob}{$type} if $type ne 'SCALAR' && defined(*{$glob}{$type}); |
|
393
|
|
|
|
|
1959
|
|
|
779
|
|
|
|
|
2423
|
|
102
|
|
|
|
|
|
|
|
103
|
481
|
50
|
|
|
|
966
|
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
|
481
|
|
|
|
|
1689
|
my $sv = B::svref_2object($glob)->SV; |
118
|
481
|
100
|
|
|
|
1772
|
return *{$glob}{$type} if $sv->isa('B::SV'); |
|
88
|
|
|
|
|
258
|
|
119
|
393
|
50
|
|
|
|
1207
|
return undef unless $sv->isa('B::SPECIAL'); |
120
|
393
|
50
|
|
|
|
845
|
return *{$glob}{$type} if $B::specialsv_name[$$sv] ne 'Nullsv'; |
|
0
|
|
|
|
|
0
|
|
121
|
393
|
|
|
|
|
848
|
return undef; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub purge_symbol { |
125
|
88
|
|
|
88
|
1
|
416
|
my $sym = _parse_symbol(scalar(caller), @_); |
126
|
|
|
|
|
|
|
|
127
|
88
|
|
|
|
|
160
|
local *GLOBCLONE = *{get_glob($sym)}; |
|
88
|
|
|
|
|
214
|
|
128
|
88
|
|
|
|
|
257
|
delete get_stash($sym->{package})->{$sym->{name}}; |
129
|
88
|
|
|
|
|
187
|
my $new_glob = get_glob($sym); |
130
|
|
|
|
|
|
|
|
131
|
88
|
|
|
|
|
217
|
for my $type (qw/CODE SCALAR HASH ARRAY FORMAT IO/) { |
132
|
528
|
100
|
|
|
|
1100
|
next if $type eq $sym->{type}; |
133
|
440
|
|
|
|
|
1318
|
my $ref = get_symbol({type => $type, name => 'GLOBCLONE', sigil => $SLOTMAP{$type}}, __PACKAGE__); |
134
|
440
|
100
|
|
|
|
1242
|
next unless $ref; |
135
|
21
|
|
|
|
|
47
|
*$new_glob = $ref; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
88
|
|
|
|
|
735
|
return *GLOBCLONE{$sym->{type}}; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
1; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
__END__ |