line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Exporter::Simple; |
2
|
|
|
|
|
|
|
|
3
|
4
|
|
|
4
|
|
155448
|
use 5.008; |
|
4
|
|
|
|
|
2502
|
|
|
4
|
|
|
|
|
243
|
|
4
|
4
|
|
|
4
|
|
30
|
use warnings; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
175
|
|
5
|
4
|
|
|
4
|
|
22
|
use strict; |
|
4
|
|
|
|
|
21
|
|
|
4
|
|
|
|
|
168
|
|
6
|
4
|
|
|
4
|
|
4318
|
use Attribute::Handlers; |
|
4
|
|
|
|
|
39827
|
|
|
4
|
|
|
|
|
35
|
|
7
|
4
|
|
|
4
|
|
218
|
use base 'Exporter'; |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
579
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = '1.10'; |
10
|
4
|
|
|
4
|
|
28
|
no warnings 'redefine'; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
316
|
|
11
|
|
|
|
|
|
|
|
12
|
4
|
|
|
4
|
0
|
30
|
sub UNIVERSAL::Exported :ATTR(SCALAR,BEGIN) { export('$', BEGIN => @_) } |
|
4
|
|
|
4
|
|
7
|
|
|
4
|
|
|
|
|
22
|
|
|
4
|
|
|
|
|
1868
|
|
13
|
4
|
|
|
4
|
0
|
1371
|
sub UNIVERSAL::Exported :ATTR(ARRAY,BEGIN) { export('@', BEGIN => @_) } |
|
4
|
|
|
0
|
|
10
|
|
|
4
|
|
|
|
|
20
|
|
|
0
|
|
|
|
|
0
|
|
14
|
4
|
|
|
4
|
0
|
1264
|
sub UNIVERSAL::Exported :ATTR(HASH,BEGIN) { export('%', BEGIN => @_) } |
|
4
|
|
|
4
|
|
10
|
|
|
4
|
|
|
|
|
24
|
|
|
4
|
|
|
|
|
1078
|
|
15
|
4
|
|
|
4
|
0
|
1245
|
sub UNIVERSAL::Exported :ATTR(CODE,BEGIN,CHECK) { export('', INIT => @_) } |
|
4
|
|
|
16
|
|
10
|
|
|
4
|
|
|
|
|
20
|
|
|
16
|
|
|
|
|
5682
|
|
16
|
|
|
|
|
|
|
|
17
|
4
|
|
|
4
|
0
|
1594
|
sub UNIVERSAL::Exportable :ATTR(SCALAR,BEGIN) { exportable('$', BEGIN => @_) } |
|
4
|
|
|
0
|
|
7
|
|
|
4
|
|
|
|
|
17
|
|
|
0
|
|
|
|
|
0
|
|
18
|
4
|
|
|
4
|
0
|
1074
|
sub UNIVERSAL::Exportable :ATTR(ARRAY,BEGIN) { exportable('@', BEGIN => @_) } |
|
4
|
|
|
4
|
|
6
|
|
|
4
|
|
|
|
|
17
|
|
|
4
|
|
|
|
|
1623
|
|
19
|
4
|
|
|
4
|
0
|
1190
|
sub UNIVERSAL::Exportable :ATTR(HASH,BEGIN) { exportable('%', BEGIN => @_) } |
|
4
|
|
|
0
|
|
8
|
|
|
4
|
|
|
|
|
15
|
|
|
0
|
|
|
|
|
0
|
|
20
|
4
|
|
|
4
|
0
|
1330
|
sub UNIVERSAL::Exportable :ATTR(CODE,BEGIN,CHECK) { exportable('', INIT => @_) } |
|
4
|
|
|
24
|
|
7
|
|
|
4
|
|
|
|
|
19
|
|
|
24
|
|
|
|
|
6510
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# Build a structure in which we remember what to export when (in |
23
|
|
|
|
|
|
|
# which phase, BEGIN or INIT) to whom. Scalars, arrays and hashes are exported |
24
|
|
|
|
|
|
|
# during BEGIN, but subroutines need to be exported during CHECK, because |
25
|
|
|
|
|
|
|
# their names aren't known during BEGIN (they're 'ANON' in this phase). But |
26
|
|
|
|
|
|
|
# because of a bug in Attribute::Handlers, we can't just declare |
27
|
|
|
|
|
|
|
# :ATTR(CODE,CHECK), because that would make the handlers for scalars, arrays |
28
|
|
|
|
|
|
|
# and hashes run during CHECK as well, even though they were declared as |
29
|
|
|
|
|
|
|
# :ATTR(...,BEGIN). But each handler specifies in the call to export() or |
30
|
|
|
|
|
|
|
# exportable() which phase the symbol is to be exported in. |
31
|
|
|
|
|
|
|
# |
32
|
|
|
|
|
|
|
# The structure is %EXPORTDEF and is built when the attribute handlers run, |
33
|
|
|
|
|
|
|
# and consulted during do_export(), which is called both from import() and |
34
|
|
|
|
|
|
|
# INIT(), see below. |
35
|
|
|
|
|
|
|
# |
36
|
|
|
|
|
|
|
# An example structure is shown here and is built by declaring the following |
37
|
|
|
|
|
|
|
# exports in a module that subclasses Exporter::Simple: |
38
|
|
|
|
|
|
|
# |
39
|
|
|
|
|
|
|
# our @bar : Exportable(vars) = (2, 3, 5, 7); |
40
|
|
|
|
|
|
|
# our $foo : Exported(vars) = 42; |
41
|
|
|
|
|
|
|
# our %baz : Exported = (a => 65, b => 66); |
42
|
|
|
|
|
|
|
# |
43
|
|
|
|
|
|
|
# sub hello : Exported(greet,uk) { "hello there" } |
44
|
|
|
|
|
|
|
# sub askme : Exportable { "what you will" } |
45
|
|
|
|
|
|
|
# sub hi : Exportable(greet,us) { "hi there" } |
46
|
|
|
|
|
|
|
# |
47
|
|
|
|
|
|
|
# sub get_foo : Exported(vars) { $foo } |
48
|
|
|
|
|
|
|
# sub get_bar : Exportable(vars) { @bar } |
49
|
|
|
|
|
|
|
# |
50
|
|
|
|
|
|
|
# results in: |
51
|
|
|
|
|
|
|
# |
52
|
|
|
|
|
|
|
# %EXPORTDEF = |
53
|
|
|
|
|
|
|
# --- #YAML:1.0 |
54
|
|
|
|
|
|
|
# BEGIN: |
55
|
|
|
|
|
|
|
# MyExport: |
56
|
|
|
|
|
|
|
# EXPORT: |
57
|
|
|
|
|
|
|
# - '$foo' |
58
|
|
|
|
|
|
|
# - '%baz' |
59
|
|
|
|
|
|
|
# EXPORT_OK: |
60
|
|
|
|
|
|
|
# - '@bar' |
61
|
|
|
|
|
|
|
# EXPORT_TAGS: |
62
|
|
|
|
|
|
|
# all: |
63
|
|
|
|
|
|
|
# - '@bar' |
64
|
|
|
|
|
|
|
# - '$foo' |
65
|
|
|
|
|
|
|
# - '%baz' |
66
|
|
|
|
|
|
|
# greet: [] |
67
|
|
|
|
|
|
|
# uk: [] |
68
|
|
|
|
|
|
|
# us: [] |
69
|
|
|
|
|
|
|
# vars: |
70
|
|
|
|
|
|
|
# - '@bar' |
71
|
|
|
|
|
|
|
# - '$foo' |
72
|
|
|
|
|
|
|
# INIT: |
73
|
|
|
|
|
|
|
# MyExport: |
74
|
|
|
|
|
|
|
# EXPORT: |
75
|
|
|
|
|
|
|
# - hello |
76
|
|
|
|
|
|
|
# - get_foo |
77
|
|
|
|
|
|
|
# EXPORT_OK: |
78
|
|
|
|
|
|
|
# - askme |
79
|
|
|
|
|
|
|
# - hi |
80
|
|
|
|
|
|
|
# - get_bar |
81
|
|
|
|
|
|
|
# EXPORT_TAGS: |
82
|
|
|
|
|
|
|
# all: |
83
|
|
|
|
|
|
|
# - hello |
84
|
|
|
|
|
|
|
# - askme |
85
|
|
|
|
|
|
|
# - hi |
86
|
|
|
|
|
|
|
# - get_foo |
87
|
|
|
|
|
|
|
# - get_bar |
88
|
|
|
|
|
|
|
# greet: |
89
|
|
|
|
|
|
|
# - hello |
90
|
|
|
|
|
|
|
# - hi |
91
|
|
|
|
|
|
|
# uk: |
92
|
|
|
|
|
|
|
# - hello |
93
|
|
|
|
|
|
|
# us: |
94
|
|
|
|
|
|
|
# - hi |
95
|
|
|
|
|
|
|
# vars: |
96
|
|
|
|
|
|
|
# - get_foo |
97
|
|
|
|
|
|
|
# - get_bar |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub add { |
100
|
52
|
|
|
52
|
0
|
113
|
my ($arrname, $sigil, $exp_phase, $pkg, $symbol, $ref, $attr, $tags) = @_; |
101
|
52
|
50
|
|
|
|
139
|
$symbol = *{$symbol}{NAME} if ref $symbol; |
|
52
|
|
|
|
|
259
|
|
102
|
52
|
|
|
|
|
115
|
$symbol = "$sigil$symbol"; |
103
|
52
|
100
|
33
|
|
|
181
|
$tags = [ $tags || () ] unless ref $tags eq 'ARRAY'; |
104
|
|
|
|
|
|
|
|
105
|
52
|
|
|
|
|
73
|
our %EXPORTDEF; |
106
|
|
|
|
|
|
|
|
107
|
52
|
50
|
|
|
|
116
|
if ($symbol eq 'ANON') { |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# see the empty arrays in keys 'greet', 'uk' and 'us' in the above |
110
|
|
|
|
|
|
|
# sample of $EXPORT{BEGIN}{MyExport}{EXPORT_TAGS} ? They need to be |
111
|
|
|
|
|
|
|
# there because these tags are only defined by subroutines (hello() |
112
|
|
|
|
|
|
|
# and hi(); see sample code above), and hence they would appear in |
113
|
|
|
|
|
|
|
# %EXPORTDEF only during CHECK, but the tag ':greet' still gets passed |
114
|
|
|
|
|
|
|
# to Exporter::import() during BEGIN (which is necessary because some |
115
|
|
|
|
|
|
|
# scalars, arrays and hashes *could* still have used these tags in |
116
|
|
|
|
|
|
|
# their attribute declarations). Therefore, when we handle a subroutine |
117
|
|
|
|
|
|
|
# attribute during BEGIN (recognized by the symbol name being 'ANON'), |
118
|
|
|
|
|
|
|
# we make empty entries for the tags in %EXPORTDEF. Now Exporter is |
119
|
|
|
|
|
|
|
# happy and the tests are happy and we are all happy. |
120
|
|
|
|
|
|
|
|
121
|
0
|
|
0
|
|
|
0
|
$EXPORTDEF{BEGIN}{$pkg}{EXPORT_TAGS}{$_} ||= [] for @$tags, 'all'; |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# we'll see the sub again during CHECK, to be exported during INIT, so: |
124
|
|
|
|
|
|
|
|
125
|
0
|
|
|
|
|
0
|
return; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
32
|
|
|
|
|
91
|
push @{ $EXPORTDEF{$exp_phase}{$pkg}{$arrname} } => $symbol unless |
|
72
|
|
|
|
|
183
|
|
129
|
52
|
100
|
|
|
|
60
|
grep { $_ eq $symbol } @{ $EXPORTDEF{$exp_phase}{$pkg}{$arrname} }; |
|
52
|
|
|
|
|
173
|
|
130
|
|
|
|
|
|
|
|
131
|
52
|
|
|
|
|
102
|
for my $tag (@$tags, 'all') { |
132
|
64
|
|
|
|
|
282
|
push @{ $EXPORTDEF{$exp_phase}{$pkg}{EXPORT_TAGS}{$tag} } => $symbol |
|
204
|
|
|
|
|
510
|
|
133
|
108
|
|
|
|
|
305
|
unless grep { $_ eq $symbol } |
134
|
108
|
100
|
|
|
|
123
|
@{ $EXPORTDEF{$exp_phase}{$pkg}{EXPORT_TAGS}{$tag} }; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
24
|
|
|
24
|
0
|
57
|
sub export { add(EXPORT => @_) } |
139
|
28
|
|
|
28
|
0
|
65
|
sub exportable { add(EXPORT_OK => @_) } |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# import() could be called several times, from different packages |
142
|
|
|
|
|
|
|
# who want to import symbols from us. So we remember who gets to |
143
|
|
|
|
|
|
|
# import what in which phase. Scalars, arrays and hashes are imported |
144
|
|
|
|
|
|
|
# during BEGIN (that's why import() also calls do_export('BEGIN') at |
145
|
|
|
|
|
|
|
# the end, while subroutines are exported during INIT. Tags, starting |
146
|
|
|
|
|
|
|
# with a colon, need to be seen both during BEGIN and END. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
sub import { |
149
|
4
|
|
|
4
|
|
1022
|
my $pkg = shift; |
150
|
4
|
|
|
|
|
9
|
our %wants_import; |
151
|
|
|
|
|
|
|
|
152
|
4
|
|
|
|
|
14
|
for (@_) { |
153
|
6
|
100
|
|
|
|
34
|
if (/^:/) { |
|
|
50
|
|
|
|
|
|
154
|
5
|
|
|
|
|
8
|
push @{ $wants_import{BEGIN}{$pkg} } => $_; |
|
5
|
|
|
|
|
17
|
|
155
|
5
|
|
|
|
|
8
|
push @{ $wants_import{INIT}{$pkg} } => $_; |
|
5
|
|
|
|
|
19
|
|
156
|
|
|
|
|
|
|
} elsif (/^[\$\@%]/) { |
157
|
0
|
|
|
|
|
0
|
push @{ $wants_import{BEGIN}{$pkg} } => $_; |
|
0
|
|
|
|
|
0
|
|
158
|
|
|
|
|
|
|
} else { |
159
|
1
|
|
|
|
|
2
|
push @{ $wants_import{INIT}{$pkg} } => $_; |
|
1
|
|
|
|
|
4
|
|
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
4
|
|
|
|
|
18
|
do_export('BEGIN'); |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub do_export { |
167
|
7
|
|
|
7
|
0
|
17
|
my $phase = shift; |
168
|
7
|
|
|
|
|
17
|
our (%EXPORTDEF, %wants_import); |
169
|
|
|
|
|
|
|
|
170
|
7
|
|
|
|
|
16
|
while (my ($pkg, $def) = each %{ $EXPORTDEF{$phase} }) { |
|
13
|
|
|
|
|
2569
|
|
171
|
4
|
|
|
4
|
|
3605
|
no strict 'refs'; |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
917
|
|
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# remove export cache; without this, we can't export in both BEGIN |
174
|
|
|
|
|
|
|
# and INIT phases |
175
|
|
|
|
|
|
|
|
176
|
7
|
|
|
|
|
15
|
undef %{ "$pkg\::EXPORT" }; |
|
7
|
|
|
|
|
55
|
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# build the variables Exporter requires to do its work and ask it to export |
179
|
|
|
|
|
|
|
# the symbols we remembered during import(). |
180
|
|
|
|
|
|
|
|
181
|
7
|
50
|
|
|
|
15
|
@{ "$pkg\::EXPORT" } = @{ $def->{EXPORT} || [] }; |
|
7
|
|
|
|
|
78
|
|
|
7
|
|
|
|
|
37
|
|
182
|
7
|
50
|
|
|
|
13
|
@{ "$pkg\::EXPORT_OK" } = @{ $def->{EXPORT_OK} || [] }; |
|
7
|
|
|
|
|
44
|
|
|
7
|
|
|
|
|
31
|
|
183
|
7
|
50
|
|
|
|
47
|
%{ "$pkg\::EXPORT_TAGS" } = %{ $def->{EXPORT_TAGS} || {} }; |
|
7
|
|
|
|
|
58
|
|
|
7
|
|
|
|
|
50
|
|
184
|
|
|
|
|
|
|
|
185
|
7
|
|
|
|
|
21
|
local $Exporter::ExportLevel = 2; |
186
|
7
|
100
|
|
|
|
11
|
Exporter::import($pkg => @{ $wants_import{$phase}{$pkg} || [] }); |
|
7
|
|
|
|
|
1873
|
|
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
3
|
|
|
3
|
|
203
|
INIT { do_export('INIT') } |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
1; |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
__END__ |