line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::MicroMason::Base; |
2
|
|
|
|
|
|
|
|
3
|
39
|
|
|
39
|
|
230
|
use strict; |
|
39
|
|
|
|
|
68
|
|
|
39
|
|
|
|
|
1309
|
|
4
|
|
|
|
|
|
|
require Carp; |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
###################################################################### |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
###################################################################### |
9
|
|
|
|
|
|
|
|
10
|
39
|
|
|
39
|
|
14445
|
use Class::MixinFactory -hasafactory; |
|
39
|
|
|
|
|
105736
|
|
|
39
|
|
|
|
|
214
|
|
11
|
|
|
|
|
|
|
for my $factory ( (__PACKAGE__)->mixin_factory ) { |
12
|
|
|
|
|
|
|
$factory->base_class( "Text::MicroMason::Base" ); |
13
|
|
|
|
|
|
|
$factory->mixin_prefix( "Text::MicroMason" ); |
14
|
|
|
|
|
|
|
} |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
###################################################################### |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
###################################################################### |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub new { |
21
|
163
|
|
|
163
|
1
|
7503
|
my $callee = shift; |
22
|
163
|
|
|
|
|
251
|
my ( @traits, @attribs ); |
23
|
163
|
|
|
|
|
724
|
while ( scalar @_ ) { |
24
|
302
|
100
|
|
|
|
1112
|
if ( $_[0] =~ /^\-(\w+)$/ ) { |
25
|
264
|
|
|
|
|
655
|
push @traits, $1; |
26
|
264
|
|
|
|
|
512
|
shift; |
27
|
|
|
|
|
|
|
} else { |
28
|
38
|
|
|
|
|
126
|
push @attribs, splice(@_, 0, 2); |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
} |
31
|
163
|
100
|
|
|
|
348
|
if ( scalar @traits ) { |
32
|
153
|
50
|
|
|
|
373
|
die("Adding moxins to an existing class not supported yet!") |
33
|
|
|
|
|
|
|
unless ( $callee eq __PACKAGE__ ); |
34
|
153
|
|
|
|
|
611
|
$callee->class( @traits )->create( @attribs ) |
35
|
|
|
|
|
|
|
} else { |
36
|
10
|
|
|
|
|
31
|
$callee->create( @attribs ) |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
###################################################################### |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# $mason = $class->create( %options ); |
43
|
|
|
|
|
|
|
# $clone = $object->create( %options ); |
44
|
|
|
|
|
|
|
sub create { |
45
|
203
|
|
|
203
|
1
|
11283
|
my $referent = shift; |
46
|
203
|
100
|
|
|
|
465
|
if ( ! ref $referent ) { |
47
|
154
|
|
|
|
|
428
|
bless { $referent->defaults(), @_ }, $referent; |
48
|
|
|
|
|
|
|
} else { |
49
|
49
|
|
|
|
|
98
|
bless { $referent->defaults(), %$referent, @_ }, ref $referent; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub defaults { |
54
|
|
|
|
|
|
|
return () |
55
|
203
|
|
|
203
|
1
|
1986
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
###################################################################### |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
###################################################################### |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# $code_ref = $mason->compile( text => $template, %options ); |
62
|
|
|
|
|
|
|
# $code_ref = $mason->compile( file => $filename, %options ); |
63
|
|
|
|
|
|
|
# $code_ref = $mason->compile( handle => $filehandle, %options ); |
64
|
|
|
|
|
|
|
sub compile { |
65
|
311
|
|
|
311
|
1
|
100338
|
my ( $self, $src_type, $src_data, %options ) = @_; |
66
|
|
|
|
|
|
|
|
67
|
311
|
|
|
|
|
888
|
($self, $src_type, $src_data) = $self->prepare($src_type, $src_data,%options); |
68
|
|
|
|
|
|
|
|
69
|
311
|
|
|
|
|
782
|
my $code = $self->interpret( $src_type, $src_data ); |
70
|
|
|
|
|
|
|
|
71
|
311
|
100
|
|
|
|
724
|
$self->eval_sub( $code ) |
72
|
|
|
|
|
|
|
or $self->croak_msg( "MicroMason compilation failed: $@\n". _number_lines($code)."\n" ); |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# Internal helper to number the lines in the compiled template when compilation croaks |
77
|
|
|
|
|
|
|
sub _number_lines { |
78
|
17
|
|
|
17
|
|
180
|
my $code = shift; |
79
|
|
|
|
|
|
|
|
80
|
17
|
|
|
|
|
25
|
my $n = 0; |
81
|
17
|
|
|
|
|
86
|
return join("\n", map { sprintf("%4d %s", $n++, $_) } split(/\n/, $code)). |
|
204
|
|
|
|
|
619
|
|
82
|
|
|
|
|
|
|
"\n** Please use Text::MicroMason->new\(-LineNumbers\) for better diagnostics!"; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
###################################################################### |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# $result = $mason->execute( code => $subref, @arguments ); |
89
|
|
|
|
|
|
|
# $result = $mason->execute( $src_type, $src_data, @arguments ); |
90
|
|
|
|
|
|
|
# $result = $mason->execute( $src_type, $src_data, \%options, @arguments ); |
91
|
|
|
|
|
|
|
sub execute { |
92
|
262
|
|
|
262
|
1
|
238625
|
my $self = shift; |
93
|
4
|
|
|
|
|
5
|
my $sub = ( $_[0] eq 'code' ) ? do { shift; shift } : |
|
4
|
|
|
|
|
9
|
|
94
|
262
|
100
|
|
|
|
1003
|
$self->compile( shift, shift, ref($_[0]) ? %{ shift() } : () ) |
|
1
|
100
|
|
|
|
3
|
|
|
|
100
|
|
|
|
|
|
95
|
|
|
|
|
|
|
or $self->croak_msg("MicroMason compilation failed: $@"); |
96
|
252
|
|
|
|
|
7267
|
&$sub( @_ ); |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
###################################################################### |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
###################################################################### |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# ($self, $src_type, $src_data) = $self->prepare($src_type, $src_data, %options) |
104
|
|
|
|
|
|
|
sub prepare { |
105
|
311
|
|
|
311
|
1
|
2371
|
my ( $self, $src_type, $src_data, %options ) = @_; |
106
|
311
|
100
|
|
|
|
761
|
$self = $self->create( %options ) if ( scalar keys %options ); |
107
|
311
|
|
|
|
|
922
|
return ( $self, $src_type, $src_data ); |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
###################################################################### |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# $perl_code = $mason->interpret( $src_type, $src_data ); |
113
|
|
|
|
|
|
|
sub interpret { |
114
|
313
|
|
|
313
|
1
|
557
|
my ( $self, $src_type, $src_data ) = @_; |
115
|
313
|
|
|
|
|
677
|
my $template = $self->read( $src_type, $src_data ); |
116
|
313
|
|
|
|
|
783
|
my @tokens = $self->lex( $template ); |
117
|
313
|
|
|
|
|
911
|
my $code = $self->assemble( @tokens ); |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# Source file and line number |
120
|
313
|
|
|
|
|
988
|
my $source_line = $self->source_file_line_label( $src_type, $src_data ); |
121
|
|
|
|
|
|
|
|
122
|
313
|
|
|
|
|
1051
|
return $source_line . "\n" . $code; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# $line_number_comment = $mason->source_file_line_label( $src_type, $src_data ); |
126
|
|
|
|
|
|
|
sub source_file_line_label { |
127
|
313
|
|
|
313
|
0
|
567
|
my ( $self, $src_type, $src_data ) = @_; |
128
|
|
|
|
|
|
|
|
129
|
313
|
100
|
|
|
|
660
|
if ( $src_type eq 'file' ) { |
130
|
47
|
|
|
|
|
155
|
return qq(# line 1 "$src_data"); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
266
|
|
|
|
|
353
|
my @caller; |
134
|
|
|
|
|
|
|
my $call_level; |
135
|
266
|
|
100
|
|
|
303
|
do { @caller = caller( ++ $call_level ) } |
|
951
|
|
|
|
|
7335
|
|
136
|
|
|
|
|
|
|
while ( $caller[0] =~ /^Text::MicroMason/ or $self->isa($caller[0]) ); |
137
|
266
|
|
33
|
|
|
598
|
my $package = ( $caller[1] || $0 ); |
138
|
266
|
|
|
|
|
928
|
qq{# line 1 "text template (compiled at $package line $caller[2])"} |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
###################################################################### |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
# $code_ref = $mason->eval_sub( $perl_code ); |
145
|
|
|
|
|
|
|
sub eval_sub { |
146
|
292
|
|
|
292
|
1
|
450
|
my $m = shift; |
147
|
|
|
|
|
|
|
package Text::MicroMason::Commands; |
148
|
|
|
|
|
|
|
eval( shift ) |
149
|
292
|
|
|
1
|
|
69404
|
} |
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
56
|
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
###################################################################### |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
###################################################################### |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# $template = $mason->read( $src_type, $src_data ); |
156
|
|
|
|
|
|
|
sub read { |
157
|
313
|
|
|
313
|
1
|
764
|
my ( $self, $src_type, $src_data ) = @_; |
158
|
|
|
|
|
|
|
|
159
|
313
|
|
|
|
|
556
|
my $src_method = "read_$src_type"; |
160
|
313
|
50
|
|
|
|
1240
|
$self->can($src_method) |
161
|
|
|
|
|
|
|
or $self->croak_msg("Unsupported source type '$src_type'"); |
162
|
313
|
|
|
|
|
711
|
$self->$src_method( $src_data ); |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# $template = $mason->read_text( $template ); |
166
|
|
|
|
|
|
|
sub read_text { |
167
|
263
|
50
|
|
263
|
1
|
822
|
ref($_[1]) ? $$_[1] : $_[1]; |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# $contents = $mason->read_file( $filename ); |
171
|
|
|
|
|
|
|
sub read_file { |
172
|
47
|
|
|
47
|
1
|
1093
|
my ( $self, $file ) = @_; |
173
|
47
|
|
|
|
|
103
|
local *FILE; |
174
|
47
|
50
|
|
|
|
1429
|
open FILE, "$file" or $self->croak_msg("MicroMason can't open $file: $!"); |
175
|
47
|
|
|
|
|
244
|
local $/ = undef; |
176
|
47
|
|
|
|
|
920
|
local $_ = ; |
177
|
47
|
50
|
|
|
|
397
|
close FILE or $self->croak_msg("MicroMason can't close $file: $!");; |
178
|
47
|
|
|
|
|
323
|
return $_; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# $contents = $mason->read_handle( $filehandle ); |
182
|
|
|
|
|
|
|
sub read_handle { |
183
|
3
|
|
|
3
|
1
|
8
|
my ( $self, $handle ) = @_; |
184
|
3
|
50
|
|
|
|
11
|
my $fh = (ref $handle eq 'GLOB') ? $handle : $$handle; |
185
|
3
|
|
|
|
|
10
|
local $/ = undef; |
186
|
|
|
|
|
|
|
<$fh> |
187
|
3
|
|
|
|
|
80
|
} |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
###################################################################### |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# @token_pairs = $mason->lex( $template ); |
192
|
|
|
|
|
|
|
sub lex { |
193
|
299
|
|
|
299
|
1
|
426
|
my $self = shift; |
194
|
299
|
|
|
|
|
540
|
local $_ = "$_[0]"; |
195
|
299
|
|
|
|
|
381
|
my @tokens; |
196
|
299
|
50
|
|
|
|
831
|
my $lexer = $self->can('lex_token') |
197
|
|
|
|
|
|
|
or $self->croak_msg('Unable to lex_token(); must select a syntax mixin'); |
198
|
|
|
|
|
|
|
# warn "Lexing: " . pos($_) . " of " . length($_) . "\n"; |
199
|
299
|
|
|
|
|
1059
|
until ( /\G\z/gc ) { |
200
|
1161
|
50
|
0
|
|
|
2031
|
my @parsed = &$lexer( $self ) or |
201
|
|
|
|
|
|
|
/\G ( .{0,20} ) /gcxs |
202
|
|
|
|
|
|
|
&& die "MicroMason parsing halted at '$1'\n"; |
203
|
1161
|
|
|
|
|
3372
|
push @tokens, @parsed; |
204
|
|
|
|
|
|
|
} |
205
|
299
|
|
|
|
|
1058
|
return @tokens; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# ( $type, $value ) = $mason->lex_token(); |
209
|
|
|
|
|
|
|
sub lex_token { |
210
|
0
|
|
|
0
|
1
|
0
|
die "The lex_token() method is abstract and must be provided by a subclass"; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
###################################################################### |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
###################################################################### |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
# Text elements used for subroutine assembly |
218
|
|
|
|
|
|
|
sub assembler_rules { |
219
|
|
|
|
|
|
|
template => [ qw( $sub_start $init_errs $init_output |
220
|
|
|
|
|
|
|
$init_args @perl $return_output $sub_end ) ], |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
# Subroutine scafolding |
223
|
|
|
|
|
|
|
sub_start => 'sub { ', |
224
|
|
|
|
|
|
|
sub_end => '}', |
225
|
|
|
|
|
|
|
init_errs => |
226
|
|
|
|
|
|
|
'local $SIG{__DIE__} = sub { die "MicroMason execution failed: ", @_ };', |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# Argument processing elements |
229
|
|
|
|
|
|
|
init_args => 'my %ARGS = @_ if ($#_ % 2);', |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# Output generation |
232
|
308
|
50
|
|
308
|
|
424
|
init_output => sub { my $m = shift; my $sub = $m->{output_sub} ? '$m->{output_sub}' : 'sub {push @OUT, @_}'; 'my @OUT; my $_out = ' . $sub . ';' }, |
|
308
|
|
|
|
|
625
|
|
|
308
|
|
|
|
|
928
|
|
233
|
308
|
50
|
|
308
|
|
411
|
add_output => sub { my $m = shift; $m->{output_sub} ? '&$_out' : 'push @OUT,' }, |
|
308
|
|
|
|
|
863
|
|
234
|
313
|
|
|
313
|
1
|
12679
|
return_output => 'join("", @OUT)', |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
# Mapping between token types |
237
|
|
|
|
|
|
|
text_token => 'perl OUT( QUOTED );', |
238
|
|
|
|
|
|
|
expr_token => "perl OUT( \"\".do{\nTOKEN\n} );", |
239
|
|
|
|
|
|
|
# the "". here forces string context, and should hopefully make |
240
|
|
|
|
|
|
|
# 'uninitialized' warnings appear closer to their source, rather |
241
|
|
|
|
|
|
|
# than at the big join "", @OUT; at the end |
242
|
|
|
|
|
|
|
file_token => "perl OUT( \$m->execute( file => do {\nTOKEN\n} ) );", |
243
|
|
|
|
|
|
|
# Note that we need newline after TOKEN here in case it ends with a comment. |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub assembler_vars { |
247
|
313
|
|
|
313
|
0
|
393
|
my $self = shift; |
248
|
313
|
|
|
|
|
757
|
my %assembler = $self->assembler_rules(); |
249
|
|
|
|
|
|
|
|
250
|
313
|
|
|
|
|
735
|
my @assembly = @{ delete $assembler{ template } }; |
|
313
|
|
|
|
|
957
|
|
251
|
|
|
|
|
|
|
|
252
|
1047
|
|
|
|
|
3534
|
my %token_map = map { ( /^(.*?)_token$/ )[0] => delete $assembler{$_} } |
253
|
313
|
|
|
|
|
971
|
grep { /_token$/ } keys %assembler; |
|
3266
|
|
|
|
|
5788
|
|
254
|
|
|
|
|
|
|
|
255
|
313
|
100
|
|
|
|
950
|
my %fragments = map { $_ => map { ref($_) ? &{$_}( $self ) : $_ } $assembler{$_} } keys %assembler; |
|
2219
|
|
|
|
|
2604
|
|
|
2219
|
|
|
|
|
3956
|
|
|
616
|
|
|
|
|
931
|
|
256
|
|
|
|
|
|
|
|
257
|
313
|
|
|
|
|
2299
|
return( \@assembly, \%fragments, \%token_map ); |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
# $perl_code = $mason->assemble( @tokens ); |
261
|
|
|
|
|
|
|
sub assemble { |
262
|
313
|
|
|
313
|
1
|
2153
|
my $self = shift; |
263
|
313
|
|
|
|
|
756
|
my @tokens = @_; |
264
|
|
|
|
|
|
|
|
265
|
313
|
|
|
|
|
775
|
my ( $order, $fragments, $token_map ) = $self->assembler_vars(); |
266
|
|
|
|
|
|
|
|
267
|
313
|
|
|
|
|
613
|
my %token_streams = map { $_ => [] } map { ( /^\W?\@(\w+)$/ ) } @$order; |
|
1497
|
|
|
|
|
2747
|
|
|
3403
|
|
|
|
|
5474
|
|
268
|
|
|
|
|
|
|
|
269
|
313
|
|
|
|
|
889
|
while ( scalar @tokens ) { |
270
|
1228
|
|
|
|
|
2162
|
my ( $type, $token ) = splice( @tokens, 0, 2 ); |
271
|
|
|
|
|
|
|
|
272
|
1228
|
100
|
100
|
|
|
3419
|
unless ( $token_streams{$type} or $token_map->{$type} ) { |
273
|
40
|
|
|
|
|
55
|
my $method = "assemble_$type"; |
274
|
40
|
50
|
|
|
|
132
|
my $sub = $self->can( $method ) |
275
|
|
|
|
|
|
|
or $self->croak_msg( "Unexpected token type '$type': '$token'" ); |
276
|
40
|
|
|
|
|
88
|
($type, $token) = &$sub( $self, $token ); |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
|
279
|
1228
|
100
|
|
|
|
2238
|
if ( my $typedef = $token_map->{ $type } ) { |
280
|
|
|
|
|
|
|
# Perform token map substitution in a single pass so that uses of |
281
|
|
|
|
|
|
|
# OUT in the token text are not improperly converted to output calls. |
282
|
|
|
|
|
|
|
# -- Simon, 2009-11-14 |
283
|
|
|
|
|
|
|
my %substitution_map = ( |
284
|
|
|
|
|
|
|
'OUT' => $fragments->{add_output}, |
285
|
959
|
|
|
|
|
2964
|
'TOKEN' => $token, |
286
|
|
|
|
|
|
|
'QUOTED' => "qq(\Q$token\E)", |
287
|
|
|
|
|
|
|
); |
288
|
959
|
|
|
|
|
6007
|
$typedef =~ s/\b(OUT|TOKEN|QUOTED)\b/$substitution_map{$1}/g; |
289
|
|
|
|
|
|
|
|
290
|
959
|
|
|
|
|
2947
|
( $type, $token ) = split ' ', $typedef, 2; |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
1228
|
50
|
|
|
|
2269
|
my $ary = $token_streams{$type} |
294
|
|
|
|
|
|
|
or $self->croak_msg( "Unexpected token type '$type': '$token'" ); |
295
|
|
|
|
|
|
|
|
296
|
1228
|
|
|
|
|
2921
|
push @$ary, $token |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
join( "\n", map { |
300
|
313
|
50
|
|
|
|
567
|
/^(\W+)(\w+)$/ or $self->croak_msg("Can't assemble $_"); |
|
3403
|
|
|
|
|
7458
|
|
301
|
3403
|
100
|
|
|
|
6371
|
if ( $1 eq '$' ) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
302
|
1906
|
|
|
|
|
3351
|
$fragments->{ $2 } |
303
|
|
|
|
|
|
|
} elsif ( $1 eq '@' ) { |
304
|
905
|
|
|
|
|
941
|
@{ $token_streams{ $2 } } |
|
905
|
|
|
|
|
1774
|
|
305
|
|
|
|
|
|
|
} elsif ( $1 eq '!@' ) { |
306
|
296
|
|
|
|
|
333
|
reverse @{ $token_streams{ $2 } } |
|
296
|
|
|
|
|
526
|
|
307
|
|
|
|
|
|
|
} elsif ( $1 eq '-@' ) { |
308
|
|
|
|
|
|
|
() |
309
|
296
|
|
|
|
|
2196
|
} else { |
310
|
0
|
|
|
|
|
0
|
$self->croak_msg("Can't assemble $_"); |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
} @$order ); |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
###################################################################### |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
###################################################################### |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub croak_msg { |
320
|
22
|
|
|
22
|
1
|
61
|
local $Carp::CarpLevel = 2; |
321
|
22
|
50
|
|
|
|
4074
|
shift and Carp::croak( ( @_ == 1 ) ? $_[0] : join(' ', map _printable(), @_) ) |
|
|
50
|
|
|
|
|
|
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
my %Escape = ( |
325
|
|
|
|
|
|
|
( map { chr($_), unpack('H2', chr($_)) } (0..255) ), |
326
|
|
|
|
|
|
|
"\\"=>'\\', "\r"=>'r', "\n"=>'n', "\t"=>'t', "\""=>'"' |
327
|
|
|
|
|
|
|
); |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
# $special_characters_escaped = _printable( $source_string ); |
330
|
|
|
|
|
|
|
sub _printable { |
331
|
0
|
0
|
|
0
|
|
0
|
local $_ = scalar(@_) ? (shift) : $_; |
332
|
0
|
0
|
|
|
|
0
|
return "(undef)" unless defined; |
333
|
0
|
|
|
|
|
0
|
s/([\r\n\t\"\\\x00-\x1f\x7F-\xFF])/\\$Escape{$1}/sgo; |
334
|
0
|
0
|
|
|
|
0
|
/[^\w\d\-\:\.\']/ ? "q($_)" : $_; |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
###################################################################### |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
sub cache_key { |
341
|
52
|
|
|
52
|
0
|
133
|
my $self = shift; |
342
|
52
|
|
|
|
|
71
|
my ($src_type, $src_data, %options) = @_; |
343
|
|
|
|
|
|
|
|
344
|
52
|
|
|
|
|
84
|
return $src_data; |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
1; |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
__END__ |