| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Sub::Quote; |
|
2
|
|
|
|
|
|
|
|
|
3
|
5
|
|
|
5
|
|
128
|
sub _clean_eval { eval $_[0] } |
|
|
5
|
|
|
40
|
|
17
|
|
|
|
5
|
|
|
1
|
|
184
|
|
|
|
40
|
|
|
1
|
|
6044
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
|
|
|
|
|
5
|
10
|
|
|
10
|
|
290080
|
use strict; |
|
|
9
|
|
|
|
|
66
|
|
|
|
9
|
|
|
|
|
308
|
|
|
6
|
10
|
|
|
10
|
|
55
|
use warnings; |
|
|
10
|
|
|
|
|
24
|
|
|
|
10
|
|
|
|
|
534
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '2.006008'; |
|
9
|
|
|
|
|
|
|
$VERSION =~ tr/_//d; |
|
10
|
|
|
|
|
|
|
|
|
11
|
10
|
|
|
10
|
|
2661
|
use Sub::Defer qw(defer_sub); |
|
|
9
|
|
|
|
|
20
|
|
|
|
9
|
|
|
|
|
493
|
|
|
12
|
10
|
|
|
10
|
|
77
|
use Scalar::Util qw(weaken); |
|
|
10
|
|
|
|
|
20
|
|
|
|
10
|
|
|
|
|
449
|
|
|
13
|
10
|
|
|
10
|
|
58
|
use Exporter (); |
|
|
10
|
|
|
|
|
18
|
|
|
|
10
|
|
|
|
|
455
|
|
|
14
|
10
|
|
|
10
|
|
203
|
BEGIN { *import = \&Exporter::import } |
|
15
|
11
|
|
|
10
|
|
48
|
use Carp qw(croak); |
|
|
11
|
|
|
|
|
157
|
|
|
|
10
|
|
|
|
|
473
|
|
|
16
|
10
|
|
|
10
|
|
5038
|
BEGIN { our @CARP_NOT = qw(Sub::Defer) } |
|
17
|
|
|
|
|
|
|
BEGIN { |
|
18
|
11
|
|
|
10
|
|
90
|
my $TRUE = sub(){!!1}; |
|
19
|
11
|
|
|
|
|
155
|
my $FALSE = sub(){!!0}; |
|
20
|
10
|
50
|
|
|
|
163
|
*_HAVE_IS_UTF8 = defined &utf8::is_utf8 ? $TRUE : $FALSE; |
|
21
|
10
|
50
|
|
|
|
65
|
*_CAN_TRACK_BOOLEANS = defined &builtin::is_bool ? $TRUE : $FALSE; |
|
22
|
10
|
50
|
|
|
|
33
|
*_CAN_TRACK_NUMBERS = defined &builtin::created_as_number ? $TRUE : $FALSE; |
|
23
|
10
|
100
|
66
|
|
|
299
|
*_HAVE_HEX_FLOAT = !$ENV{SUB_QUOTE_NO_HEX_FLOAT} && "$]" >= 5.022 ? $TRUE : $FALSE; |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# This may not be perfect, as we can't tell the format purely from the size |
|
26
|
|
|
|
|
|
|
# but it should cover the common cases, and other formats are more likely to |
|
27
|
|
|
|
|
|
|
# be less precise. |
|
28
|
10
|
|
|
|
|
155
|
my $nvsize = 8 * length pack 'F', 0; |
|
29
|
9
|
0
|
|
|
|
41
|
my $nvmantbits |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
= $nvsize == 16 ? 11 |
|
31
|
|
|
|
|
|
|
: $nvsize == 32 ? 24 |
|
32
|
|
|
|
|
|
|
: $nvsize == 64 ? 53 |
|
33
|
|
|
|
|
|
|
: $nvsize == 80 ? 64 |
|
34
|
|
|
|
|
|
|
: $nvsize == 128 ? 113 |
|
35
|
|
|
|
|
|
|
: $nvsize == 256 ? 237 |
|
36
|
|
|
|
|
|
|
: 237 # unknown float format |
|
37
|
|
|
|
|
|
|
; |
|
38
|
9
|
|
|
|
|
84
|
my $precision = int( log(2)/log(10)*$nvmantbits ); |
|
39
|
|
|
|
|
|
|
|
|
40
|
8
|
|
|
|
|
108
|
*_NVSIZE = sub(){ $nvsize }; |
|
|
1
|
|
|
|
|
7
|
|
|
41
|
8
|
|
|
|
|
36
|
*_NVMANTBITS = sub(){ $nvmantbits }; |
|
|
1
|
|
|
|
|
103
|
|
|
42
|
8
|
|
|
|
|
31
|
*_FLOAT_PRECISION = sub(){ $precision }; |
|
|
1
|
|
|
|
|
3
|
|
|
43
|
|
|
|
|
|
|
|
|
44
|
8
|
|
|
|
|
67
|
local $@; |
|
45
|
|
|
|
|
|
|
# if B is already loaded, just use its perlstring |
|
46
|
8
|
50
|
33
|
|
|
102
|
if ("$]" >= 5.008_000 && "$]" != 5.010_000 && defined &B::perlstring) { |
|
|
|
0
|
33
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
47
|
8
|
|
|
|
|
710
|
*_perlstring = \&B::perlstring; |
|
48
|
|
|
|
|
|
|
} |
|
49
|
|
|
|
|
|
|
# XString is smaller than B, so prefer to use it. Buggy until 0.003. |
|
50
|
1
|
|
|
|
|
83
|
elsif (eval { require XString; XString->VERSION(0.003) }) { |
|
|
1
|
|
|
|
|
5
|
|
|
51
|
1
|
|
|
|
|
3
|
*_perlstring = \&XString::perlstring; |
|
52
|
|
|
|
|
|
|
} |
|
53
|
|
|
|
|
|
|
# B::perlstring in perl 5.10 handles escaping incorrectly on utf8 strings |
|
54
|
|
|
|
|
|
|
elsif ("$]" == 5.010_000) { |
|
55
|
1
|
|
|
|
|
57
|
my %escape = ( |
|
56
|
|
|
|
|
|
|
(map +(chr($_) => sprintf '\x%02x', $_), 0 .. 0x31, 0x7f), |
|
57
|
|
|
|
|
|
|
"\t" => "\\t", |
|
58
|
|
|
|
|
|
|
"\n" => "\\n", |
|
59
|
|
|
|
|
|
|
"\r" => "\\r", |
|
60
|
|
|
|
|
|
|
"\f" => "\\f", |
|
61
|
|
|
|
|
|
|
"\b" => "\\b", |
|
62
|
|
|
|
|
|
|
"\a" => "\\a", |
|
63
|
|
|
|
|
|
|
"\e" => "\\e", |
|
64
|
|
|
|
|
|
|
(map +($_ => "\\$_"), qw(" \ $ @)), |
|
65
|
|
|
|
|
|
|
); |
|
66
|
|
|
|
|
|
|
*_perlstring = sub { |
|
67
|
1
|
|
|
|
|
2
|
my $value = shift; |
|
68
|
1
|
|
|
|
|
99
|
$value =~ s{(["\$\@\\[:cntrl:]]|[^\x00-\x7f])}{ |
|
69
|
1
|
0
|
|
|
|
5
|
$escape{$1} || sprintf('\x{%x}', ord($1)) |
|
70
|
|
|
|
|
|
|
}ge; |
|
71
|
1
|
|
|
|
|
2
|
qq["$value"]; |
|
72
|
1
|
|
|
|
|
8
|
}; |
|
73
|
|
|
|
|
|
|
} |
|
74
|
1
|
|
|
|
|
56
|
elsif ("$]" >= 5.008_000 && eval { require B; 1 } && defined &B::perlstring ) { |
|
|
1
|
|
|
|
|
7
|
|
|
75
|
1
|
|
|
|
|
2
|
*_perlstring = \&B::perlstring; |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
# on perl 5.6, perlstring is not available. quotemeta will mostly serve as a |
|
78
|
|
|
|
|
|
|
# replacement. it quotes just by adding lots of backslashes though. if a |
|
79
|
|
|
|
|
|
|
# utf8 string was written out directly as bytes, it wouldn't get interpreted |
|
80
|
|
|
|
|
|
|
# correctly if not under 'use utf8'. this is mostly a theoretical concern, |
|
81
|
|
|
|
|
|
|
# but enough to stick with perlstring when possible. |
|
82
|
|
|
|
|
|
|
else { |
|
83
|
1
|
|
|
|
|
80
|
*_perlstring = sub { qq["\Q$_[0]\E"] }; |
|
|
1
|
|
|
|
|
5
|
|
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
our @EXPORT = qw(quote_sub unquote_sub quoted_from_sub qsub); |
|
88
|
|
|
|
|
|
|
our @EXPORT_OK = qw(quotify capture_unroll inlinify sanitize_identifier); |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
our %QUOTED; |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
sub quotify { |
|
93
|
1875
|
|
|
1875
|
1
|
3422073
|
my $value = $_[0]; |
|
94
|
8
|
|
|
10
|
|
51
|
no warnings 'numeric'; |
|
|
8
|
|
|
|
|
71
|
|
|
|
8
|
|
|
|
|
409
|
|
|
95
|
|
|
|
|
|
|
BEGIN { |
|
96
|
8
|
|
|
10
|
|
18276
|
warnings->unimport(qw(experimental::builtin)) |
|
97
|
|
|
|
|
|
|
if _CAN_TRACK_BOOLEANS || _CAN_TRACK_NUMBERS; |
|
98
|
|
|
|
|
|
|
} |
|
99
|
|
|
|
|
|
|
! defined $value ? 'undef()' |
|
100
|
|
|
|
|
|
|
: _CAN_TRACK_BOOLEANS && builtin::is_bool($value) ? ( |
|
101
|
|
|
|
|
|
|
$value ? '(!!1)' : '(!!0)' |
|
102
|
|
|
|
|
|
|
) |
|
103
|
|
|
|
|
|
|
# numeric detection |
|
104
|
|
|
|
|
|
|
: ( |
|
105
|
|
|
|
|
|
|
_CAN_TRACK_NUMBERS |
|
106
|
|
|
|
|
|
|
? builtin::created_as_number($value) |
|
107
|
|
|
|
|
|
|
: ( |
|
108
|
|
|
|
|
|
|
!(_HAVE_IS_UTF8 && utf8::is_utf8($value)) |
|
109
|
|
|
|
|
|
|
&& length( (my $dummy = '') & $value ) |
|
110
|
|
|
|
|
|
|
&& 0 + $value eq $value |
|
111
|
|
|
|
|
|
|
) |
|
112
|
|
|
|
|
|
|
) ? ( |
|
113
|
|
|
|
|
|
|
$value != $value ? ( |
|
114
|
|
|
|
|
|
|
$value eq (9**9**9*0) |
|
115
|
|
|
|
|
|
|
? '(9**9**9*0)' # nan |
|
116
|
|
|
|
|
|
|
: '(-(9**9**9*0))' # -nan |
|
117
|
|
|
|
|
|
|
) |
|
118
|
|
|
|
|
|
|
: $value == 9**9**9 ? '(9**9**9)' # inf |
|
119
|
|
|
|
|
|
|
: $value == -9**9**9 ? '(-9**9**9)' # -inf |
|
120
|
|
|
|
|
|
|
: $value == 0 ? ( |
|
121
|
|
|
|
|
|
|
sprintf('%g', $value) eq '-0' ? '-0.0' : '0', |
|
122
|
|
|
|
|
|
|
) |
|
123
|
|
|
|
|
|
|
: $value !~ /[e.]/i ? ( |
|
124
|
|
|
|
|
|
|
$value > 0 ? (sprintf '%u', $value) |
|
125
|
|
|
|
|
|
|
: (sprintf '%d', $value) |
|
126
|
|
|
|
|
|
|
) |
|
127
|
1875
|
100
|
100
|
|
|
24817
|
: do { |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
128
|
180
|
|
|
|
|
404
|
my $float = $value; |
|
129
|
180
|
|
|
|
|
788
|
my $max_factor = int( log( abs($value) ) / log(2) ) - _NVMANTBITS; |
|
130
|
180
|
100
|
|
|
|
406
|
my $ex_sign = $max_factor > 0 ? 1 : -1; |
|
131
|
180
|
|
|
|
|
460
|
FACTOR: for my $ex (0 .. abs($max_factor)) { |
|
132
|
188
|
|
|
|
|
469
|
my $num = $value / 2**($ex_sign * $ex); |
|
133
|
188
|
|
|
|
|
302
|
for my $precision (_FLOAT_PRECISION .. _FLOAT_PRECISION+2) { |
|
134
|
289
|
|
|
|
|
1681
|
my $formatted = sprintf '%0.'.$precision.'g', $num; |
|
135
|
289
|
100
|
|
|
|
713
|
$float = $formatted |
|
136
|
|
|
|
|
|
|
if $ex == 0; |
|
137
|
289
|
100
|
|
|
|
968
|
if ($formatted == $num) { |
|
138
|
177
|
100
|
|
|
|
360
|
if ($ex) { |
|
139
|
5
|
50
|
|
|
|
24
|
$float |
|
|
|
50
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
= $formatted |
|
141
|
|
|
|
|
|
|
. ($ex_sign == 1 ? '*' : '/') |
|
142
|
|
|
|
|
|
|
. ( |
|
143
|
|
|
|
|
|
|
$ex > _NVMANTBITS |
|
144
|
|
|
|
|
|
|
? "2**$ex" |
|
145
|
|
|
|
|
|
|
: sprintf('%u', 2**$ex) |
|
146
|
|
|
|
|
|
|
); |
|
147
|
|
|
|
|
|
|
} |
|
148
|
177
|
|
|
|
|
539
|
last FACTOR; |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
} |
|
151
|
16
|
|
|
|
|
46
|
if (_HAVE_HEX_FLOAT) { |
|
152
|
97
|
|
|
|
|
303
|
$float = sprintf '%a', $value; |
|
153
|
8
|
|
|
|
|
106
|
last FACTOR; |
|
154
|
|
|
|
|
|
|
} |
|
155
|
|
|
|
|
|
|
} |
|
156
|
93
|
|
|
|
|
269
|
"$float"; |
|
157
|
|
|
|
|
|
|
} |
|
158
|
|
|
|
|
|
|
) |
|
159
|
|
|
|
|
|
|
: !_CAN_TRACK_BOOLEANS && !length($value) && length( (my $dummy2 = '') & $value ) ? '(!!0)' # false |
|
160
|
|
|
|
|
|
|
: _perlstring($value); |
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
sub sanitize_identifier { |
|
164
|
3
|
|
|
3
|
1
|
560
|
my $name = shift; |
|
165
|
3
|
|
|
|
|
92
|
$name =~ s/([_\W])/sprintf('_%x', ord($1))/ge; |
|
|
6
|
|
|
|
|
23
|
|
|
166
|
2
|
|
|
|
|
15
|
$name; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub capture_unroll { |
|
170
|
43
|
|
|
44
|
1
|
1682
|
my ($from, $captures, $indent) = @_; |
|
171
|
|
|
|
|
|
|
join( |
|
172
|
|
|
|
|
|
|
'', |
|
173
|
|
|
|
|
|
|
map { |
|
174
|
43
|
100
|
|
|
|
122
|
/^([\@\%\$])/ |
|
|
88
|
|
|
|
|
616
|
|
|
175
|
|
|
|
|
|
|
or croak "capture key should start with \@, \% or \$: $_"; |
|
176
|
86
|
|
|
|
|
319
|
(' ' x $indent).qq{my ${_} = ${1}{${from}->{${\quotify $_}}};\n}; |
|
|
86
|
|
|
|
|
160
|
|
|
177
|
|
|
|
|
|
|
} keys %$captures |
|
178
|
|
|
|
|
|
|
); |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub inlinify { |
|
182
|
9
|
|
|
10
|
1
|
10430
|
my ($code, $args, $extra, $local) = @_; |
|
183
|
9
|
100
|
|
|
|
83
|
$args = '()' |
|
184
|
|
|
|
|
|
|
if !defined $args; |
|
185
|
9
|
|
100
|
|
|
33
|
my $do = 'do { '.($extra||''); |
|
186
|
9
|
100
|
|
|
|
40
|
if ($code =~ s/^(\s*package\s+([a-zA-Z0-9:]+);)//) { |
|
187
|
2
|
|
|
|
|
73
|
$do .= $1; |
|
188
|
|
|
|
|
|
|
} |
|
189
|
9
|
100
|
100
|
|
|
59
|
if ($code =~ s{ |
|
|
|
100
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
\A((?:\#\ BEGIN\ quote_sub\ PRELUDE\n.*?\#\ END\ quote_sub\ PRELUDE\n)?\s*) |
|
191
|
|
|
|
|
|
|
(^\s*) my \s* \(([^)]+)\) \s* = \s* \@_; |
|
192
|
|
|
|
|
|
|
}{}xms) { |
|
193
|
4
|
|
|
|
|
16
|
my ($pre, $indent, $code_args) = ($1, $2, $3); |
|
194
|
4
|
|
|
|
|
352
|
$do .= $pre; |
|
195
|
4
|
100
|
|
|
|
834
|
if ($code_args ne $args) { |
|
196
|
2
|
|
|
|
|
16
|
$do .= $indent . 'my ('.$code_args.') = ('.$args.'); '; |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
} |
|
199
|
|
|
|
|
|
|
elsif ($local || $args ne '@_') { |
|
200
|
3
|
100
|
|
|
|
10
|
$do .= ($local ? 'local ' : '').'@_ = ('.$args.'); '; |
|
201
|
|
|
|
|
|
|
} |
|
202
|
8
|
|
|
|
|
26
|
$do.$code.' }'; |
|
203
|
|
|
|
|
|
|
} |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
sub quote_sub { |
|
206
|
|
|
|
|
|
|
# HOLY DWIMMERY, BATMAN! |
|
207
|
|
|
|
|
|
|
# $name => $code => \%captures => \%options |
|
208
|
|
|
|
|
|
|
# $name => $code => \%captures |
|
209
|
|
|
|
|
|
|
# $name => $code |
|
210
|
|
|
|
|
|
|
# $code => \%captures => \%options |
|
211
|
|
|
|
|
|
|
# $code |
|
212
|
59
|
100
|
100
|
61
|
1
|
23661
|
my $options = |
|
213
|
|
|
|
|
|
|
(ref($_[-1]) eq 'HASH' and ref($_[-2]) eq 'HASH') |
|
214
|
|
|
|
|
|
|
? pop |
|
215
|
|
|
|
|
|
|
: {}; |
|
216
|
59
|
100
|
|
|
|
154
|
my $captures = ref($_[-1]) eq 'HASH' ? pop : undef; |
|
217
|
59
|
100
|
100
|
|
|
181
|
undef($captures) if $captures && !keys %$captures; |
|
218
|
59
|
|
|
|
|
133
|
my $code = pop; |
|
219
|
59
|
|
|
|
|
95
|
my $name = $_[0]; |
|
220
|
59
|
100
|
|
|
|
122
|
if ($name) { |
|
221
|
21
|
|
|
|
|
27
|
my $subname = $name; |
|
222
|
21
|
100
|
|
|
|
179
|
my $package = $subname =~ s/(.*)::// ? $1 : caller; |
|
223
|
21
|
|
|
|
|
65
|
$name = join '::', $package, $subname; |
|
224
|
21
|
100
|
|
|
|
399
|
croak qq{package name "$package" too long!} |
|
225
|
|
|
|
|
|
|
if length $package > 252; |
|
226
|
19
|
100
|
|
|
|
289
|
croak qq{package name "$package" is not valid!} |
|
227
|
|
|
|
|
|
|
unless $package =~ /^[^\d\W]\w*(?:::\w+)*$/; |
|
228
|
17
|
100
|
|
|
|
131
|
croak qq{sub name "$subname" too long!} |
|
229
|
|
|
|
|
|
|
if length $subname > 252; |
|
230
|
16
|
100
|
|
|
|
235
|
croak qq{sub name "$subname" is not valid!} |
|
231
|
|
|
|
|
|
|
unless $subname =~ /^[^\d\W]\w*$/; |
|
232
|
|
|
|
|
|
|
} |
|
233
|
52
|
|
|
|
|
314
|
my @caller = caller(0); |
|
234
|
52
|
|
|
|
|
97
|
my ($attributes, $file, $line) = @{$options}{qw(attributes file line)}; |
|
|
52
|
|
|
|
|
157
|
|
|
235
|
52
|
100
|
|
|
|
117
|
if ($attributes) { |
|
236
|
|
|
|
|
|
|
/\A\w+(?:\(.*\))?\z/s || croak "invalid attribute $_" |
|
237
|
3
|
|
66
|
|
|
118
|
for @$attributes; |
|
238
|
|
|
|
|
|
|
} |
|
239
|
|
|
|
|
|
|
my $quoted_info = { |
|
240
|
|
|
|
|
|
|
name => $name, |
|
241
|
|
|
|
|
|
|
code => $code, |
|
242
|
|
|
|
|
|
|
captures => $captures, |
|
243
|
|
|
|
|
|
|
package => (exists $options->{package} ? $options->{package} : $caller[0]), |
|
244
|
|
|
|
|
|
|
hints => (exists $options->{hints} ? $options->{hints} : $caller[8]), |
|
245
|
|
|
|
|
|
|
warning_bits => (exists $options->{warning_bits} ? $options->{warning_bits} : $caller[9]), |
|
246
|
51
|
100
|
|
|
|
446
|
hintshash => (exists $options->{hintshash} ? $options->{hintshash} : $caller[10]), |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
($attributes ? (attributes => $attributes) : ()), |
|
248
|
|
|
|
|
|
|
($file ? (file => $file) : ()), |
|
249
|
|
|
|
|
|
|
($line ? (line => $line) : ()), |
|
250
|
|
|
|
|
|
|
}; |
|
251
|
51
|
|
|
|
|
86
|
my $unquoted; |
|
252
|
51
|
|
|
|
|
235
|
weaken($quoted_info->{unquoted} = \$unquoted); |
|
253
|
51
|
100
|
|
|
|
106
|
if ($options->{no_defer}) { |
|
254
|
4
|
|
|
|
|
6
|
my $fake = \my $var; |
|
255
|
4
|
|
|
|
|
13
|
local $QUOTED{$fake} = $quoted_info; |
|
256
|
4
|
|
|
|
|
9
|
my $sub = unquote_sub($fake); |
|
257
|
4
|
100
|
100
|
|
|
20
|
Sub::Defer::_install_coderef($name, $sub) if $name && !$options->{no_install}; |
|
258
|
4
|
|
|
|
|
22
|
return $sub; |
|
259
|
|
|
|
|
|
|
} |
|
260
|
|
|
|
|
|
|
else { |
|
261
|
|
|
|
|
|
|
my $deferred = defer_sub( |
|
262
|
|
|
|
|
|
|
($options->{no_install} ? undef : $name), |
|
263
|
|
|
|
|
|
|
sub { |
|
264
|
30
|
|
|
32
|
|
39
|
$unquoted if 0; |
|
265
|
30
|
|
|
|
|
61
|
unquote_sub($quoted_info->{deferred}); |
|
266
|
|
|
|
|
|
|
}, |
|
267
|
|
|
|
|
|
|
{ |
|
268
|
|
|
|
|
|
|
($attributes ? ( attributes => $attributes ) : ()), |
|
269
|
47
|
100
|
|
|
|
310
|
($name ? () : ( package => $quoted_info->{package} )), |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
}, |
|
271
|
|
|
|
|
|
|
); |
|
272
|
47
|
|
|
|
|
144
|
weaken($quoted_info->{deferred} = $deferred); |
|
273
|
47
|
|
|
|
|
152
|
weaken($QUOTED{$deferred} = $quoted_info); |
|
274
|
47
|
|
|
|
|
226
|
return $deferred; |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
} |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub _context { |
|
279
|
47
|
|
|
49
|
|
91
|
my $info = shift; |
|
280
|
47
|
|
66
|
|
|
138
|
$info->{context} ||= do { |
|
281
|
|
|
|
|
|
|
my ($package, $hints, $warning_bits, $hintshash, $file, $line) |
|
282
|
41
|
|
|
|
|
65
|
= @{$info}{qw(package hints warning_bits hintshash file line)}; |
|
|
41
|
|
|
|
|
111
|
|
|
283
|
|
|
|
|
|
|
|
|
284
|
41
|
100
|
50
|
|
|
85
|
$line ||= 1 |
|
285
|
|
|
|
|
|
|
if $file; |
|
286
|
|
|
|
|
|
|
|
|
287
|
41
|
|
|
|
|
64
|
my $line_mark = ''; |
|
288
|
41
|
100
|
|
|
|
83
|
if ($line) { |
|
289
|
2
|
|
|
|
|
5
|
$line_mark = "#line ".($line-1); |
|
290
|
2
|
100
|
|
|
|
8
|
if ($file) { |
|
291
|
1
|
|
|
|
|
3
|
$line_mark .= qq{ "$file"}; |
|
292
|
|
|
|
|
|
|
} |
|
293
|
2
|
|
|
|
|
3
|
$line_mark .= "\n"; |
|
294
|
|
|
|
|
|
|
} |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
$info->{context} |
|
297
|
|
|
|
|
|
|
="# BEGIN quote_sub PRELUDE\n" |
|
298
|
|
|
|
|
|
|
."package $package;\n" |
|
299
|
|
|
|
|
|
|
."BEGIN {\n" |
|
300
|
|
|
|
|
|
|
." \$^H = ".quotify($hints).";\n" |
|
301
|
|
|
|
|
|
|
." \${^WARNING_BITS} = ".quotify($warning_bits).";\n" |
|
302
|
|
|
|
|
|
|
." \%^H = (\n" |
|
303
|
|
|
|
|
|
|
. join('', map |
|
304
|
|
|
|
|
|
|
" ".quotify($_)." => ".quotify($hintshash->{$_}).",\n", |
|
305
|
41
|
|
33
|
|
|
136
|
grep !(ref $hintshash->{$_} && $hintshash->{$_} =~ /\A(?:\w+(?:::\w+)*=)?[A-Z]+\(0x[[0-9a-fA-F]+\)\z/), |
|
306
|
|
|
|
|
|
|
keys %$hintshash) |
|
307
|
|
|
|
|
|
|
." );\n" |
|
308
|
|
|
|
|
|
|
."}\n" |
|
309
|
|
|
|
|
|
|
.$line_mark |
|
310
|
|
|
|
|
|
|
."# END quote_sub PRELUDE\n"; |
|
311
|
|
|
|
|
|
|
}; |
|
312
|
|
|
|
|
|
|
} |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
sub quoted_from_sub { |
|
315
|
10
|
|
|
15
|
1
|
463
|
my ($sub) = @_; |
|
316
|
10
|
100
|
50
|
|
|
49
|
my $quoted_info = $QUOTED{$sub||''} or return undef; |
|
317
|
|
|
|
|
|
|
my ($name, $code, $captures, $unquoted, $deferred) |
|
318
|
8
|
|
|
|
|
19
|
= @{$quoted_info}{qw(name code captures unquoted deferred)}; |
|
|
8
|
|
|
|
|
26
|
|
|
319
|
8
|
|
|
|
|
17
|
$code = _context($quoted_info) . $code; |
|
320
|
8
|
|
66
|
|
|
52
|
$unquoted &&= $$unquoted; |
|
321
|
8
|
100
|
100
|
|
|
75
|
if (($deferred && $deferred eq $sub) |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
322
|
|
|
|
|
|
|
|| ($unquoted && $unquoted eq $sub)) { |
|
323
|
7
|
|
|
|
|
51
|
return [ $name, $code, $captures, $unquoted, $deferred ]; |
|
324
|
|
|
|
|
|
|
} |
|
325
|
1
|
|
|
|
|
7
|
return undef; |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub unquote_sub { |
|
329
|
43
|
|
|
45
|
1
|
694
|
my ($sub) = @_; |
|
330
|
43
|
100
|
|
|
|
135
|
my $quoted_info = $QUOTED{$sub} or return undef; |
|
331
|
42
|
|
|
|
|
71
|
my $unquoted = $quoted_info->{unquoted}; |
|
332
|
42
|
100
|
66
|
|
|
155
|
unless ($unquoted && $$unquoted) { |
|
333
|
|
|
|
|
|
|
my ($name, $code, $captures, $package, $attributes) |
|
334
|
40
|
|
|
|
|
57
|
= @{$quoted_info}{qw(name code captures package attributes)}; |
|
|
40
|
|
|
|
|
111
|
|
|
335
|
|
|
|
|
|
|
|
|
336
|
40
|
100
|
|
|
|
135
|
($package, $name) = $name =~ /(.*)::(.*)/ |
|
337
|
|
|
|
|
|
|
if $name; |
|
338
|
|
|
|
|
|
|
|
|
339
|
40
|
100
|
|
|
|
91
|
my %captures = $captures ? %$captures : (); |
|
340
|
40
|
|
|
|
|
73
|
$captures{'$_UNQUOTED'} = \$unquoted; |
|
341
|
40
|
|
|
|
|
65
|
$captures{'$_QUOTED'} = \$quoted_info; |
|
342
|
|
|
|
|
|
|
|
|
343
|
40
|
100
|
|
|
|
86
|
my $make_sub |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
= "{\n" |
|
345
|
|
|
|
|
|
|
. capture_unroll("\$_[1]", \%captures, 2) |
|
346
|
|
|
|
|
|
|
. " package ${package};\n" |
|
347
|
|
|
|
|
|
|
. ( |
|
348
|
|
|
|
|
|
|
$name |
|
349
|
|
|
|
|
|
|
# disable the 'variable $x will not stay shared' warning since |
|
350
|
|
|
|
|
|
|
# we're not letting it escape from this scope anyway so there's |
|
351
|
|
|
|
|
|
|
# nothing trying to share it |
|
352
|
|
|
|
|
|
|
? " no warnings 'closure';\n sub ${name} " |
|
353
|
|
|
|
|
|
|
: " \$\$_UNQUOTED = sub " |
|
354
|
|
|
|
|
|
|
) |
|
355
|
|
|
|
|
|
|
. ($attributes ? join('', map ":$_ ", @$attributes) : '') . "{\n" |
|
356
|
|
|
|
|
|
|
. " (\$_QUOTED,\$_UNQUOTED) if 0;\n" |
|
357
|
|
|
|
|
|
|
. _context($quoted_info) |
|
358
|
|
|
|
|
|
|
. $code |
|
359
|
|
|
|
|
|
|
. " }".($name ? "\n \$\$_UNQUOTED = \\&${name}" : '') . ";\n" |
|
360
|
|
|
|
|
|
|
. "}\n" |
|
361
|
|
|
|
|
|
|
. "1;\n"; |
|
362
|
39
|
100
|
|
|
|
139
|
if (my $debug = $ENV{SUB_QUOTE_DEBUG}) { |
|
363
|
12
|
100
|
|
|
|
100
|
if ($debug =~ m{^([^\W\d]\w*(?:::\w+)*(?:::)?)$}) { |
|
|
|
100
|
|
|
|
|
|
|
364
|
9
|
|
|
|
|
29
|
my $filter = $1; |
|
365
|
9
|
100
|
50
|
|
|
55
|
my $match |
|
|
|
100
|
100
|
|
|
|
|
|
366
|
|
|
|
|
|
|
= $filter =~ /::$/ ? $package.'::' |
|
367
|
|
|
|
|
|
|
: $filter =~ /::/ ? $package.'::'.($name||'__ANON__') |
|
368
|
|
|
|
|
|
|
: ($name||'__ANON__'); |
|
369
|
9
|
100
|
|
|
|
47
|
warn $make_sub |
|
370
|
|
|
|
|
|
|
if $match eq $filter; |
|
371
|
|
|
|
|
|
|
} |
|
372
|
|
|
|
|
|
|
elsif ($debug =~ m{\A/(.*)/\z}s) { |
|
373
|
2
|
|
|
|
|
5
|
my $filter = $1; |
|
374
|
2
|
100
|
|
|
|
25
|
warn $make_sub |
|
375
|
|
|
|
|
|
|
if $code =~ $filter; |
|
376
|
|
|
|
|
|
|
} |
|
377
|
|
|
|
|
|
|
else { |
|
378
|
1
|
|
|
|
|
11
|
warn $make_sub; |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
} |
|
381
|
|
|
|
|
|
|
{ |
|
382
|
8
|
|
|
8
|
|
137
|
no strict 'refs'; |
|
|
8
|
|
|
|
|
19
|
|
|
|
8
|
|
|
|
|
2597
|
|
|
|
39
|
|
|
|
|
89
|
|
|
383
|
39
|
100
|
|
|
|
72
|
local *{"${package}::${name}"} if $name; |
|
|
13
|
|
|
|
|
59
|
|
|
384
|
39
|
|
|
|
|
96
|
my ($success, $e); |
|
385
|
|
|
|
|
|
|
{ |
|
386
|
39
|
|
|
|
|
51
|
local $@; |
|
|
39
|
|
|
|
|
52
|
|
|
387
|
39
|
|
|
|
|
102
|
$success = _clean_eval($make_sub, \%captures); |
|
388
|
39
|
|
|
|
|
117
|
$e = $@; |
|
389
|
|
|
|
|
|
|
} |
|
390
|
39
|
100
|
|
|
|
103
|
unless ($success) { |
|
391
|
2
|
|
|
|
|
12
|
my $space = length($make_sub =~ tr/\n//); |
|
392
|
2
|
|
|
|
|
4
|
my $line = 0; |
|
393
|
2
|
|
|
|
|
13
|
$make_sub =~ s/^/sprintf "%${space}d: ", ++$line/emg; |
|
|
39
|
|
|
|
|
113
|
|
|
394
|
2
|
|
|
|
|
210
|
croak "Eval went very, very wrong:\n\n${make_sub}\n\n$e"; |
|
395
|
|
|
|
|
|
|
} |
|
396
|
37
|
|
|
|
|
249
|
weaken($QUOTED{$$unquoted} = $quoted_info); |
|
397
|
|
|
|
|
|
|
} |
|
398
|
|
|
|
|
|
|
} |
|
399
|
39
|
|
|
|
|
144
|
$$unquoted; |
|
400
|
|
|
|
|
|
|
} |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
sub qsub ($) { |
|
403
|
1
|
|
|
2
|
1
|
555
|
goto "e_sub; |
|
404
|
|
|
|
|
|
|
} |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
sub CLONE { |
|
407
|
5
|
|
|
6
|
|
43
|
my @quoted = map { defined $_ ? ( |
|
408
|
2
|
|
|
|
|
10
|
$_->{unquoted} && ${$_->{unquoted}} ? (${ $_->{unquoted} } => $_) : (), |
|
409
|
8
|
100
|
100
|
|
|
26
|
$_->{deferred} ? ($_->{deferred} => $_) : (), |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
) : () } values %QUOTED; |
|
411
|
5
|
|
|
|
|
16
|
%QUOTED = @quoted; |
|
412
|
5
|
|
|
|
|
21
|
weaken($_) for values %QUOTED; |
|
413
|
|
|
|
|
|
|
} |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
1; |
|
416
|
|
|
|
|
|
|
__END__ |