line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Module::ExtractUse; |
2
|
|
|
|
|
|
|
|
3
|
12
|
|
|
12
|
|
978283
|
use strict; |
|
12
|
|
|
|
|
132
|
|
|
12
|
|
|
|
|
420
|
|
4
|
12
|
|
|
12
|
|
69
|
use warnings; |
|
12
|
|
|
|
|
22
|
|
|
12
|
|
|
|
|
356
|
|
5
|
12
|
|
|
12
|
|
277
|
use 5.008; |
|
12
|
|
|
|
|
40
|
|
6
|
|
|
|
|
|
|
|
7
|
12
|
|
|
12
|
|
6564
|
use Pod::Strip; |
|
12
|
|
|
|
|
397737
|
|
|
12
|
|
|
|
|
510
|
|
8
|
12
|
|
|
12
|
|
16206
|
use Parse::RecDescent 1.967009; |
|
12
|
|
|
|
|
529537
|
|
|
12
|
|
|
|
|
86
|
|
9
|
12
|
|
|
12
|
|
34261
|
use Module::ExtractUse::Grammar; |
|
12
|
|
|
|
|
51
|
|
|
12
|
|
|
|
|
1421
|
|
10
|
12
|
|
|
12
|
|
122
|
use Carp; |
|
12
|
|
|
|
|
29
|
|
|
12
|
|
|
|
|
26799
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.344'; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# ABSTRACT: Find out what modules are used |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
#$::RD_TRACE=1; |
16
|
|
|
|
|
|
|
#$::RD_HINT=1; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub new { |
21
|
146
|
|
|
146
|
1
|
263058
|
my $class=shift; |
22
|
146
|
|
|
|
|
748
|
return bless { |
23
|
|
|
|
|
|
|
found=>{}, |
24
|
|
|
|
|
|
|
files=>0, |
25
|
|
|
|
|
|
|
},$class; |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# Regular expression to detect eval |
30
|
|
|
|
|
|
|
# On newer perl, you can use named capture groups and (?&name) for recursive regex |
31
|
|
|
|
|
|
|
# However, it requires perl newer than 5.008 declared as requirement in this module |
32
|
|
|
|
|
|
|
my $re_block; |
33
|
|
|
|
|
|
|
$re_block = qr { |
34
|
|
|
|
|
|
|
( # eval BLOCK, corresponding to the group 10 in the entire regex |
35
|
|
|
|
|
|
|
\{ |
36
|
|
|
|
|
|
|
((?: |
37
|
|
|
|
|
|
|
(?> [^{}]+ ) # Non-braces without backtracking |
38
|
|
|
|
|
|
|
| |
39
|
|
|
|
|
|
|
(??{$re_block}) # Recurse to group 10 |
40
|
|
|
|
|
|
|
)*) |
41
|
|
|
|
|
|
|
\} |
42
|
|
|
|
|
|
|
) |
43
|
|
|
|
|
|
|
}xs; |
44
|
|
|
|
|
|
|
my $re = qr{ |
45
|
|
|
|
|
|
|
\G(.*?) # group 1 |
46
|
|
|
|
|
|
|
eval |
47
|
|
|
|
|
|
|
(?: |
48
|
|
|
|
|
|
|
(?:\s+ |
49
|
|
|
|
|
|
|
(?: |
50
|
|
|
|
|
|
|
qq?\((.*?)\) # eval q(), group 2 |
51
|
|
|
|
|
|
|
| |
52
|
|
|
|
|
|
|
qq?\[(.*?)\] # eval q[], group 3 |
53
|
|
|
|
|
|
|
| |
54
|
|
|
|
|
|
|
qq?{(.*?)} # eval q{}, group 4 |
55
|
|
|
|
|
|
|
| |
56
|
|
|
|
|
|
|
qq?<(.*?)> # eval q<>, group 5 |
57
|
|
|
|
|
|
|
| |
58
|
|
|
|
|
|
|
qq?(\S)(.*?)\6 # eval q'' or so, group 6, group 7 |
59
|
|
|
|
|
|
|
) |
60
|
|
|
|
|
|
|
) |
61
|
|
|
|
|
|
|
| |
62
|
|
|
|
|
|
|
(?:\s*(?: |
63
|
|
|
|
|
|
|
(?:(['"])(.*?)\8) # eval '' or eval "", group 8, group 9 |
64
|
|
|
|
|
|
|
| |
65
|
|
|
|
|
|
|
( # eval BLOCK, group 10 |
66
|
|
|
|
|
|
|
\{ |
67
|
|
|
|
|
|
|
((?: # group 11 |
68
|
|
|
|
|
|
|
(?> [^{}]+ ) # Non-braces without backtracking |
69
|
|
|
|
|
|
|
| |
70
|
|
|
|
|
|
|
(??{$re_block}) # Recurse to group 10 |
71
|
|
|
|
|
|
|
)*) |
72
|
|
|
|
|
|
|
\} |
73
|
|
|
|
|
|
|
) |
74
|
|
|
|
|
|
|
)) |
75
|
|
|
|
|
|
|
) |
76
|
|
|
|
|
|
|
}xs; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub extract_use { |
79
|
383
|
|
|
383
|
1
|
16498
|
my $self=shift; |
80
|
383
|
|
|
|
|
710
|
my $code_to_parse=shift; |
81
|
|
|
|
|
|
|
|
82
|
383
|
|
|
|
|
694
|
my $podless; |
83
|
383
|
|
|
|
|
2629
|
my $pod_parser=Pod::Strip->new; |
84
|
383
|
|
|
|
|
17434
|
$pod_parser->output_string(\$podless); |
85
|
383
|
50
|
|
|
|
36756
|
$pod_parser->parse_characters(1) if $pod_parser->can('parse_characters'); |
86
|
383
|
100
|
|
|
|
3555
|
if (ref($code_to_parse) eq 'SCALAR') { |
87
|
379
|
|
|
|
|
1352
|
$pod_parser->parse_string_document($$code_to_parse); |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
else { |
90
|
4
|
|
|
|
|
31
|
$pod_parser->parse_file($code_to_parse); |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# Strip obvious comments. |
94
|
383
|
|
|
|
|
132776
|
$podless =~ s/(^|[\};])\s*#.*$/$1/mg; |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# Strip __(DATA|END)__ sections. |
97
|
383
|
|
|
|
|
930
|
$podless =~ s/\n__(?:DATA|END)__\b.*$//s; |
98
|
|
|
|
|
|
|
|
99
|
383
|
|
|
|
|
652
|
my @statements; |
100
|
383
|
|
|
|
|
3002
|
while($podless =~ /$re/gc) { |
101
|
|
|
|
|
|
|
# to keep parsing time short, split code in statements |
102
|
|
|
|
|
|
|
# (I know that this is not very exact, patches welcome!) |
103
|
51
|
|
|
|
|
156
|
my $pre = $1; |
104
|
51
|
|
|
|
|
111
|
my $eval = join('', grep { defined $_ } ($2, $3, $4, $5, $7, $9, $11)); |
|
357
|
|
|
|
|
749
|
|
105
|
51
|
|
|
|
|
166
|
push @statements, map { [ 0, $_ ] } split(/;/, $pre); # non-eval context |
|
131
|
|
|
|
|
260
|
|
106
|
51
|
|
|
|
|
184
|
push @statements, map { [ 1, $_ ] } split(/;/, $eval); # eval context |
|
100
|
|
|
|
|
416
|
|
107
|
|
|
|
|
|
|
} |
108
|
383
|
|
100
|
|
|
2772
|
push @statements, map { [ 0, $_ ] } split(/;/, substr($podless, pos($podless) || 0)); # non-eval context |
|
855
|
|
|
|
|
2216
|
|
109
|
|
|
|
|
|
|
|
110
|
383
|
|
|
|
|
955
|
foreach my $statement_ (@statements) { |
111
|
1086
|
|
|
|
|
2754
|
my ($eval, $statement) = @$statement_; |
112
|
1086
|
|
|
|
|
4113
|
$statement=~s/\n+/ /gs; |
113
|
1086
|
|
|
|
|
2117
|
my $result; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# now that we've got some code containing 'use' or 'require', |
116
|
|
|
|
|
|
|
# parse it! (using different entry point to save some more |
117
|
|
|
|
|
|
|
# time) |
118
|
|
|
|
|
|
|
my $type; |
119
|
1086
|
100
|
|
|
|
8637
|
if ($statement=~m/require_module|use_module|use_package_optimistically/) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
120
|
69
|
|
|
|
|
651
|
$statement=~s/^(.*?)\b(\S+(?:require_module|use_module|use_package_optimistically)\([^)]*\))/$2/; |
121
|
69
|
50
|
66
|
|
|
363
|
next if $1 && $1 =~ /->\s*$/; |
122
|
69
|
|
|
|
|
137
|
eval { |
123
|
69
|
|
|
|
|
716
|
my $parser=Module::ExtractUse::Grammar->new(); |
124
|
69
|
|
|
|
|
937
|
$result=$parser->token_module_runtime($statement); |
125
|
|
|
|
|
|
|
}; |
126
|
69
|
100
|
|
|
|
21220
|
$type = $statement =~ m/require/ ? 'require' : 'use'; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
elsif ($statement=~/\buse/) { |
129
|
289
|
|
|
|
|
1440
|
$statement=~s/^(.*?)use\b/use/; |
130
|
289
|
100
|
100
|
|
|
1311
|
next if $1 && $1 =~ /->\s*$/; |
131
|
286
|
|
|
|
|
506
|
eval { |
132
|
286
|
|
|
|
|
1600
|
my $parser=Module::ExtractUse::Grammar->new(); |
133
|
286
|
|
|
|
|
3045
|
$result=$parser->token_use($statement.';'); |
134
|
|
|
|
|
|
|
}; |
135
|
286
|
|
|
|
|
60658
|
$type = 'use'; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
elsif ($statement=~/\brequire/) { |
138
|
54
|
|
|
|
|
288
|
$statement=~s/^(.*?)require\b/require/s; |
139
|
54
|
100
|
100
|
|
|
325
|
next if $1 && $1 =~ /->\s*$/; |
140
|
51
|
|
|
|
|
103
|
eval { |
141
|
51
|
|
|
|
|
273
|
my $parser=Module::ExtractUse::Grammar->new(); |
142
|
51
|
|
|
|
|
572
|
$result=$parser->token_require($statement.';'); |
143
|
|
|
|
|
|
|
}; |
144
|
51
|
|
|
|
|
10313
|
$type = 'require'; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
elsif ($statement=~/\bno/) { |
147
|
41
|
|
|
|
|
179
|
$statement=~s/^(.*?)no\b/no/s; |
148
|
41
|
50
|
66
|
|
|
180
|
next if $1 && $1 =~ /->\s*$/; |
149
|
41
|
|
|
|
|
66
|
eval { |
150
|
41
|
|
|
|
|
223
|
my $parser=Module::ExtractUse::Grammar->new(); |
151
|
41
|
|
|
|
|
394
|
$result=$parser->token_no($statement.';'); |
152
|
|
|
|
|
|
|
}; |
153
|
41
|
|
|
|
|
7742
|
$type = 'no'; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
elsif ($statement=~m/load_class|try_load_class|load_first_existing_class|load_optional_class/) { |
156
|
73
|
|
|
|
|
658
|
$statement=~s/^(.*?)\b(\S+(?:load_class|try_load_class|load_first_existing_class|load_optional_class)\([^)]*\))/$2/; |
157
|
73
|
50
|
66
|
|
|
268
|
next if $1 && $1 =~ /->\s*$/; |
158
|
73
|
|
|
|
|
127
|
eval { |
159
|
73
|
|
|
|
|
571
|
my $parser=Module::ExtractUse::Grammar->new(); |
160
|
73
|
|
|
|
|
724
|
$result = $parser->token_class_load($statement.';'); |
161
|
|
|
|
|
|
|
}; |
162
|
73
|
|
|
|
|
13815
|
$type = 'require'; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
1080
|
100
|
|
|
|
3123
|
next unless $result; |
166
|
|
|
|
|
|
|
|
167
|
345
|
|
|
|
|
1856
|
foreach (split(/\s+/,$result)) { |
168
|
405
|
100
|
|
|
|
1876
|
$self->_add($_, $eval, $type) if($_); |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# increment file counter |
173
|
383
|
|
|
|
|
1368
|
$self->_inc_files; |
174
|
|
|
|
|
|
|
|
175
|
383
|
|
|
|
|
8043
|
return $self; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
sub used { |
181
|
18
|
|
|
18
|
1
|
5972
|
my $self=shift; |
182
|
18
|
|
|
|
|
34
|
my $key=shift; |
183
|
18
|
100
|
|
|
|
134
|
return $self->{found}{$key} if ($key); |
184
|
1
|
|
|
|
|
3
|
return $self->{found}; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub used_in_eval { |
189
|
18
|
|
|
18
|
1
|
592
|
my $self=shift; |
190
|
18
|
|
|
|
|
35
|
my $key=shift; |
191
|
18
|
100
|
|
|
|
111
|
return $self->{found_in_eval}{$key} if ($key); |
192
|
1
|
|
|
|
|
3
|
return $self->{found_in_eval}; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub used_out_of_eval { |
197
|
18
|
|
|
18
|
1
|
576
|
my $self=shift; |
198
|
18
|
|
|
|
|
37
|
my $key=shift; |
199
|
18
|
100
|
|
|
|
96
|
return $self->{found_not_in_eval}{$key} if ($key); |
200
|
1
|
|
|
|
|
4
|
return $self->{found_not_in_eval}; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
sub required { |
205
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
206
|
0
|
|
|
|
|
0
|
my $key=shift; |
207
|
0
|
0
|
|
|
|
0
|
return $self->{require}{$key} if ($key); |
208
|
0
|
|
|
|
|
0
|
return $self->{require}; |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub required_in_eval { |
213
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
214
|
0
|
|
|
|
|
0
|
my $key=shift; |
215
|
0
|
0
|
|
|
|
0
|
return $self->{require_in_eval}{$key} if ($key); |
216
|
0
|
|
|
|
|
0
|
return $self->{require_in_eval}; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub required_out_of_eval { |
221
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
222
|
0
|
|
|
|
|
0
|
my $key=shift; |
223
|
0
|
0
|
|
|
|
0
|
return $self->{require_not_in_eval}{$key} if ($key); |
224
|
0
|
|
|
|
|
0
|
return $self->{require_not_in_eval}; |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub noed { |
229
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
230
|
0
|
|
|
|
|
0
|
my $key=shift; |
231
|
0
|
0
|
|
|
|
0
|
return $self->{no}{$key} if ($key); |
232
|
0
|
|
|
|
|
0
|
return $self->{no}; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub noed_in_eval { |
237
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
238
|
0
|
|
|
|
|
0
|
my $key=shift; |
239
|
0
|
0
|
|
|
|
0
|
return $self->{no_in_eval}{$key} if ($key); |
240
|
0
|
|
|
|
|
0
|
return $self->{no_in_eval}; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
sub noed_out_of_eval { |
245
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
246
|
0
|
|
|
|
|
0
|
my $key=shift; |
247
|
0
|
0
|
|
|
|
0
|
return $self->{no_not_in_eval}{$key} if ($key); |
248
|
0
|
|
|
|
|
0
|
return $self->{no_not_in_eval}; |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub string { |
253
|
21
|
|
|
21
|
1
|
47
|
my $self=shift; |
254
|
21
|
|
50
|
|
|
87
|
my $sep=shift || ' '; |
255
|
21
|
|
|
|
|
47
|
return join($sep,sort keys(%{$self->{found}})); |
|
21
|
|
|
|
|
218
|
|
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
sub string_in_eval { |
260
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
261
|
0
|
|
0
|
|
|
0
|
my $sep=shift || ' '; |
262
|
0
|
|
|
|
|
0
|
return join($sep,sort keys(%{$self->{found_in_eval}})); |
|
0
|
|
|
|
|
0
|
|
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
sub string_out_of_eval { |
267
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
268
|
0
|
|
0
|
|
|
0
|
my $sep=shift || ' '; |
269
|
0
|
|
|
|
|
0
|
return join($sep,sort keys(%{$self->{found_not_in_eval}})); |
|
0
|
|
|
|
|
0
|
|
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
sub array { |
274
|
111
|
|
|
111
|
1
|
203
|
return keys(%{shift->{found}}) |
|
111
|
|
|
|
|
798
|
|
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub array_in_eval { |
279
|
111
|
|
|
111
|
1
|
211
|
return keys(%{shift->{found_in_eval}}) |
|
111
|
|
|
|
|
868
|
|
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub array_out_of_eval { |
284
|
111
|
|
|
111
|
1
|
237
|
return keys(%{shift->{found_not_in_eval}}) |
|
111
|
|
|
|
|
851
|
|
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
sub arrayref { |
289
|
110
|
|
|
110
|
1
|
417
|
my @a=shift->array; |
290
|
110
|
100
|
|
|
|
586
|
return \@a if @a; |
291
|
28
|
|
|
|
|
86
|
return; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
sub arrayref_in_eval { |
296
|
110
|
|
|
110
|
1
|
5358
|
my @a=shift->array_in_eval; |
297
|
110
|
100
|
|
|
|
353
|
return \@a if @a; |
298
|
107
|
|
|
|
|
349
|
return; |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
sub arrayref_out_of_eval { |
303
|
110
|
|
|
110
|
1
|
380
|
my @a=shift->array_out_of_eval; |
304
|
110
|
100
|
|
|
|
607
|
return \@a if @a; |
305
|
30
|
|
|
|
|
97
|
return; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
sub files { |
310
|
0
|
|
|
0
|
1
|
0
|
return shift->{files}; |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# Internal Accessor Methods |
314
|
|
|
|
|
|
|
sub _add { |
315
|
402
|
|
|
402
|
|
734
|
my $self=shift; |
316
|
402
|
|
|
|
|
657
|
my $found=shift; |
317
|
402
|
|
|
|
|
619
|
my $eval=shift; |
318
|
402
|
|
|
|
|
605
|
my $type=shift; |
319
|
402
|
|
|
|
|
1073
|
$self->{found}{$found}++; |
320
|
402
|
|
|
|
|
861
|
$self->{$type}{$found}++; |
321
|
402
|
100
|
|
|
|
1007
|
if ($eval) { |
322
|
29
|
|
|
|
|
72
|
$self->{found_in_eval}{$found}++; |
323
|
29
|
|
|
|
|
176
|
$self->{"${type}_in_eval"}{$found}++; |
324
|
|
|
|
|
|
|
} else { |
325
|
373
|
|
|
|
|
803
|
$self->{found_not_in_eval}{$found}++; |
326
|
373
|
|
|
|
|
1886
|
$self->{"${type}_not_in_eval"}{$found}++; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
sub _found { |
331
|
|
|
|
|
|
|
return shift->{found} |
332
|
0
|
|
|
0
|
|
0
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub _inc_files { |
335
|
383
|
|
|
383
|
|
881
|
shift->{files}++ |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
1; |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
__END__ |