Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Perl/Critic/Policy/Subroutines/RequireArgUnpacking.pm |
Statements | Executed 38 statements in 1.30ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 17µs | 19µs | supported_parameters | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 16µs | 16µs | BEGIN@10 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 16µs | 64µs | BEGIN@25 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 12µs | 31µs | BEGIN@16 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 11µs | 36µs | BEGIN@19 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 10µs | 11µs | default_severity | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 8µs | 19µs | BEGIN@11 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 8µs | 426µs | BEGIN@22 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 8µs | 42µs | BEGIN@14 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 8µs | 11µs | BEGIN@12 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 7µs | 377µs | BEGIN@15 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 7µs | 187µs | BEGIN@20 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
1 | 1 | 1 | 5µs | 5µs | BEGIN@18 | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | _get_arg_symbols | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | _is_cast_of_array | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | _is_cast_of_scalar | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | _is_delegation | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | _is_postfix_foreach | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | _is_size_check | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | _is_unpack | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | _legal_after_size_check | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | _legal_before_size_check | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | _magic_finder | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | applies_to | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | default_themes | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
0 | 0 | 0 | 0s | 0s | violates | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | ############################################################################## | ||||
2 | # $URL$ | ||||
3 | # $Date$ | ||||
4 | # $Author$ | ||||
5 | # $Revision$ | ||||
6 | ############################################################################## | ||||
7 | |||||
8 | package Perl::Critic::Policy::Subroutines::RequireArgUnpacking; | ||||
9 | |||||
10 | 2 | 40µs | 1 | 16µs | # spent 16µs within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@10 which was called:
# once (16µs+0s) by Module::Pluggable::Object::_require at line 10 # spent 16µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@10 |
11 | 2 | 20µs | 2 | 31µs | # spent 19µs (8+11) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@11 which was called:
# once (8µs+11µs) by Module::Pluggable::Object::_require at line 11 # spent 19µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@11
# spent 11µs making 1 call to strict::import |
12 | 2 | 18µs | 2 | 15µs | # spent 11µs (8+4) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@12 which was called:
# once (8µs+4µs) by Module::Pluggable::Object::_require at line 12 # spent 11µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@12
# spent 4µs making 1 call to warnings::import |
13 | |||||
14 | 2 | 22µs | 2 | 75µs | # spent 42µs (8+34) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@14 which was called:
# once (8µs+34µs) by Module::Pluggable::Object::_require at line 14 # spent 42µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@14
# spent 34µs making 1 call to Exporter::import |
15 | 2 | 22µs | 2 | 747µs | # spent 377µs (7+370) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@15 which was called:
# once (7µs+370µs) by Module::Pluggable::Object::_require at line 15 # spent 377µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@15
# spent 370µs making 1 call to English::import |
16 | 2 | 21µs | 2 | 50µs | # spent 31µs (12+19) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@16 which was called:
# once (12µs+19µs) by Module::Pluggable::Object::_require at line 16 # spent 31µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@16
# spent 19µs making 1 call to Exporter::import |
17 | |||||
18 | 2 | 20µs | 1 | 5µs | # spent 5µs within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@18 which was called:
# once (5µs+0s) by Module::Pluggable::Object::_require at line 18 # spent 5µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@18 |
19 | 2 | 22µs | 2 | 43µs | # spent 36µs (11+25) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@19 which was called:
# once (11µs+25µs) by Module::Pluggable::Object::_require at line 19 # spent 36µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@19
# spent 8µs making 1 call to List::Util::import |
20 | 2 | 26µs | 2 | 366µs | # spent 187µs (7+179) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@20 which was called:
# once (7µs+179µs) by Module::Pluggable::Object::_require at line 20 # spent 187µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@20
# spent 179µs making 1 call to Exporter::Tiny::import |
21 | |||||
22 | 1 | 200ns | # spent 426µs (8+419) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@22 which was called:
# once (8µs+419µs) by Module::Pluggable::Object::_require at line 24 | ||
23 | :booleans :characters hashify :severities words_from_string | ||||
24 | 1 | 33µs | 2 | 845µs | >; # spent 426µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@22
# spent 418µs making 1 call to Exporter::import |
25 | 2 | 1.01ms | 2 | 112µs | # spent 64µs (16+48) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@25 which was called:
# once (16µs+48µs) by Module::Pluggable::Object::_require at line 25 # spent 64µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@25
# spent 48µs making 1 call to base::import |
26 | |||||
27 | 1 | 600ns | our $VERSION = '1.121'; | ||
28 | |||||
29 | #----------------------------------------------------------------------------- | ||||
30 | |||||
31 | 1 | 2µs | 1 | 30µs | Readonly::Scalar my $AT => q{@}; # spent 30µs making 1 call to Readonly::Scalar |
32 | 1 | 1µs | 1 | 21µs | Readonly::Scalar my $AT_ARG => q{@_}; ## no critic (InterpolationOfMetachars) # spent 21µs making 1 call to Readonly::Scalar |
33 | 1 | 900ns | 1 | 20µs | Readonly::Scalar my $DOLLAR => q{$}; # spent 20µs making 1 call to Readonly::Scalar |
34 | 1 | 900ns | 1 | 19µs | Readonly::Scalar my $DOLLAR_ARG => q{$_}; ## no critic (InterpolationOfMetaChars) # spent 19µs making 1 call to Readonly::Scalar |
35 | |||||
36 | 1 | 4µs | 2 | 21µs | Readonly::Scalar my $DESC => qq{Always unpack $AT_ARG first}; # spent 20µs making 1 call to Readonly::Scalar
# spent 2µs making 1 call to Readonly::Scalar::FETCH |
37 | 1 | 2µs | 1 | 40µs | Readonly::Scalar my $EXPL => [178]; # spent 40µs making 1 call to Readonly::Scalar |
38 | |||||
39 | #----------------------------------------------------------------------------- | ||||
40 | |||||
41 | # spent 19µs (17+2) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::supported_parameters which was called:
# once (17µs+2µs) by Perl::Critic::Policy::new at line 88 of Perl/Critic/Policy.pm | ||||
42 | return ( | ||||
43 | { | ||||
44 | 1 | 15µs | 2 | 2µs | name => 'short_subroutine_statements', # spent 2µs making 2 calls to Readonly::Scalar::FETCH, avg 1µs/call |
45 | description => | ||||
46 | 'The number of statements to allow without unpacking.', | ||||
47 | default_string => '0', | ||||
48 | behavior => 'integer', | ||||
49 | integer_minimum => 0, | ||||
50 | }, | ||||
51 | { | ||||
52 | name => 'allow_subscripts', | ||||
53 | description => | ||||
54 | 'Should unpacking from array slices and elements be allowed?', | ||||
55 | default_string => $FALSE, | ||||
56 | behavior => 'boolean', | ||||
57 | }, | ||||
58 | { | ||||
59 | name => 'allow_delegation_to', | ||||
60 | description => | ||||
61 | 'Allow the usual delegation idiom to these namespaces/subroutines', | ||||
62 | behavior => 'string list', | ||||
63 | list_always_present_values => [ qw< SUPER:: NEXT:: > ], | ||||
64 | } | ||||
65 | ); | ||||
66 | } | ||||
67 | |||||
68 | 1 | 2µs | # spent 11µs (10+1) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::default_severity which was called:
# once (10µs+1µs) by Perl::Critic::Policy::get_severity at line 331 of Perl/Critic/Policy.pm | ||
69 | sub default_themes { return qw( core pbp maintenance ) } | ||||
70 | sub applies_to { return 'PPI::Statement::Sub' } | ||||
71 | |||||
72 | #----------------------------------------------------------------------------- | ||||
73 | |||||
74 | sub violates { | ||||
75 | my ( $self, $elem, undef ) = @_; | ||||
76 | |||||
77 | # forward declaration? | ||||
78 | return if not $elem->block; | ||||
79 | |||||
80 | my @statements = $elem->block->schildren; | ||||
81 | |||||
82 | # empty sub? | ||||
83 | return if not @statements; | ||||
84 | |||||
85 | # Don't apply policy to short subroutines | ||||
86 | |||||
87 | # Should we instead be doing a find() for PPI::Statement | ||||
88 | # instances? That is, should we count all statements instead of | ||||
89 | # just top-level statements? | ||||
90 | return if $self->{_short_subroutine_statements} >= @statements; | ||||
91 | |||||
92 | # look for explicit dereferences of @_, including '$_[0]' | ||||
93 | # You may use "... = @_;" in the first paragraph of the sub | ||||
94 | # Don't descend into nested or anonymous subs | ||||
95 | my $state = 'unpacking'; # still in unpacking paragraph | ||||
96 | for my $statement (@statements) { | ||||
97 | |||||
98 | my @magic = _get_arg_symbols($statement); | ||||
99 | |||||
100 | my $saw_unpack = $FALSE; | ||||
101 | |||||
102 | MAGIC: | ||||
103 | for my $magic (@magic) { | ||||
104 | # allow conditional checks on the size of @_ | ||||
105 | next MAGIC if _is_size_check($magic); | ||||
106 | |||||
107 | if ('unpacking' eq $state) { | ||||
108 | if ($self->_is_unpack($magic)) { | ||||
109 | $saw_unpack = $TRUE; | ||||
110 | next MAGIC; | ||||
111 | } | ||||
112 | } | ||||
113 | |||||
114 | # allow @$_[] construct in "... for ();" | ||||
115 | # Check for "print @$_[] for ()" construct (rt39601) | ||||
116 | next MAGIC | ||||
117 | if _is_cast_of_array($magic) and _is_postfix_foreach($magic); | ||||
118 | |||||
119 | # allow $$_[], which is equivalent to $_->[] and not a use | ||||
120 | # of @_ at all. | ||||
121 | next MAGIC | ||||
122 | if _is_cast_of_scalar( $magic ); | ||||
123 | |||||
124 | # allow delegation of the form "$self->SUPER::foo( @_ );" | ||||
125 | next MAGIC | ||||
126 | if $self->_is_delegation( $magic ); | ||||
127 | |||||
128 | # If we make it this far, it is a violation | ||||
129 | return $self->violation( $DESC, $EXPL, $elem ); | ||||
130 | } | ||||
131 | if (not $saw_unpack) { | ||||
132 | $state = 'post_unpacking'; | ||||
133 | } | ||||
134 | } | ||||
135 | return; # OK | ||||
136 | } | ||||
137 | |||||
138 | sub _is_unpack { | ||||
139 | my ($self, $magic) = @_; | ||||
140 | |||||
141 | my $prev = $magic->sprevious_sibling(); | ||||
142 | my $next = $magic->snext_sibling(); | ||||
143 | |||||
144 | # If we have a subscript, we're dealing with an array slice on @_ | ||||
145 | # or an array element of @_. See RT #34009. | ||||
146 | if ( $next and $next->isa('PPI::Structure::Subscript') ) { | ||||
147 | $self->{_allow_subscripts} or return; | ||||
148 | $next = $next->snext_sibling; | ||||
149 | } | ||||
150 | |||||
151 | return $TRUE if | ||||
152 | $prev | ||||
153 | and $prev->isa('PPI::Token::Operator') | ||||
154 | and q{=} eq $prev->content() | ||||
155 | and ( | ||||
156 | not $next | ||||
157 | or $next->isa('PPI::Token::Structure') | ||||
158 | and $SCOLON eq $next->content() | ||||
159 | ); | ||||
160 | return; | ||||
161 | } | ||||
162 | |||||
163 | sub _is_size_check { | ||||
164 | my ($magic) = @_; | ||||
165 | |||||
166 | # No size check on $_[0]. RT #34009. | ||||
167 | $AT eq $magic->raw_type or return; | ||||
168 | |||||
169 | my $prev = $magic->sprevious_sibling; | ||||
170 | my $next = $magic->snext_sibling; | ||||
171 | |||||
172 | if ( $prev || $next ) { | ||||
173 | |||||
174 | return $TRUE | ||||
175 | if _legal_before_size_check( $prev ) | ||||
176 | and _legal_after_size_check( $next ); | ||||
177 | } | ||||
178 | |||||
179 | my $parent = $magic; | ||||
180 | { | ||||
181 | $parent = $parent->parent() | ||||
182 | or return; | ||||
183 | $prev = $parent->sprevious_sibling(); | ||||
184 | $next = $parent->snext_sibling(); | ||||
185 | $prev | ||||
186 | or $next | ||||
187 | or redo; | ||||
188 | } # until ( $prev || $next ); | ||||
189 | |||||
190 | return $TRUE | ||||
191 | if $parent->isa( 'PPI::Structure::Condition' ); | ||||
192 | |||||
193 | return; | ||||
194 | } | ||||
195 | |||||
196 | { | ||||
197 | |||||
198 | 2 | 4µs | 2 | 35µs | Readonly::Hash my %LEGAL_NEXT_OPER => hashify( # spent 31µs making 1 call to Readonly::Hash
# spent 4µs making 1 call to Perl::Critic::Utils::hashify |
199 | qw{ && || == != > >= < <= and or } ); | ||||
200 | |||||
201 | 1 | 2µs | 2 | 20µs | Readonly::Hash my %LEGAL_NEXT_STRUCT => hashify( qw{ ; } ); # spent 18µs making 1 call to Readonly::Hash
# spent 2µs making 1 call to Perl::Critic::Utils::hashify |
202 | |||||
203 | sub _legal_after_size_check { | ||||
204 | my ( $next ) = @_; | ||||
205 | |||||
206 | $next | ||||
207 | or return $TRUE; | ||||
208 | |||||
209 | $next->isa( 'PPI::Token::Operator' ) | ||||
210 | and return $LEGAL_NEXT_OPER{ $next->content() }; | ||||
211 | |||||
212 | $next->isa( 'PPI::Token::Structure' ) | ||||
213 | and return $LEGAL_NEXT_STRUCT{ $next->content() }; | ||||
214 | |||||
215 | return; | ||||
216 | } | ||||
217 | } | ||||
218 | |||||
219 | { | ||||
220 | |||||
221 | 2 | 3µs | 2 | 32µs | Readonly::Hash my %LEGAL_PREV_OPER => hashify( # spent 28µs making 1 call to Readonly::Hash
# spent 4µs making 1 call to Perl::Critic::Utils::hashify |
222 | qw{ && || ! == != > >= < <= and or not } ); | ||||
223 | |||||
224 | 1 | 2µs | 2 | 22µs | Readonly::Hash my %LEGAL_PREV_WORD => hashify( # spent 20µs making 1 call to Readonly::Hash
# spent 2µs making 1 call to Perl::Critic::Utils::hashify |
225 | qw{ if unless } ); | ||||
226 | |||||
227 | sub _legal_before_size_check { | ||||
228 | my ( $prev ) = @_; | ||||
229 | |||||
230 | $prev | ||||
231 | or return $TRUE; | ||||
232 | |||||
233 | $prev->isa( 'PPI::Token::Operator' ) | ||||
234 | and return $LEGAL_PREV_OPER{ $prev->content() }; | ||||
235 | |||||
236 | $prev->isa( 'PPI::Token::Word' ) | ||||
237 | and return $LEGAL_PREV_WORD{ $prev->content() }; | ||||
238 | |||||
239 | return; | ||||
240 | } | ||||
241 | |||||
242 | } | ||||
243 | |||||
244 | sub _is_postfix_foreach { | ||||
245 | my ($magic) = @_; | ||||
246 | |||||
247 | my $sibling = $magic; | ||||
248 | while ( $sibling = $sibling->snext_sibling ) { | ||||
249 | return $TRUE | ||||
250 | if | ||||
251 | $sibling->isa('PPI::Token::Word') | ||||
252 | and $sibling =~ m< \A for (?:each)? \z >xms; | ||||
253 | } | ||||
254 | return; | ||||
255 | } | ||||
256 | |||||
257 | sub _is_cast_of_array { | ||||
258 | my ($magic) = @_; | ||||
259 | |||||
260 | my $prev = $magic->sprevious_sibling; | ||||
261 | |||||
262 | return $TRUE | ||||
263 | if ( $prev && $prev->content() eq $AT ) | ||||
264 | and $prev->isa('PPI::Token::Cast'); | ||||
265 | return; | ||||
266 | } | ||||
267 | |||||
268 | # This subroutine recognizes (e.g.) $$_[0]. This is a use of $_ (equivalent to | ||||
269 | # $_->[0]), not @_. | ||||
270 | |||||
271 | sub _is_cast_of_scalar { | ||||
272 | my ($magic) = @_; | ||||
273 | |||||
274 | my $prev = $magic->sprevious_sibling; | ||||
275 | my $next = $magic->snext_sibling; | ||||
276 | |||||
277 | return $DOLLAR_ARG eq $magic->content() && | ||||
278 | $prev && $prev->isa('PPI::Token::Cast') && | ||||
279 | $DOLLAR eq $prev->content() && | ||||
280 | $next && $next->isa('PPI::Structure::Subscript'); | ||||
281 | } | ||||
282 | |||||
283 | # A literal @_ is allowed as the argument for a delegation. | ||||
284 | # An example of the idiom we are looking for is $self->SUPER::foo(@_). | ||||
285 | # The argument list of (@_) is required; no other use of @_ is allowed. | ||||
286 | |||||
287 | sub _is_delegation { | ||||
288 | my ($self, $magic) = @_; | ||||
289 | |||||
290 | $AT_ARG eq $magic->content() or return; # Not a literal '@_'. | ||||
291 | my $parent = $magic->parent() # Don't know what to do with | ||||
292 | or return; # orphans. | ||||
293 | $parent->isa( 'PPI::Statement::Expression' ) | ||||
294 | or return; # Parent must be expression. | ||||
295 | 1 == $parent->schildren() # '@_' must stand alone in | ||||
296 | or return; # its expression. | ||||
297 | $parent = $parent->parent() # Still don't know what to do | ||||
298 | or return; # with orphans. | ||||
299 | $parent->isa ( 'PPI::Structure::List' ) | ||||
300 | or return; # Parent must be a list. | ||||
301 | 1 == $parent->schildren() # '@_' must stand alone in | ||||
302 | or return; # the argument list. | ||||
303 | my $subroutine_name = $parent->sprevious_sibling() | ||||
304 | or return; # Missing sub name. | ||||
305 | $subroutine_name->isa( 'PPI::Token::Word' ) | ||||
306 | or return; | ||||
307 | $self->{_allow_delegation_to}{$subroutine_name} | ||||
308 | and return 1; | ||||
309 | my ($subroutine_namespace) = $subroutine_name =~ m/ \A ( .* ::) \w+ \z /smx | ||||
310 | or return; | ||||
311 | return $self->{_allow_delegation_to}{$subroutine_namespace}; | ||||
312 | } | ||||
313 | |||||
314 | |||||
315 | sub _get_arg_symbols { | ||||
316 | my ($statement) = @_; | ||||
317 | |||||
318 | return grep {$AT_ARG eq $_->symbol} @{$statement->find(\&_magic_finder) || []}; | ||||
319 | } | ||||
320 | |||||
321 | sub _magic_finder { | ||||
322 | # Find all @_ and $_[\d+] not inside of nested subs | ||||
323 | my (undef, $elem) = @_; | ||||
324 | return $TRUE if $elem->isa('PPI::Token::Magic'); # match | ||||
325 | |||||
326 | if ($elem->isa('PPI::Structure::Block')) { | ||||
327 | # don't descend into a nested named sub | ||||
328 | return if $elem->statement->isa('PPI::Statement::Sub'); | ||||
329 | |||||
330 | my $prev = $elem->sprevious_sibling; | ||||
331 | # don't descend into a nested anon sub block | ||||
332 | return if $prev | ||||
333 | and $prev->isa('PPI::Token::Word') | ||||
334 | and 'sub' eq $prev->content(); | ||||
335 | } | ||||
336 | |||||
337 | return $FALSE; # no match, descend | ||||
338 | } | ||||
339 | |||||
340 | |||||
341 | 1 | 9µs | 1; | ||
342 | |||||
343 | __END__ |