line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#======================================================================== |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# Badger::Exporter |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# DESCRIPTION |
6
|
|
|
|
|
|
|
# This module is an OO version of the Exporter module. It |
7
|
|
|
|
|
|
|
# does the same kind of thing but with an OO interface that means |
8
|
|
|
|
|
|
|
# you don't have to go messing around with package variables. It |
9
|
|
|
|
|
|
|
# correctly handles inheritance, exporting not only those symbols |
10
|
|
|
|
|
|
|
# defined by a subclass, but also those of its base classes. |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
# AUTHOR |
13
|
|
|
|
|
|
|
# Andy Wardley |
14
|
|
|
|
|
|
|
# |
15
|
|
|
|
|
|
|
#======================================================================== |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
package Badger::Exporter; |
18
|
|
|
|
|
|
|
|
19
|
70
|
|
|
70
|
|
2144
|
use Carp; |
|
70
|
|
|
|
|
114
|
|
|
70
|
|
|
|
|
3140
|
|
20
|
70
|
|
|
70
|
|
314
|
use strict; |
|
70
|
|
|
|
|
99
|
|
|
70
|
|
|
|
|
1210
|
|
21
|
70
|
|
|
70
|
|
249
|
use warnings; |
|
70
|
|
|
|
|
95
|
|
|
70
|
|
|
|
|
8323
|
|
22
|
|
|
|
|
|
|
use constant { |
23
|
70
|
|
|
|
|
73189
|
ALL => 'all', # Alas, we can't pull these in from |
24
|
|
|
|
|
|
|
NONE => 'none', # Badger::Constants because it's a |
25
|
|
|
|
|
|
|
DEFAULT => 'default', # subclass of Badger::Exporter which |
26
|
|
|
|
|
|
|
IMPORT => 'import', # gives us a chicken-and-egg dependency |
27
|
|
|
|
|
|
|
IMPORTS => 'imports', # problem.We could pull them into |
28
|
|
|
|
|
|
|
HOOKS => 'hooks', # Badger::Constants though because |
29
|
|
|
|
|
|
|
ARRAY => 'ARRAY', # that's a subclass... hmmm.... |
30
|
|
|
|
|
|
|
HASH => 'HASH', |
31
|
|
|
|
|
|
|
CODE => 'CODE', |
32
|
|
|
|
|
|
|
EXPORT_ALL => 'EXPORT_ALL', |
33
|
|
|
|
|
|
|
EXPORT_ANY => 'EXPORT_ANY', |
34
|
|
|
|
|
|
|
EXPORT_TAGS => 'EXPORT_TAGS', |
35
|
|
|
|
|
|
|
EXPORT_FAIL => 'EXPORT_FAIL', |
36
|
|
|
|
|
|
|
EXPORT_HOOKS => 'EXPORT_HOOKS', |
37
|
|
|
|
|
|
|
EXPORT_BEFORE => 'EXPORT_BEFORE', |
38
|
|
|
|
|
|
|
EXPORT_AFTER => 'EXPORT_AFTER', |
39
|
|
|
|
|
|
|
EXPORTABLES => 'EXPORTABLES', |
40
|
|
|
|
|
|
|
ISA => 'ISA', |
41
|
|
|
|
|
|
|
REFS => 'refs', |
42
|
|
|
|
|
|
|
ONCE => 'once', |
43
|
|
|
|
|
|
|
PKG => '::', |
44
|
|
|
|
|
|
|
DELIMITER => qr/(?:,\s*)|\s+/, # match a comma or whitespace |
45
|
|
|
|
|
|
|
MISSING => "Missing value for the '%s' option%s", |
46
|
|
|
|
|
|
|
BAD_HANDLER => "Invalid export %s handler specified: %s", |
47
|
|
|
|
|
|
|
BAD_HOOK => "Invalid export hook handler specified for the '%s' option: %s", |
48
|
|
|
|
|
|
|
WANTED => " (%s wanted, %s specified)", |
49
|
|
|
|
|
|
|
UNDEFINED => " (argument %s of %s is undefined)", |
50
|
70
|
|
|
70
|
|
456
|
}; |
|
70
|
|
|
|
|
125
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
our $VERSION = 0.01; |
53
|
|
|
|
|
|
|
our $DEBUG = 0 unless defined $DEBUG; |
54
|
|
|
|
|
|
|
our $HANDLERS = { |
55
|
|
|
|
|
|
|
all => \&export_all, |
56
|
|
|
|
|
|
|
any => \&export_any, |
57
|
|
|
|
|
|
|
tags => \&export_tags, |
58
|
|
|
|
|
|
|
hooks => \&export_hooks, |
59
|
|
|
|
|
|
|
fail => \&export_fail, |
60
|
|
|
|
|
|
|
before => \&export_before, |
61
|
|
|
|
|
|
|
after => \&export_after, |
62
|
|
|
|
|
|
|
}; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
#----------------------------------------------------------------------- |
66
|
|
|
|
|
|
|
# export declaration methods: |
67
|
|
|
|
|
|
|
# exports( all => [...], any => [...], ...etc... ) |
68
|
|
|
|
|
|
|
# export_all('foo bar baz') |
69
|
|
|
|
|
|
|
# export_any('foo bar baz') |
70
|
|
|
|
|
|
|
# export_before( sub { ... } ) |
71
|
|
|
|
|
|
|
# export_after( sub { ... } ) |
72
|
|
|
|
|
|
|
# export_tags( set1 => 'foo bar baz', set2 => 'wam bam' ) |
73
|
|
|
|
|
|
|
# export_hooks( foo => sub { ... }, bar => sub { ... } ) |
74
|
|
|
|
|
|
|
# export_fail( sub { ... } ) |
75
|
|
|
|
|
|
|
#----------------------------------------------------------------------- |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub exports { |
78
|
696
|
|
|
696
|
1
|
1124
|
my $self = shift; |
79
|
696
|
100
|
66
|
|
|
2823
|
my $data = @_ == 1 && ref $_[0] eq HASH ? shift : { @_ }; |
80
|
696
|
|
|
|
|
814
|
my $handler; |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
# delegate each key in $data to a handler in $HANDLERS |
83
|
696
|
|
|
|
|
2548
|
while (my ($key, $value) = each %$data) { |
84
|
1188
|
|
33
|
|
|
2743
|
$handler = $HANDLERS->{ $key } |
85
|
|
|
|
|
|
|
|| croak "Invalid exports key: $key\n"; |
86
|
1188
|
|
|
|
|
2212
|
$handler->($self, $value); |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub export_all { |
91
|
75
|
|
|
75
|
1
|
2670
|
my $self = shift; |
92
|
75
|
100
|
|
|
|
396
|
my $args = @_ == 1 ? shift : [ @_ ]; |
93
|
75
|
|
|
|
|
290
|
my $list = $self->export_variable( EXPORT_ALL => [ ] ); |
94
|
75
|
100
|
|
|
|
1504
|
push( @$list, ref $args eq ARRAY ? @$args : split(DELIMITER, $args) ); |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub export_any { |
98
|
795
|
|
|
795
|
1
|
2228
|
my $self = shift; |
99
|
795
|
100
|
|
|
|
2848
|
my $args = @_ == 1 ? shift : [ @_ ]; |
100
|
795
|
|
|
|
|
4642
|
my $list = $self->export_variable( EXPORT_ANY => [ ] ); |
101
|
795
|
100
|
|
|
|
6180
|
push( @$list, ref $args eq ARRAY ? @$args : split(DELIMITER, $args) ); |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub export_before { |
105
|
26
|
|
|
26
|
1
|
72
|
my $self = shift; |
106
|
26
|
50
|
|
|
|
97
|
my $args = @_ == 1 ? shift : [ @_ ]; |
107
|
26
|
|
|
|
|
78
|
my $list = $self->export_variable( EXPORT_BEFORE => [ ] ); |
108
|
26
|
50
|
|
|
|
130
|
push( @$list, ref $args eq ARRAY ? @$args : $args ); |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub export_after { |
112
|
72
|
|
|
72
|
1
|
185
|
my $self = shift; |
113
|
72
|
50
|
|
|
|
371
|
my $args = @_ == 1 ? shift : [ @_ ]; |
114
|
72
|
|
|
|
|
379
|
my $list = $self->export_variable( EXPORT_AFTER => [ ] ); |
115
|
72
|
50
|
|
|
|
491
|
push( @$list, ref $args eq ARRAY ? @$args : $args ); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub export_tags { |
119
|
287
|
|
|
287
|
1
|
1634
|
my $self = shift; |
120
|
287
|
100
|
66
|
|
|
2590
|
my $args = (@_ == 1) && (ref $_[0] eq HASH) ? shift : { @_ }; |
121
|
287
|
|
|
|
|
911
|
my $tags = $self->export_variable( EXPORT_TAGS => { } ); |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# Add new tags into $EXPORT_TAGS hash ref |
124
|
|
|
|
|
|
|
@$tags{ keys %$args } = map { |
125
|
|
|
|
|
|
|
# Tags can be defined as hash arrays containing (key => '=value') |
126
|
|
|
|
|
|
|
# declarataions. We upgrade each '=value' to a constant subroutine. |
127
|
287
|
100
|
100
|
|
|
808
|
if (ref && ref eq HASH) { |
|
500
|
|
|
|
|
3929
|
|
128
|
4
|
|
|
|
|
28
|
while (my ($key, $value) = each %$_) { |
129
|
13
|
100
|
|
|
|
40
|
if ($value =~ s/^=//) { |
130
|
4
|
50
|
|
|
|
10
|
_debug("export_tags() constructing constant: $key => $value\n") if $DEBUG; |
131
|
4
|
|
|
0
|
|
31
|
$_->{ $key } = sub() { $value }; |
|
0
|
|
|
|
|
0
|
|
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
} |
135
|
500
|
|
|
|
|
1329
|
$_; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
values %$args; |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# all symbols referenced in tagsets (except other tag sets) must be |
140
|
|
|
|
|
|
|
# flagged as exportable |
141
|
|
|
|
|
|
|
$self->export_any( |
142
|
|
|
|
|
|
|
grep { |
143
|
|
|
|
|
|
|
# ignore references to code or other tag sets |
144
|
2702
|
|
66
|
|
|
8883
|
not (ref || /^(:|=)/); |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
map { |
147
|
|
|
|
|
|
|
# symbols in tagset can be a list ref, hash ref or string |
148
|
287
|
100
|
|
|
|
637
|
ref $_ eq ARRAY ? @$_ : |
|
500
|
100
|
|
|
|
3910
|
|
149
|
|
|
|
|
|
|
ref $_ eq HASH ? %$_ : |
150
|
|
|
|
|
|
|
split DELIMITER |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
values %$args |
153
|
|
|
|
|
|
|
); |
154
|
|
|
|
|
|
|
|
155
|
287
|
|
|
|
|
977
|
return $tags; |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub export_hooks { |
159
|
506
|
|
|
506
|
1
|
1270
|
my $self = shift; |
160
|
506
|
100
|
66
|
|
|
1919
|
my $args = (@_ == 1) && (ref $_[0] eq HASH) ? shift : { @_ }; |
161
|
506
|
|
|
|
|
1965
|
my $hooks = $self->export_variable( EXPORT_HOOKS => { } ); |
162
|
506
|
|
|
|
|
2453
|
@$hooks{ keys %$args } = values %$args; |
163
|
506
|
|
|
|
|
1768
|
return $hooks; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub export_fail { |
167
|
166
|
|
|
166
|
1
|
1270
|
my $self = shift; |
168
|
166
|
|
33
|
|
|
629
|
my $class = ref $self || $self; |
169
|
70
|
|
|
70
|
|
528
|
no strict REFS; |
|
70
|
|
|
|
|
116
|
|
|
70
|
|
|
|
|
13813
|
|
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# get/set $EXPORT_FAIL |
172
|
|
|
|
|
|
|
return @_ |
173
|
166
|
|
|
|
|
853
|
? (${$class.PKG.EXPORT_FAIL} = shift) |
174
|
166
|
50
|
|
|
|
568
|
: ${$class.PKG.EXPORT_FAIL}; |
|
0
|
|
|
|
|
0
|
|
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
179
|
|
|
|
|
|
|
# import/export methods: |
180
|
|
|
|
|
|
|
# import(@imports) |
181
|
|
|
|
|
|
|
# export($target, @exports) |
182
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
sub import { |
185
|
3423
|
|
|
3423
|
|
23547
|
my $class = shift; |
186
|
3423
|
|
|
|
|
8454
|
my $target = (caller())[0]; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# enable strict and warnings in the caller - this ensures that every |
189
|
|
|
|
|
|
|
# Badger module (that calls this method - which is pretty much all of |
190
|
|
|
|
|
|
|
# them) has strict/warnings enabled, without having to explicitly write |
191
|
|
|
|
|
|
|
# it. Thx Moose! |
192
|
3423
|
|
|
|
|
19178
|
strict->import; |
193
|
3423
|
|
|
|
|
30811
|
warnings->import; |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# call in the heavy guns |
196
|
3423
|
|
|
|
|
12079
|
$class->export($target, @_); |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
sub export { |
200
|
6648
|
|
|
6648
|
1
|
8232
|
my $class = shift; |
201
|
6648
|
|
|
|
|
9381
|
my $target = shift; |
202
|
6648
|
100
|
|
|
|
16932
|
my $imports = @_ == 1 ? shift : [ @_ ]; |
203
|
6648
|
|
|
|
|
14096
|
my ($all, $any, $tags, $hooks, $fails, $before, $after) |
204
|
|
|
|
|
|
|
= $class->exportables; |
205
|
6648
|
100
|
|
|
|
11141
|
my $can_hook = (%$hooks ? 1 : 0); |
206
|
6648
|
|
|
|
|
6234
|
my $added_all = 0; |
207
|
6648
|
|
|
|
|
5910
|
my $count = 0; |
208
|
6648
|
|
|
|
|
7316
|
my ($symbol, $symbols, $source, $hook, $pkg, $nargs, |
209
|
|
|
|
|
|
|
%done, @args, @errors); |
210
|
|
|
|
|
|
|
|
211
|
70
|
|
|
70
|
|
467
|
no strict REFS; |
|
70
|
|
|
|
|
112
|
|
|
70
|
|
|
|
|
2582
|
|
212
|
70
|
|
|
70
|
|
360
|
no warnings ONCE; |
|
70
|
|
|
|
|
124
|
|
|
70
|
|
|
|
|
57563
|
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
# imports can be a single whitespace delimited string of symbols |
215
|
6648
|
100
|
|
|
|
28701
|
$imports = [ split(DELIMITER, $imports) ] |
216
|
|
|
|
|
|
|
unless ref $imports eq ARRAY; |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
# default to export_all if list of exports not specified |
219
|
|
|
|
|
|
|
# TODO: what about: use Badger::Example qw(); ? perhaps we should |
220
|
|
|
|
|
|
|
# return unless @_ up above? |
221
|
6648
|
100
|
|
|
|
11432
|
@$imports = @$all unless @$imports; |
222
|
|
|
|
|
|
|
|
223
|
6648
|
|
|
|
|
10095
|
foreach $hook (@$before) { |
224
|
28
|
|
|
|
|
106
|
$hook->($class, $target, $imports); |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
6648
|
|
|
|
|
10076
|
SYMBOL: while (@$imports) { |
228
|
33810
|
50
|
|
|
|
48713
|
next unless ($symbol = shift @$imports); |
229
|
33810
|
100
|
|
|
|
61948
|
next if $done{ $symbol }++; |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# look for :tagset symbols and expand their contents onto @$imports |
232
|
33809
|
100
|
|
|
|
50357
|
if ($symbol =~ s/^://) { |
233
|
455
|
100
|
|
|
|
1254
|
if ($symbols = $tags->{ $symbol }) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
234
|
445
|
100
|
|
|
|
1091
|
if (ref $symbols eq ARRAY) { |
|
|
100
|
|
|
|
|
|
235
|
|
|
|
|
|
|
# expand list of symbols onto @$imports list |
236
|
8
|
|
|
|
|
16
|
unshift(@$imports, @$symbols); |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
elsif (ref $symbols eq HASH) { |
239
|
|
|
|
|
|
|
# map hash into [name => $symbol] pairs |
240
|
4
|
|
|
|
|
9
|
unshift(@$imports, map { [$_ => $symbols->{ $_ }] } keys %$symbols); |
|
13
|
|
|
|
|
23
|
|
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
else { |
243
|
|
|
|
|
|
|
# string of space-delimited symbols |
244
|
433
|
|
|
|
|
5902
|
unshift(@$imports, split(DELIMITER, $symbols)); |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
elsif ($symbol eq DEFAULT) { |
248
|
1
|
|
|
|
|
3
|
unshift(@$imports, @$all); |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
elsif ($symbol eq ALL) { |
251
|
9
|
|
|
|
|
100
|
unshift(@$imports, keys %$any); |
252
|
9
|
|
|
|
|
25
|
$added_all = 1; |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
else { |
255
|
0
|
|
|
|
|
0
|
push(@errors, "Invalid import tag: $symbol\n"); |
256
|
|
|
|
|
|
|
} |
257
|
455
|
|
|
|
|
1058
|
next SYMBOL; |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
33354
|
100
|
100
|
|
|
98024
|
if (ref $symbol eq ARRAY) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
261
|
|
|
|
|
|
|
# a pair of [name, $symbol] expanded from a :tag hash set |
262
|
13
|
|
|
|
|
16
|
($symbol, $source) = @$symbol; |
263
|
|
|
|
|
|
|
# _debug("expanded export pair: $symbol => $source\n") if $DEBUG; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
elsif ($can_hook && ($hook = $hooks->{ $symbol })) { |
266
|
|
|
|
|
|
|
# a hook can be specified as [$code,$nargs] in which case we |
267
|
|
|
|
|
|
|
# generate a closure around the $code which shifts $nargs off |
268
|
|
|
|
|
|
|
# the symbols list and passes them as arguments to $code |
269
|
14062
|
100
|
|
|
|
22717
|
$hook = $hooks->{ $symbol } = $class->export_hook_generator($symbol, $hook) |
270
|
|
|
|
|
|
|
unless ref $hook eq CODE; |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# fire off handler hooked to this import item |
273
|
14062
|
|
|
|
|
26608
|
&$hook($class, $target, $symbol, $imports); |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# hooks can be repeated so pretend we haven't done it |
276
|
14059
|
|
|
|
|
19900
|
$done{ $symbol }--; |
277
|
14059
|
|
|
|
|
17085
|
next SYMBOL; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
elsif ($symbol eq IMPORTS) { |
280
|
|
|
|
|
|
|
# special 'imports' hook disables any more hooks causing |
281
|
|
|
|
|
|
|
# all remaining arguments to be imported as symbols |
282
|
0
|
|
|
|
|
0
|
$can_hook = 0; |
283
|
0
|
|
|
|
|
0
|
next SYMBOL; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
elsif ($symbol eq IMPORT) { |
286
|
|
|
|
|
|
|
# 'import' hook accepts the next item as an import list/string |
287
|
|
|
|
|
|
|
# and unpacks it onto the front of the imports list. We disable |
288
|
|
|
|
|
|
|
# hooks for the duration of the import and insert a dummy HOOKS |
289
|
|
|
|
|
|
|
# symbol at the end to re-enable hooks |
290
|
1191
|
|
|
|
|
1541
|
$can_hook = 0; |
291
|
1191
|
50
|
|
|
|
1992
|
if ($symbols = shift @$imports) { |
292
|
1191
|
50
|
|
|
|
6398
|
$symbols = [ split(DELIMITER, $symbols) ] |
293
|
|
|
|
|
|
|
unless ref $symbols eq ARRAY; |
294
|
1191
|
|
|
|
|
3009
|
unshift(@$imports, @$symbols, HOOKS); |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
else { |
297
|
0
|
|
|
|
|
0
|
push(@errors, "Missing argument for $symbol hook\n"); |
298
|
|
|
|
|
|
|
} |
299
|
1191
|
|
|
|
|
1572
|
next SYMBOL; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
elsif ($symbol eq HOOKS) { |
302
|
|
|
|
|
|
|
# special 'hooks' item turns hooks back on |
303
|
1191
|
|
|
|
|
1377
|
$can_hook = 1; |
304
|
1191
|
|
|
|
|
1406
|
next SYMBOL; |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
else { |
307
|
|
|
|
|
|
|
# otherwise the symbol exported is the one requested |
308
|
16897
|
|
|
|
|
18347
|
$source = $symbol; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# check we're allowed to export the symbol requested |
312
|
16910
|
100
|
|
|
|
25686
|
if ($pkg = $any->{ $symbol }) { |
313
|
|
|
|
|
|
|
# _debug("exporting $symbol from $pkg to $target\n") if $DEBUG; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
else { |
316
|
197
|
|
|
|
|
416
|
foreach $hook (@$fails) { |
317
|
198
|
100
|
|
|
|
530
|
if (&$hook($class, $target, $symbol, $imports)) { |
318
|
|
|
|
|
|
|
# hooks can be repeated so pretend we haven't done it |
319
|
195
|
|
|
|
|
353
|
$done{ $symbol }--; |
320
|
195
|
|
|
|
|
380
|
next SYMBOL; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
} |
323
|
2
|
|
|
|
|
6
|
push(@errors, "$symbol is not exported by $class\n"); |
324
|
2
|
|
|
|
|
4
|
next SYMBOL; |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
16713
|
100
|
|
|
|
17648
|
if (ref $source eq CODE) { |
328
|
|
|
|
|
|
|
# patch directly into the code ref |
329
|
|
|
|
|
|
|
# _debug("exporting $symbol from code reference\n") if $DEBUG; |
330
|
8
|
|
|
|
|
8
|
*{ $target.PKG.$symbol } = $source; |
|
8
|
|
|
|
|
21
|
|
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
else { |
333
|
16705
|
|
|
|
|
14977
|
my $type = "&"; |
334
|
16705
|
|
|
|
|
22730
|
$symbol =~ s/^(\W)//; |
335
|
16705
|
100
|
|
|
|
23105
|
$source =~ s/^(\W)// and $type = $1; |
336
|
|
|
|
|
|
|
# NOTE: '=value' should *probably* never be found at this point |
337
|
|
|
|
|
|
|
# because we're now upgrading them to constant subroutines in |
338
|
|
|
|
|
|
|
# the import_tags() method. However, I'm leaving this in here |
339
|
|
|
|
|
|
|
# until I've had a chance to properly review the code and convince |
340
|
|
|
|
|
|
|
# myself that this assumption is correct. |
341
|
16705
|
50
|
33
|
|
|
21525
|
_debug("export() constructing constant: $symbol => $source\n") |
342
|
|
|
|
|
|
|
if $DEBUG && $type eq '='; |
343
|
16705
|
100
|
66
|
|
|
51717
|
$source = $pkg.PKG.$source unless $source =~ /::/ or $type eq '='; |
344
|
16705
|
50
|
|
|
|
21103
|
_debug("exporting $type$symbol from $source into $target\n") if $DEBUG; |
345
|
16705
|
|
|
|
|
59561
|
*{ $target.PKG.$symbol } = |
346
|
16646
|
|
|
|
|
35712
|
$type eq '&' ? \&{$source} : |
347
|
35
|
|
|
|
|
62
|
$type eq '$' ? \${$source} : |
348
|
14
|
|
|
|
|
24
|
$type eq '@' ? \@{$source} : |
349
|
10
|
|
|
|
|
15
|
$type eq '%' ? \%{$source} : |
350
|
0
|
|
|
|
|
0
|
$type eq '*' ? *{$source} : |
351
|
0
|
|
|
0
|
|
0
|
$type eq '=' ? sub(){$source} : |
352
|
16705
|
0
|
|
|
|
18951
|
do { push(@errors, "Can't export symbol: $type$symbol\n"); next; }; |
|
0
|
0
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
353
|
|
|
|
|
|
|
} |
354
|
16713
|
|
|
|
|
20519
|
$count++; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
continue { |
357
|
|
|
|
|
|
|
# if we're on the last item and we've only processed hooks |
358
|
|
|
|
|
|
|
# (i.e. no real symbols were specified then we export the |
359
|
|
|
|
|
|
|
# default set of symbols instead |
360
|
33807
|
100
|
100
|
|
|
72709
|
unless (@$imports or $count or $added_all) { |
|
|
|
66
|
|
|
|
|
361
|
632
|
|
|
|
|
1171
|
unshift(@$imports, @$all); |
362
|
632
|
|
|
|
|
1224
|
$added_all = 1; |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
6645
|
100
|
|
|
|
10026
|
if (@errors) { |
367
|
1
|
|
|
|
|
4
|
require Carp; |
368
|
1
|
|
|
|
|
172
|
Carp::croak("@{errors}Can't continue after import errors"); |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
|
371
|
6644
|
|
|
|
|
9007
|
foreach $hook (@$after) { |
372
|
102
|
|
|
|
|
345
|
$hook->($class, $target); |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
6643
|
|
|
|
|
1352451
|
return 1; |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
sub exportables { |
379
|
6648
|
|
|
6648
|
1
|
7372
|
my $class = shift; |
380
|
70
|
|
|
70
|
|
566
|
no strict REFS; |
|
70
|
|
|
|
|
145
|
|
|
70
|
|
|
|
|
2727
|
|
381
|
70
|
|
|
70
|
|
1661
|
no warnings ONCE; |
|
70
|
|
|
|
|
111
|
|
|
70
|
|
|
|
|
6739
|
|
382
|
|
|
|
|
|
|
|
383
|
6648
|
|
66
|
|
|
6288
|
my $cache = ${ $class.PKG.EXPORTABLES } ||= do { |
|
6648
|
|
|
|
|
24145
|
|
384
|
1101
|
|
|
|
|
1874
|
my ($pkg, $symbols, %done, @all, %any, %tags, %hooks, @fails, @before, @after); |
385
|
1101
|
|
|
|
|
2135
|
my @pending = ($class); |
386
|
70
|
|
|
70
|
|
1822
|
no strict REFS; |
|
70
|
|
|
|
|
111
|
|
|
70
|
|
|
|
|
27445
|
|
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
# walk up inheritance tree collecting values from the @$EXPORT_ALL, |
389
|
|
|
|
|
|
|
# @$EXPORT_ANY, %$EXPORT_TAGS, %$EXPORT_HOOKS and $EXPORT_FAIL pkg |
390
|
|
|
|
|
|
|
# variables, then cache them in $EXPORT_CACHE for subsequent use |
391
|
|
|
|
|
|
|
|
392
|
1101
|
|
|
|
|
2429
|
while ($pkg = shift @pending) { |
393
|
3609
|
100
|
|
|
|
7944
|
next if $done{ $pkg }++; |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
# TODO: we could optimise here by looking for a previously |
396
|
|
|
|
|
|
|
# computed EXPORTABLES in the base class and merging it in... |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
# $EXPORT_ANY package vars are list references containing symbols, |
399
|
|
|
|
|
|
|
# which we use to populate the %any hash which maps symbols to |
400
|
|
|
|
|
|
|
# their source packages. e.g. { foo => 'My::Package' } |
401
|
|
|
|
|
|
|
# The presence of an entry in this table indicates that the symbol |
402
|
|
|
|
|
|
|
# key can be exported. The corresponding value indicates the |
403
|
|
|
|
|
|
|
# package that it must be exported from. We don't replace any |
404
|
|
|
|
|
|
|
# existing entries in the %any hash because we're working from |
405
|
|
|
|
|
|
|
# sub-class upwards to super-class, . This ensures that the |
406
|
|
|
|
|
|
|
# entries put in first by more specialised sub-classes are used |
407
|
|
|
|
|
|
|
# in preference to those defined by more general super-classes. |
408
|
3532
|
100
|
|
|
|
3255
|
if ($symbols = ${ $pkg.PKG.EXPORT_ANY }) { |
|
3532
|
|
|
|
|
11373
|
|
409
|
825
|
50
|
|
|
|
3404
|
$symbols = [ split(DELIMITER, $symbols) ] |
410
|
|
|
|
|
|
|
unless ref $symbols eq ARRAY; |
411
|
|
|
|
|
|
|
$any{ $_ } ||= $pkg |
412
|
825
|
|
66
|
|
|
13455
|
for @$symbols; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# $EXPORT_ALL is merged into @all and all symbols are mapped |
416
|
|
|
|
|
|
|
# to their packages in %any |
417
|
3532
|
100
|
|
|
|
3449
|
if ($symbols = ${ $pkg.PKG.EXPORT_ALL }) { |
|
3532
|
|
|
|
|
9010
|
|
418
|
77
|
50
|
|
|
|
336
|
$symbols = [ split(DELIMITER, $symbols) ] |
419
|
|
|
|
|
|
|
unless ref $symbols eq ARRAY; |
420
|
|
|
|
|
|
|
push( |
421
|
|
|
|
|
|
|
@all, |
422
|
77
|
|
66
|
|
|
198
|
map { $any{ $_ } ||= $pkg; $_ } |
|
854
|
|
|
|
|
2952
|
|
|
854
|
|
|
|
|
1207
|
|
423
|
|
|
|
|
|
|
@$symbols |
424
|
|
|
|
|
|
|
); |
425
|
|
|
|
|
|
|
} |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
# $EXPORT_TAGS are copied into %tags unless already defined |
428
|
3532
|
100
|
|
|
|
3279
|
if ($symbols = ${ $pkg.PKG.EXPORT_TAGS }) { |
|
3532
|
|
|
|
|
8685
|
|
429
|
|
|
|
|
|
|
$tags{ $_ } ||= $symbols->{ $_ } |
430
|
434
|
|
33
|
|
|
3970
|
for keys %$symbols; |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
# $EXPORT_HOOKS are copied into %hooks unless already defined |
434
|
|
|
|
|
|
|
# (by a more specific subclass) either as hooks or any/all items |
435
|
3532
|
100
|
|
|
|
3456
|
if ($symbols = ${ $pkg.PKG.EXPORT_HOOKS }) { |
|
3532
|
|
|
|
|
8279
|
|
436
|
|
|
|
|
|
|
$any{ $_ } or $hooks{ $_ } ||= $symbols->{ $_ } |
437
|
610
|
|
33
|
|
|
11618
|
for keys %$symbols; |
|
|
|
100
|
|
|
|
|
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
# $EXPORT_FAIL has only one value per package, but we can have |
441
|
|
|
|
|
|
|
# several packages in the class ancestry |
442
|
3532
|
100
|
|
|
|
3500
|
if ($symbols = ${ $pkg.PKG.EXPORT_FAIL }) { |
|
3532
|
|
|
|
|
8823
|
|
443
|
267
|
|
|
|
|
502
|
push(@fails, $symbols); |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
# $EXPORT_BEFORE and $EXPORT_AFTER are references to CODE or |
447
|
|
|
|
|
|
|
# ARRAY refs (of CODE refs, we assume). As we travel up from |
448
|
|
|
|
|
|
|
# subclass to superclass, we unshift() the handlers onto the |
449
|
|
|
|
|
|
|
# start of the @before/@after arrays. This ensures that the base |
450
|
|
|
|
|
|
|
# class handlers get called before subclass handlers. |
451
|
3532
|
100
|
|
|
|
3344
|
if ($symbols = ${ $pkg.PKG.EXPORT_BEFORE }) { |
|
3532
|
|
|
|
|
8701
|
|
452
|
28
|
50
|
|
|
|
140
|
unshift( |
|
|
100
|
|
|
|
|
|
453
|
|
|
|
|
|
|
@before, |
454
|
|
|
|
|
|
|
ref $symbols eq CODE ? $symbols : |
455
|
|
|
|
|
|
|
ref $symbols eq ARRAY ? @$symbols : |
456
|
|
|
|
|
|
|
croak sprintf(BAD_HANDLER, before => $symbols) |
457
|
|
|
|
|
|
|
); |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
3532
|
100
|
|
|
|
3305
|
if ($symbols = ${ $pkg.PKG.EXPORT_AFTER }) { |
|
3532
|
|
|
|
|
8286
|
|
461
|
74
|
50
|
|
|
|
471
|
unshift( |
|
|
100
|
|
|
|
|
|
462
|
|
|
|
|
|
|
@after, |
463
|
|
|
|
|
|
|
ref $symbols eq CODE ? $symbols : |
464
|
|
|
|
|
|
|
ref $symbols eq ARRAY ? @$symbols : |
465
|
|
|
|
|
|
|
croak sprintf(BAD_HANDLER, after => $symbols) |
466
|
|
|
|
|
|
|
); |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
# This is the same depth-first inheritance resolution algorithm |
470
|
|
|
|
|
|
|
# that Perl uses. We can't use the fancy heritage() method in |
471
|
|
|
|
|
|
|
# Badger::Class because of the Chicken-and-Egg dependency problem |
472
|
|
|
|
|
|
|
# between Badger::Exporter and Badger::Class |
473
|
3532
|
|
|
|
|
3379
|
push(@pending, @{$pkg.PKG.ISA}); |
|
3532
|
|
|
|
|
10266
|
|
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
|
476
|
1101
|
|
|
|
|
5908
|
[\@all, \%any, \%tags, \%hooks, \@fails, \@before, \@after]; |
477
|
|
|
|
|
|
|
}; |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
return wantarray |
480
|
6648
|
50
|
|
|
|
19024
|
? @$cache |
481
|
|
|
|
|
|
|
: $cache; |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
sub export_symbol { |
485
|
304
|
|
|
304
|
1
|
683
|
my ($self, $target, $symbol, $ref) = @_; |
486
|
70
|
|
|
70
|
|
2542
|
no strict REFS; |
|
70
|
|
|
|
|
2962
|
|
|
70
|
|
|
|
|
3399
|
|
487
|
70
|
|
|
70
|
|
355
|
no warnings ONCE; |
|
70
|
|
|
|
|
1462
|
|
|
70
|
|
|
|
|
9535
|
|
488
|
304
|
|
|
|
|
440
|
*{ $target.PKG.$symbol } = $ref; |
|
304
|
|
|
|
|
1732
|
|
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
sub export_variable { |
492
|
1761
|
|
|
1761
|
0
|
3160
|
my ($self, $name, $default) = @_; |
493
|
1761
|
|
33
|
|
|
4476
|
my $class = ref $self || $self; |
494
|
1761
|
|
|
|
|
4286
|
my $var = $class.PKG.$name; |
495
|
1761
|
|
|
|
|
1638
|
my $item; |
496
|
70
|
|
|
70
|
|
392
|
no strict REFS; |
|
70
|
|
|
|
|
1743
|
|
|
70
|
|
|
|
|
20781
|
|
497
|
|
|
|
|
|
|
|
498
|
1761
|
100
|
|
|
|
1645
|
unless (defined ($item = ${$var})) { |
|
1761
|
|
|
|
|
6862
|
|
499
|
|
|
|
|
|
|
# install the default value ref into the SCALAR $EXPORT_XXXX var |
500
|
1548
|
|
|
|
|
1837
|
${$var} = $item = $default; |
|
1548
|
|
|
|
|
2422
|
|
501
|
|
|
|
|
|
|
# then poke the symbol table to make Perl notice it's defined |
502
|
1548
|
|
|
|
|
1724
|
*{$var} = \${$var}; |
|
1548
|
|
|
|
|
2634
|
|
|
1548
|
|
|
|
|
2409
|
|
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
|
505
|
1761
|
|
|
|
|
4408
|
return $item; |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
sub export_hook_generator { |
509
|
467
|
|
|
467
|
1
|
1009
|
my $self = shift; |
510
|
467
|
|
|
|
|
586
|
my $name = shift; |
511
|
467
|
50
|
|
|
|
886
|
my $hook = @_ == 1 ? shift : [ @_ ]; |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
# do nothing if we've already got a code ref that doesn't require args |
514
|
467
|
50
|
|
|
|
893
|
return $hook |
515
|
|
|
|
|
|
|
if ref $hook eq CODE; |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
# anything else must be a list ref containing [$code_ref, $n_args] |
518
|
467
|
50
|
|
|
|
892
|
croak sprintf(BAD_HOOK, $name, $hook) |
519
|
|
|
|
|
|
|
unless ref $hook eq ARRAY; |
520
|
|
|
|
|
|
|
|
521
|
467
|
|
|
|
|
764
|
my ($code, $nargs) = @$hook; |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
# user is trying to confuse us with [$non_code_ref, ...] |
524
|
467
|
50
|
|
|
|
807
|
croak sprintf(BAD_HOOK, $name, $code) |
525
|
|
|
|
|
|
|
unless ref $code eq CODE; |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
# [$code, 0] or [$code] is fine as just $code, also reject $nargs < 0 |
528
|
467
|
50
|
33
|
|
|
1363
|
return $code |
529
|
|
|
|
|
|
|
unless $nargs && $nargs > 0; |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
# OK it's safe to proceed |
532
|
|
|
|
|
|
|
return sub { |
533
|
5255
|
|
|
5255
|
|
7877
|
my ($this, $target, $symbol, $symbols) = @_; |
534
|
5255
|
|
|
|
|
4916
|
my $n = 1; |
535
|
|
|
|
|
|
|
# check we've got enough arguments |
536
|
5255
|
50
|
|
|
|
7221
|
croak sprintf(MISSING, $symbol, sprintf(WANTED, $nargs, scalar @$symbols)) |
537
|
|
|
|
|
|
|
if @$symbols < $nargs; |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
# call the code ref with the first $nargs arguments, making sure |
540
|
|
|
|
|
|
|
# they all have defined values |
541
|
|
|
|
|
|
|
$code->( |
542
|
|
|
|
|
|
|
$this, $target, $symbol, |
543
|
|
|
|
|
|
|
( map { |
544
|
5255
|
50
|
|
|
|
8062
|
croak sprintf(MISSING, $symbol, sprintf(UNDEFINED, $n, $nargs)) |
|
5255
|
|
|
|
|
6753
|
|
545
|
|
|
|
|
|
|
unless defined $_; |
546
|
5255
|
|
|
|
|
4559
|
$n++; |
547
|
5255
|
|
|
|
|
12349
|
$_ |
548
|
|
|
|
|
|
|
} |
549
|
|
|
|
|
|
|
splice(@$symbols, 0, $nargs) |
550
|
|
|
|
|
|
|
), |
551
|
|
|
|
|
|
|
$symbols, |
552
|
|
|
|
|
|
|
); |
553
|
|
|
|
|
|
|
} |
554
|
467
|
|
|
|
|
2473
|
} |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
sub _debug { |
557
|
0
|
|
|
0
|
|
|
print STDERR @_; |
558
|
|
|
|
|
|
|
} |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
1; |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
__END__ |