line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#========================================================================================= |
2
|
|
|
|
|
|
|
package ensure ; # a pragma |
3
|
|
|
|
|
|
|
#========================================================================================= |
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
21425
|
use 5.006 ; use v5.8.8 ; # Not tested for anything less |
|
1
|
|
|
1
|
|
6
|
|
|
1
|
|
|
|
|
48
|
|
|
1
|
|
|
|
|
12
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
50
|
|
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
6
|
use strict ; |
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
60
|
|
8
|
1
|
|
|
1
|
|
6
|
use warnings ; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
76
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our $VERSION = '1.10' ; # 14-Oct-2008 |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
#========================================================================================= |
13
|
|
|
|
|
|
|
|
14
|
1
|
|
|
1
|
|
5
|
use Exporter () ; # Exporter::import used explicitly |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1112
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our @EXPORT = qw(import) ; |
17
|
|
|
|
|
|
|
our @EXPORT_OK = qw(register) ; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
#========================================================================================= |
20
|
|
|
|
|
|
|
# We work on the basis that in all entries in the symbol table have a defined {SCALAR} |
21
|
|
|
|
|
|
|
# part -- whether there is a scalar or not. |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
test_scalar_symbol() or die "*** symbol table form changed -- package 'ensure' broken\n" ; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub test_scalar_symbol { |
26
|
1
|
|
|
1
|
0
|
1
|
return defined(*{stash(__PACKAGE__)->{'test_scalar_symbol'}}{SCALAR}) ; |
|
1
|
|
|
|
|
3
|
|
27
|
|
|
|
|
|
|
} ; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
#========================================================================================= |
30
|
|
|
|
|
|
|
# Tables of packages and variables known to ensure |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
my %packages = () ; # Keys = packages registered for ensure CHECK processing |
33
|
|
|
|
|
|
|
# Values = ref:Stash for registered packages |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
my %exporters = () ; # Keys = packages which we've seen export stuff |
36
|
|
|
|
|
|
|
# Values = true => package includes IMPLICIT tag |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my %no_ensure = () ; # Keys = packages with things declared no_ensure |
39
|
|
|
|
|
|
|
# Values = [name, name, ...] |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
my %no_scalar = () ; # Keys = address of undefined scalar declared 'no ensure' |
42
|
|
|
|
|
|
|
# Values = exporting package |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
my $ensure_errors = 0 ; # Count of errors. Dies at end of ensure CHECK if != 0. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
#========================================================================================= |
47
|
|
|
|
|
|
|
# Manual registration |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
register(__PACKAGE__) ; # Register ourselves |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
sub register { # May be used, eg, to register 'main' |
52
|
2
|
|
|
2
|
0
|
3
|
my ($p) = @_ ; |
53
|
2
|
|
33
|
|
|
10
|
$packages{$p} ||= stash($p) ; |
54
|
|
|
|
|
|
|
} ; |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
#========================================================================================= |
57
|
|
|
|
|
|
|
# Two small utilities |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub err { # Issue warning message and increment $ensure_errors |
60
|
0
|
|
|
0
|
0
|
0
|
warn '+++ ensure: ', @_, "\n" ; |
61
|
0
|
|
|
|
|
0
|
return $ensure_errors++ ; |
62
|
|
|
|
|
|
|
} ; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub crunch { # Die |
65
|
0
|
|
|
0
|
0
|
0
|
die '*** ensure: ', @_, "\n" ; |
66
|
|
|
|
|
|
|
} ; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub suq { # Sort given list and ensure all entries are unique |
69
|
0
|
|
|
0
|
0
|
0
|
my %l = map { ($_, undef) } @_ ; |
|
0
|
|
|
|
|
0
|
|
70
|
0
|
|
|
|
|
0
|
return sort keys %l ; |
71
|
|
|
|
|
|
|
} ; |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
#========================================================================================= |
74
|
|
|
|
|
|
|
# ensure::import |
75
|
|
|
|
|
|
|
# ============== |
76
|
|
|
|
|
|
|
# |
77
|
|
|
|
|
|
|
# This will be invoked: |
78
|
|
|
|
|
|
|
# |
79
|
|
|
|
|
|
|
# a. when a package does 'use ensure', which: |
80
|
|
|
|
|
|
|
# |
81
|
|
|
|
|
|
|
# - registers the package for the ensure CHECK block checks. |
82
|
|
|
|
|
|
|
# |
83
|
|
|
|
|
|
|
# - imports into the package the ensure::import function. |
84
|
|
|
|
|
|
|
# |
85
|
|
|
|
|
|
|
# b. when a package which has done 'use ensure' is itself used: |
86
|
|
|
|
|
|
|
# |
87
|
|
|
|
|
|
|
# - the first time this happens, the package's exports are checked. |
88
|
|
|
|
|
|
|
# |
89
|
|
|
|
|
|
|
# - in all cases the import list extensions (:ALL :NONE :IMPLICIT) are |
90
|
|
|
|
|
|
|
# implemented, before jumping to the standard Exporter::import. |
91
|
|
|
|
|
|
|
# |
92
|
|
|
|
|
|
|
# Requires: $ep -- package which is being imported from ) passed to... |
93
|
|
|
|
|
|
|
# @imports -- import list, from "use Fred (@import) ;" ) ...Exporter::import |
94
|
|
|
|
|
|
|
# |
95
|
|
|
|
|
|
|
# Returns: nothing |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub import { |
98
|
1
|
|
|
1
|
|
11
|
my $ep = $_[0] ; |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# If we are running the import on behalf of ourselves, we register importing package. |
101
|
|
|
|
|
|
|
|
102
|
1
|
|
|
|
|
2
|
my $ip = '' ; |
103
|
1
|
50
|
|
|
|
4
|
if ($ep eq __PACKAGE__) { register($ip = scalar(caller)) ; } ; |
|
1
|
|
|
|
|
6
|
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# If this is the first time we have seen this package export stuff, we run checks |
106
|
|
|
|
|
|
|
# across the export declarations. |
107
|
|
|
|
|
|
|
|
108
|
1
|
50
|
|
|
|
8
|
my $implicit = exists($exporters{$ep}) ? $exporters{$ep} : check_exports($ep) ; |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# Now we deal with the import list, if it is not empty |
111
|
|
|
|
|
|
|
|
112
|
1
|
50
|
|
|
|
5
|
if (scalar(@_) > 1) { |
113
|
|
|
|
|
|
|
|
114
|
0
|
0
|
0
|
|
|
0
|
if ($_[1] eq ':ALL') { |
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# Importing ':ALL' -- replace ':ALL' by contents of @EXPORT and @EXPORT_OK |
117
|
|
|
|
|
|
|
|
118
|
0
|
|
|
|
|
0
|
my $st = $packages{$ep} ; |
119
|
0
|
0
|
|
|
|
0
|
splice( @_, 1, 1, suq(@{stash_value($st, '@EXPORT' ) || []}, |
|
0
|
0
|
|
|
|
0
|
|
120
|
0
|
|
|
|
|
0
|
@{stash_value($st, '@EXPORT_OK') || []}) ) ; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
elsif ( ($_[1] eq ':NONE') || (!$implicit && ($_[1] eq ':IMPLICIT')) ) { |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# Importing ':NONE' or ':IMPLICIT' when no IMPLICIT tag exists. |
125
|
|
|
|
|
|
|
|
126
|
0
|
|
|
|
|
0
|
my $i = 2 ; |
127
|
0
|
|
0
|
|
|
0
|
while (defined($_[$i]) && ($_[$i] =~ m/^!/)) { $i++ ; } ; |
|
0
|
|
|
|
|
0
|
|
128
|
|
|
|
|
|
|
|
129
|
0
|
|
|
|
|
0
|
splice(@_, 1, $i-1) ; # Drop :NONE/:IMPLICIT and following '!' |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
# Give up now if nothing left of list |
132
|
|
|
|
|
|
|
|
133
|
0
|
0
|
|
|
|
0
|
if (scalar(@_) == 1) { return ; } ; # Give up now if nothing left of list |
|
0
|
|
|
|
|
0
|
|
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
elsif ( $implicit && ($_[1] ne ':IMPLICIT') && ($_[1] !~ m/^!/) ) { |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# Exporting package has 'IMPLICIT' tag and import list a) is not empty, |
138
|
|
|
|
|
|
|
# and b) does not start ':IMPLICIT' |
139
|
|
|
|
|
|
|
# and c) does not start '!...' |
140
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
0
|
splice(@_, 1, 0, ':IMPLICIT') ; |
142
|
|
|
|
|
|
|
} ; |
143
|
|
|
|
|
|
|
} ; |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# Now we can proceed to standard import ! |
146
|
|
|
|
|
|
|
|
147
|
1
|
50
|
33
|
|
|
8
|
if (($ip eq 'main') && (scalar(@_) == 1)) |
148
|
1
|
|
|
|
|
12
|
{ return ; } ; # (Unless importing self to main, in default fashion.) |
149
|
|
|
|
|
|
|
|
150
|
0
|
|
|
|
|
0
|
goto &Exporter::import ; # As if called in the first place |
151
|
|
|
|
|
|
|
} ; |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
#========================================================================================= |
154
|
|
|
|
|
|
|
# check_exports: run checks across exports & establish whether has 'IMPLICIT' tag. |
155
|
|
|
|
|
|
|
# |
156
|
|
|
|
|
|
|
# Checks that: |
157
|
|
|
|
|
|
|
# |
158
|
|
|
|
|
|
|
# a) everything in @EXPORT & @EXPORT_OK is defined, except where declared 'no ensure' |
159
|
|
|
|
|
|
|
# |
160
|
|
|
|
|
|
|
# b) everything in %EXPORT_TAGS (other than 'IMPLICIT') must appear in @EXPORT or |
161
|
|
|
|
|
|
|
# @EXPORT_OK. |
162
|
|
|
|
|
|
|
# |
163
|
|
|
|
|
|
|
# c) everything in any 'IMPLICIT' tag must appear in @EXPORT. |
164
|
|
|
|
|
|
|
# |
165
|
|
|
|
|
|
|
# d) everything in @EXPORT_FAIL must appear in @EXPORT or @EXPORT_OK. |
166
|
|
|
|
|
|
|
# |
167
|
|
|
|
|
|
|
# Sets $exporters{$ep} = true iff there is an 'IMPLICIT' tag, false otherwise. |
168
|
|
|
|
|
|
|
# |
169
|
|
|
|
|
|
|
# NB: to be called the first time the package is seen exporting stuff. |
170
|
|
|
|
|
|
|
# |
171
|
|
|
|
|
|
|
# Requires: $ep -- name of package which is exporting stuff -- default is caller ! |
172
|
|
|
|
|
|
|
# |
173
|
|
|
|
|
|
|
# Returns: true => exporting package has an 'IMPLICIT' tag |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub check_exports { |
176
|
1
|
|
|
1
|
0
|
2
|
my ($ep) = @_ ; |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
#---------------------------------------------------------------------------------- |
179
|
|
|
|
|
|
|
# Get the stash for the exporting package -- must be registered already !! |
180
|
|
|
|
|
|
|
|
181
|
1
|
50
|
|
|
|
4
|
my $st = $packages{$ep} |
182
|
|
|
|
|
|
|
or crunch "check_exports: package $ep not registered" ; |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
#---------------------------------------------------------------------------------- |
185
|
|
|
|
|
|
|
# a) check contents of @EXPORT & @EXPORT_OK, given any 'no ensure' declarations |
186
|
|
|
|
|
|
|
# |
187
|
|
|
|
|
|
|
# Names in @EXPORT & @EXPORT_OK are checked thus: |
188
|
|
|
|
|
|
|
# |
189
|
|
|
|
|
|
|
# * name -- requires: glob{CODE}, SCALAR or REF |
190
|
|
|
|
|
|
|
# * $name -- requires: glob{SCALAR} to have a defined value |
191
|
|
|
|
|
|
|
# * @name -- requires: glob{ARRAY} |
192
|
|
|
|
|
|
|
# * %name -- requires: glob{HASH} |
193
|
|
|
|
|
|
|
# * &name -- requires: glob{CODE} |
194
|
|
|
|
|
|
|
# * *name -- requires: the name to exist as glob |
195
|
|
|
|
|
|
|
# |
196
|
|
|
|
|
|
|
# Note that the undecorated name works for 5.10.0 and onwards constant values. |
197
|
|
|
|
|
|
|
# |
198
|
|
|
|
|
|
|
# Note that for $name this means that it must have some value other than 'undef'. |
199
|
|
|
|
|
|
|
# (This is because it is not possible to distinguish no $name declaration at all |
200
|
|
|
|
|
|
|
# from a declaration which leaves the value undefined.) |
201
|
|
|
|
|
|
|
# |
202
|
|
|
|
|
|
|
# Names declared 'no ensure' *must* fail the above. |
203
|
|
|
|
|
|
|
|
204
|
1
|
|
50
|
|
|
3
|
my $exp = stash_value($st, '@EXPORT' ) || [] ; |
205
|
1
|
|
50
|
|
|
3
|
my $eok = stash_value($st, '@EXPORT_OK') || [] ; |
206
|
1
|
|
50
|
|
|
6
|
my $nen = $no_ensure{$ep} || [] ; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# Collect all exports (from EXPORT and EXPORT_OK) & all 'no ensure' names. |
209
|
|
|
|
|
|
|
|
210
|
1
|
|
|
|
|
2
|
my %all_exports = map { ($_, 1) } @$exp, @$eok ; |
|
2
|
|
|
|
|
7
|
|
211
|
1
|
|
|
|
|
2
|
my %undefined = map { ($_, 1) } @$nen ; |
|
0
|
|
|
|
|
0
|
|
212
|
|
|
|
|
|
|
|
213
|
1
|
|
|
|
|
8
|
foreach my $name (sort keys %all_exports) { |
214
|
2
|
|
|
|
|
5
|
my ($id, $t) = undecorate($name) ; |
215
|
|
|
|
|
|
|
|
216
|
2
|
|
|
|
|
7
|
my $rv = $st->{$id} ; |
217
|
2
|
|
|
|
|
4
|
my $def = defined($rv) ; |
218
|
2
|
50
|
|
|
|
5
|
if ($def) { |
219
|
2
|
50
|
|
|
|
5
|
if (!ref($rv)) { |
220
|
2
|
50
|
|
|
|
8
|
if ($t eq 'SCALAR') { $def = defined(${$rv = *$rv{$t}}) ; } |
|
0
|
50
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
221
|
2
|
|
50
|
|
|
13
|
elsif ($t ne 'GLOB') { $def = defined(*$rv{$t || 'CODE'}) ; } ; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
else { |
224
|
0
|
|
0
|
|
|
0
|
$def = ($t eq '') || ($t eq 'CODE') ; |
225
|
|
|
|
|
|
|
} ; |
226
|
|
|
|
|
|
|
} ; |
227
|
|
|
|
|
|
|
|
228
|
2
|
50
|
33
|
|
|
25
|
if (exists($undefined{$name}) || (($t eq 'CODE') && exists($undefined{$id})) |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
229
|
|
|
|
|
|
|
|| (($t eq '') && exists($undefined{'&'.$id}))) { |
230
|
0
|
0
|
|
|
|
0
|
if ($def) { |
|
|
0
|
|
|
|
|
|
231
|
0
|
|
|
|
|
0
|
err "'$name' in '$ep\' is declared 'no ensure', but is defined" ; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
elsif ($t eq 'SCALAR') { |
234
|
1
|
0
|
|
1
|
|
7
|
if (!defined($rv)) { no strict 'refs' ; $rv = \${"$ep\:\:$id"} ; } ; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1085
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
235
|
0
|
|
|
|
|
0
|
$no_scalar{"$rv"} = $ep ; |
236
|
|
|
|
|
|
|
} ; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
else { |
239
|
2
|
50
|
|
|
|
8
|
if (!$def) { |
240
|
0
|
|
|
|
|
0
|
err "'$name' is exported by '$ep', but is not defined" ; |
241
|
|
|
|
|
|
|
} ; |
242
|
|
|
|
|
|
|
} ; |
243
|
|
|
|
|
|
|
} ; |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
#---------------------------------------------------------------------------------- |
246
|
|
|
|
|
|
|
# b) check that everything in the %EXPORT_TAGS is in @EXPORT or @EXPORT_OK |
247
|
|
|
|
|
|
|
# (except for any IMPLICIT tag). |
248
|
|
|
|
|
|
|
# c) check that everything in any %EXPORT_TAGS{IMPLICIT} is in @EXPORT |
249
|
|
|
|
|
|
|
|
250
|
1
|
|
|
|
|
3
|
my $implicit = 0 ; |
251
|
|
|
|
|
|
|
|
252
|
1
|
50
|
|
|
|
3
|
if (my $etg = stash_value($st, '%EXPORT_TAGS')) { |
253
|
0
|
|
|
|
|
0
|
foreach my $tag (sort keys %$etg) { |
254
|
0
|
0
|
|
|
|
0
|
if ($tag ne 'IMPLICIT') { |
255
|
0
|
|
|
|
|
0
|
foreach my $name (suq @{$$etg{$tag}}) { |
|
0
|
|
|
|
|
0
|
|
256
|
0
|
0
|
|
|
|
0
|
if (!exists($all_exports{$name})) { |
257
|
0
|
|
|
|
|
0
|
err "'$name' is in '$ep\'s '$tag' tag list,", |
258
|
|
|
|
|
|
|
" but not in \@EXPORT or \@EXPORT_OK" ; |
259
|
|
|
|
|
|
|
} ; |
260
|
|
|
|
|
|
|
} ; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
else { |
263
|
0
|
|
|
|
|
0
|
$implicit = 1 ; |
264
|
0
|
|
|
|
|
0
|
my %default = map { ($_, 1) } @$exp ; # That which is in @EXPORT |
|
0
|
|
|
|
|
0
|
|
265
|
0
|
|
|
|
|
0
|
foreach my $name (suq @{$$etg{IMPLICIT}}) { |
|
0
|
|
|
|
|
0
|
|
266
|
0
|
0
|
|
|
|
0
|
if (!exists($default{$name})) { |
267
|
0
|
|
|
|
|
0
|
err "'$name' is in '$ep\'s 'IMPLICIT' tag list, but not in \@EXPORT" ; |
268
|
|
|
|
|
|
|
} ; |
269
|
|
|
|
|
|
|
} ; |
270
|
|
|
|
|
|
|
} ; |
271
|
|
|
|
|
|
|
} ; |
272
|
|
|
|
|
|
|
} ; |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
#---------------------------------------------------------------------------------- |
275
|
|
|
|
|
|
|
# d) check that everything in the @EXPORT_FAIL is in @EXPORT or @EXPORT_OK |
276
|
|
|
|
|
|
|
|
277
|
1
|
50
|
|
|
|
4
|
if (my $ef = stash_value($st, '@EXPORT_FAIL')) { |
278
|
0
|
|
|
|
|
0
|
foreach my $name (suq(@$ef)) { |
279
|
0
|
0
|
|
|
|
0
|
if (!exists($all_exports{$name})) { |
280
|
0
|
|
|
|
|
0
|
err "'$name' is in '$ep\'s \@EXPORT_FAIL, but not in \@EXPORT or \@EXPORT_OK" ; |
281
|
|
|
|
|
|
|
} ; |
282
|
|
|
|
|
|
|
} ; |
283
|
|
|
|
|
|
|
} ; |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
#---------------------------------------------------------------------------------- |
286
|
|
|
|
|
|
|
# Done -- record exporting package and whether it has an 'IMPLICIT' tag |
287
|
|
|
|
|
|
|
|
288
|
1
|
|
|
|
|
5
|
return $exporters{$ep} = $implicit ; |
289
|
|
|
|
|
|
|
} ; |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
#========================================================================================= |
292
|
|
|
|
|
|
|
# ensure::unimport |
293
|
|
|
|
|
|
|
# ================ |
294
|
|
|
|
|
|
|
# |
295
|
|
|
|
|
|
|
# unimport: mechanics for no ensure qw(....) ; |
296
|
|
|
|
|
|
|
# |
297
|
|
|
|
|
|
|
# no ensure qw(name $name @name %name &name *name) |
298
|
|
|
|
|
|
|
# |
299
|
|
|
|
|
|
|
# The export checks use the full name, complete with decoration. So if you want to |
300
|
|
|
|
|
|
|
# export an undefined '@name' (for example) you need to be specific. |
301
|
|
|
|
|
|
|
# |
302
|
|
|
|
|
|
|
# The CHECK block ignores the decoration. You can say, for example, that you expect |
303
|
|
|
|
|
|
|
# '$name' to be undefined, the effect is that it is deemed OK if nothing at all is |
304
|
|
|
|
|
|
|
# defined for 'name'. |
305
|
|
|
|
|
|
|
# |
306
|
|
|
|
|
|
|
# Requires: $self = ourselves (__PACKAGE__) ! |
307
|
|
|
|
|
|
|
# list of possibly decorated names |
308
|
|
|
|
|
|
|
# |
309
|
|
|
|
|
|
|
# Returns: nothing |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
sub unimport { |
312
|
1
|
|
|
1
|
|
3344
|
shift(@_) ; # Discard self |
313
|
1
|
|
50
|
|
|
4
|
push @{$no_ensure{scalar(caller)} ||= []}, @_ ; |
|
1
|
|
|
|
|
11
|
|
314
|
1
|
|
|
|
|
581
|
return 1 ; |
315
|
|
|
|
|
|
|
} ; |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
#========================================================================================= |
318
|
|
|
|
|
|
|
# Post Compile-Time Checks -- the ensure CHECK block |
319
|
|
|
|
|
|
|
# ================================================== |
320
|
|
|
|
|
|
|
# |
321
|
|
|
|
|
|
|
# For all packages that have been registered, we look for any completely undefined |
322
|
|
|
|
|
|
|
# simple names -- which we treat as undefined subroutine errors, unless declared |
323
|
|
|
|
|
|
|
# 'no ensure'. |
324
|
|
|
|
|
|
|
# |
325
|
|
|
|
|
|
|
# By simple we mean names starting '_' or alphabetic, excluding a small number of |
326
|
|
|
|
|
|
|
# well known names. |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
CHECK { |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# These may appear undefined in the stash or are otherwise not worth checking. |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# a and b appear if sort is used ? |
333
|
|
|
|
|
|
|
# MODIFY_xxx_ATTRIBUTES appear and are undefined if a variable is declared ': shared'. |
334
|
|
|
|
|
|
|
|
335
|
1
|
|
|
1
|
|
6
|
my %except = map { ($_, 1) } (qw(a b BEGIN UNITCHECK CHECK INIT END |
|
12
|
|
|
|
|
30
|
|
336
|
|
|
|
|
|
|
DESTROY AUTOLOAD |
337
|
|
|
|
|
|
|
MODIFY_SCALAR_ATTRIBUTES |
338
|
|
|
|
|
|
|
MODIFY_ARRAY_ATTRIBUTES |
339
|
|
|
|
|
|
|
MODIFY_HASH_ATTRIBUTES)) ; |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
# Run checks across all registered packages |
342
|
|
|
|
|
|
|
|
343
|
1
|
|
|
|
|
13
|
foreach my $pkg (sort keys(%packages)) { |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
# Debug introduces a number of undefined things in 'main', which just get in the way |
346
|
|
|
|
|
|
|
|
347
|
2
|
100
|
33
|
|
|
25
|
if (($^D || $^P) && ($pkg eq 'main')) { |
|
|
|
66
|
|
|
|
|
348
|
1
|
|
|
|
|
14
|
print STDERR "+++ NB: Debug prevents ensure check for '$pkg'\n" ; |
349
|
1
|
|
|
|
|
3
|
next ; |
350
|
|
|
|
|
|
|
} ; |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
# Collect any 'no ensure' names |
353
|
|
|
|
|
|
|
|
354
|
1
|
|
|
|
|
3
|
my %undefined = () ; |
355
|
1
|
50
|
|
|
|
4
|
if (exists($no_ensure{$pkg})) { |
356
|
0
|
|
|
|
|
0
|
%undefined = map { s/^[\$@%&*]// ; ($_, 1) } @{$no_ensure{$pkg}} ; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
357
|
|
|
|
|
|
|
} ; |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# Check the stash for this package |
360
|
|
|
|
|
|
|
|
361
|
1
|
|
|
|
|
3
|
my $stash = $packages{$pkg} ; # Stash for package |
362
|
|
|
|
|
|
|
|
363
|
1
|
|
|
|
|
11
|
NAME: foreach my $name (sort keys %$stash) { |
364
|
16
|
100
|
66
|
|
|
181
|
if (($name =~ m/^(?:__|_?\W|_?\d)/) # Ignore names which are not simple... |
|
|
|
66
|
|
|
|
|
365
|
|
|
|
|
|
|
|| $except{$name} # ...or which are exceptional |
366
|
|
|
|
|
|
|
|| $undefined{$name}) # ...or which are declared 'no ensure' |
367
|
2
|
|
|
|
|
5
|
{ next NAME ; } ; |
368
|
|
|
|
|
|
|
|
369
|
14
|
|
|
|
|
32
|
my $rv = $stash->{$name} ; # Get the stash entry |
370
|
|
|
|
|
|
|
|
371
|
14
|
50
|
|
|
|
27
|
next if !defined($rv); # Ignore undefined stash entries |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
# OK if stash entry is ref() (=> is 5.10.0 or later 'constant') |
374
|
|
|
|
|
|
|
# or if have a {CODE} value -- these are the commonest cases ! |
375
|
|
|
|
|
|
|
|
376
|
14
|
100
|
66
|
|
|
56
|
if (ref($rv) || defined(*$rv{CODE})) { next NAME ; } ; |
|
11
|
|
|
|
|
30
|
|
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
# OK if glob has a defined {SCALAR} value |
379
|
|
|
|
|
|
|
# or if undefined {SCALAR} is import of an exported 'no ensure' |
380
|
|
|
|
|
|
|
|
381
|
3
|
|
|
|
|
7
|
my $rs = *$rv{SCALAR} ; |
382
|
3
|
100
|
66
|
|
|
19
|
if (defined($rs) && (defined($$rs) || exists($no_scalar{"$rs"}))) { next NAME ; } ; |
|
1
|
|
33
|
|
|
3
|
|
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
# OK if glob has at least one of these other types of value. |
385
|
|
|
|
|
|
|
|
386
|
2
|
|
|
|
|
3
|
foreach my $type (qw(ARRAY HASH IO FORMAT)) { |
387
|
2
|
50
|
|
|
|
23
|
if (defined(*$rv{$type})) { next NAME ; } ; |
|
2
|
|
|
|
|
6
|
|
388
|
|
|
|
|
|
|
} ; |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
# Generate error for name with no defined value |
391
|
|
|
|
|
|
|
|
392
|
0
|
|
|
|
|
0
|
err "$pkg\:\:$name is undefined" ; |
393
|
|
|
|
|
|
|
} ; |
394
|
|
|
|
|
|
|
} ; |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
# Now... if any errors seen by ensure, give up ! |
397
|
|
|
|
|
|
|
|
398
|
1
|
50
|
|
|
|
943
|
if ($ensure_errors) { crunch "$ensure_errors errors found" ; } ; |
|
0
|
|
|
|
|
0
|
|
399
|
|
|
|
|
|
|
} ; |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
#========================================================================================= |
402
|
|
|
|
|
|
|
# Stash Access |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------- |
405
|
|
|
|
|
|
|
# stash: get ref:Stash for given package |
406
|
|
|
|
|
|
|
# |
407
|
|
|
|
|
|
|
# Requires: $pkg -- package name -- no trailing '::' -- ASSUMED VALID |
408
|
|
|
|
|
|
|
# |
409
|
|
|
|
|
|
|
# Returns: ref:Stash -- i.e. hash containing symbols for given package |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
sub stash { |
412
|
3
|
|
|
3
|
0
|
4
|
my ($pkg) = @_ ; |
413
|
1
|
|
|
1
|
|
6
|
no strict qw(refs) ; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
334
|
|
414
|
3
|
0
|
|
|
|
3
|
return *{$pkg.'::'}{HASH} or crunch "cannot find package '$pkg'" ; |
|
3
|
|
|
|
|
23
|
|
415
|
|
|
|
|
|
|
} ; |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------- |
418
|
|
|
|
|
|
|
# stash_value: get value of SCALAR, ARRAY or HASH from given package/stash |
419
|
|
|
|
|
|
|
# |
420
|
|
|
|
|
|
|
# Requires: $st -- ref:Stash (as returned by stash()) |
421
|
|
|
|
|
|
|
# $name -- decorated name of value |
422
|
|
|
|
|
|
|
# |
423
|
|
|
|
|
|
|
# Returns: value -- if SCALAR and scalar is defined |
424
|
|
|
|
|
|
|
# ref:Value -- if ARRAY, HASH and value is defined |
425
|
|
|
|
|
|
|
# undef -- name not found or value not defined |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
sub stash_value { |
428
|
4
|
|
|
4
|
0
|
6
|
my ($st, $name) = @_ ; |
429
|
|
|
|
|
|
|
|
430
|
4
|
|
|
|
|
8
|
my ($id, $type) = undecorate($name) ; |
431
|
4
|
|
|
|
|
9
|
my $rv = $st->{$id} ; |
432
|
4
|
100
|
|
|
|
10
|
if (defined($rv)) { |
433
|
2
|
50
|
|
|
|
4
|
if (!ref($rv)) { |
434
|
2
|
|
|
|
|
4
|
$rv = *$rv{$type} ; |
435
|
2
|
50
|
33
|
|
|
15
|
if (defined($rv) && ($type eq 'SCALAR')) { $rv = $$rv ; } ; |
|
0
|
|
|
|
|
0
|
|
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
else { |
438
|
0
|
|
|
|
|
0
|
$rv = undef ; # ref:SCALAR or ref:REF => 5.10.0 type constant |
439
|
|
|
|
|
|
|
} ; |
440
|
|
|
|
|
|
|
} ; |
441
|
|
|
|
|
|
|
|
442
|
4
|
|
|
|
|
16
|
return $rv ; |
443
|
|
|
|
|
|
|
} ; |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------- |
446
|
|
|
|
|
|
|
# undecorate: remove decoration from name and return explicit type, if any |
447
|
|
|
|
|
|
|
# |
448
|
|
|
|
|
|
|
# Requires: $name -- possibly decorated name |
449
|
|
|
|
|
|
|
# |
450
|
|
|
|
|
|
|
# Returns: ($id, $type) -- $id = name less any decoration |
451
|
|
|
|
|
|
|
# $type = if decorated: SCALAR, ARRAY, HASH, CODE or GLOB |
452
|
|
|
|
|
|
|
# otherwise: '' |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
my %TYPE = qw($ SCALAR @ ARRAY % HASH & CODE * GLOB) ; |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
sub undecorate { |
457
|
6
|
|
|
6
|
0
|
9
|
my ($id) = @_ ; |
458
|
6
|
|
|
|
|
8
|
my $type = '' ; |
459
|
6
|
100
|
|
|
|
25
|
if ($id =~ s/^([\$@%&*])//) { $type = $TYPE{$1} ; } ; |
|
4
|
|
|
|
|
10
|
|
460
|
6
|
|
|
|
|
16
|
return ($id, $type) ; |
461
|
|
|
|
|
|
|
} ; |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
#_________________________________________________________________________________________ |
464
|
|
|
|
|
|
|
1 ; # OK -- end of ensure |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
__END__ |