line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::Xslate; |
2
|
|
|
|
|
|
|
# The Xslate engine class |
3
|
180
|
|
|
180
|
|
5089823
|
use 5.008_001; |
|
180
|
|
|
|
|
714
|
|
4
|
180
|
|
|
180
|
|
1001
|
use strict; |
|
180
|
|
|
|
|
344
|
|
|
180
|
|
|
|
|
4193
|
|
5
|
180
|
|
|
180
|
|
979
|
use warnings; |
|
180
|
|
|
|
|
339
|
|
|
180
|
|
|
|
|
7979
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '3.3.8'; |
8
|
|
|
|
|
|
|
|
9
|
180
|
|
|
180
|
|
970
|
use Carp (); |
|
180
|
|
|
|
|
420
|
|
|
180
|
|
|
|
|
3369
|
|
10
|
180
|
|
|
180
|
|
953
|
use File::Spec (); |
|
180
|
|
|
|
|
353
|
|
|
180
|
|
|
|
|
3252
|
|
11
|
180
|
|
|
180
|
|
915
|
use Exporter (); |
|
180
|
|
|
|
|
392
|
|
|
180
|
|
|
|
|
3208
|
|
12
|
180
|
|
|
180
|
|
141198
|
use Data::MessagePack (); |
|
180
|
|
|
|
|
216999
|
|
|
180
|
|
|
|
|
4553
|
|
13
|
180
|
|
|
180
|
|
1150
|
use Scalar::Util (); |
|
180
|
|
|
|
|
353
|
|
|
180
|
|
|
|
|
3247
|
|
14
|
|
|
|
|
|
|
|
15
|
180
|
|
|
180
|
|
102167
|
use Text::Xslate::Util (); |
|
180
|
|
|
|
|
527
|
|
|
180
|
|
|
|
|
10460
|
|
16
|
|
|
|
|
|
|
BEGIN { |
17
|
|
|
|
|
|
|
# all the exportable functions are defined in ::Util |
18
|
180
|
|
|
180
|
|
658
|
our @EXPORT_OK = qw( |
19
|
|
|
|
|
|
|
mark_raw |
20
|
|
|
|
|
|
|
unmark_raw |
21
|
|
|
|
|
|
|
escaped_string |
22
|
|
|
|
|
|
|
html_escape |
23
|
|
|
|
|
|
|
uri_escape |
24
|
|
|
|
|
|
|
html_builder |
25
|
|
|
|
|
|
|
); |
26
|
180
|
|
|
|
|
70936
|
Text::Xslate::Util->import(@EXPORT_OK); |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
our @ISA = qw(Text::Xslate::Engine); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my $BYTECODE_VERSION = '1.6'; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# $bytecode_version + $fullpath + $compiler_and_parser_options |
34
|
|
|
|
|
|
|
my $XSLATE_MAGIC = qq{xslate;$BYTECODE_VERSION;%s;%s;}; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
our $DEFAULT_CACHE_DIR; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# load backend (XS or PP) |
39
|
|
|
|
|
|
|
my $use_xs = 0; |
40
|
|
|
|
|
|
|
if(!exists $INC{'Text/Xslate/PP.pm'}) { |
41
|
|
|
|
|
|
|
my $pp = ($Text::Xslate::Util::DEBUG =~ /\b pp \b/xms or $ENV{PERL_ONLY}); |
42
|
|
|
|
|
|
|
if(!$pp) { |
43
|
|
|
|
|
|
|
eval { |
44
|
|
|
|
|
|
|
require XSLoader; |
45
|
|
|
|
|
|
|
XSLoader::load(__PACKAGE__, $VERSION); |
46
|
|
|
|
|
|
|
$use_xs = 1; |
47
|
|
|
|
|
|
|
}; |
48
|
|
|
|
|
|
|
die $@ if $@ && $Text::Xslate::Util::DEBUG =~ /\b xs \b/xms; # force XS |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
if(!__PACKAGE__->can('render')) { |
51
|
|
|
|
|
|
|
require 'Text/Xslate/PP.pm'; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
} |
54
|
0
|
|
|
0
|
0
|
0
|
sub USE_XS() { $use_xs } |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# for error messages (see T::X::Util) |
57
|
2766
|
100
|
|
2766
|
1
|
23826
|
sub input_layer { ref($_[0]) ? $_[0]->{input_layer} : ':utf8' } |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
package Text::Xslate::Engine; # XS/PP common base class |
60
|
|
|
|
|
|
|
|
61
|
180
|
|
|
|
|
38844
|
use Text::Xslate::Util qw( |
62
|
|
|
|
|
|
|
make_error |
63
|
|
|
|
|
|
|
dump |
64
|
180
|
|
|
180
|
|
1086
|
); |
|
180
|
|
|
|
|
1559
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# constants |
67
|
|
|
|
|
|
|
BEGIN { |
68
|
180
|
|
|
180
|
|
1814
|
our @ISA = qw(Exporter); |
69
|
|
|
|
|
|
|
|
70
|
180
|
|
|
|
|
516
|
my $dump_load = scalar($Text::Xslate::Util::DEBUG =~ /\b dump=load \b/xms); |
71
|
180
|
|
|
|
|
2759
|
*_DUMP_LOAD = sub(){ $dump_load }; |
|
0
|
|
|
|
|
0
|
|
72
|
|
|
|
|
|
|
|
73
|
180
|
|
|
|
|
2913
|
my $save_src = scalar($Text::Xslate::Util::DEBUG =~ /\b save_src \b/xms); |
74
|
180
|
|
|
|
|
2278
|
*_SAVE_SRC = sub() { $save_src }; |
|
0
|
|
|
|
|
0
|
|
75
|
|
|
|
|
|
|
|
76
|
180
|
|
|
|
|
714005
|
*_ST_MTIME = sub() { 9 }; # see perldoc -f stat |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
unless(defined $DEFAULT_CACHE_DIR) { |
80
|
|
|
|
|
|
|
my $cache_dir = '.xslate_cache'; |
81
|
|
|
|
|
|
|
foreach my $d($ENV{HOME}, File::Spec->tmpdir) { |
82
|
|
|
|
|
|
|
if(defined($d) and -d $d and -w _) { |
83
|
|
|
|
|
|
|
$cache_dir = File::Spec->catfile($d, '.xslate_cache'); |
84
|
|
|
|
|
|
|
last; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
$DEFAULT_CACHE_DIR = $cache_dir; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# the real defaults are defined in the parser |
92
|
|
|
|
|
|
|
my %parser_option = ( |
93
|
|
|
|
|
|
|
line_start => undef, |
94
|
|
|
|
|
|
|
tag_start => undef, |
95
|
|
|
|
|
|
|
tag_end => undef, |
96
|
|
|
|
|
|
|
); |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
# the real defaults are defined in the compiler |
99
|
|
|
|
|
|
|
my %compiler_option = ( |
100
|
|
|
|
|
|
|
syntax => undef, |
101
|
|
|
|
|
|
|
type => undef, |
102
|
|
|
|
|
|
|
header => undef, # template augment |
103
|
|
|
|
|
|
|
footer => undef, # template augment |
104
|
|
|
|
|
|
|
macro => undef, # template augment |
105
|
|
|
|
|
|
|
); |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
my %builtin = ( |
108
|
|
|
|
|
|
|
html_escape => \&Text::Xslate::Util::html_escape, |
109
|
|
|
|
|
|
|
mark_raw => \&Text::Xslate::Util::mark_raw, |
110
|
|
|
|
|
|
|
unmark_raw => \&Text::Xslate::Util::unmark_raw, |
111
|
|
|
|
|
|
|
uri_escape => \&Text::Xslate::Util::uri_escape, |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
is_array_ref => \&Text::Xslate::Util::is_array_ref, |
114
|
|
|
|
|
|
|
is_hash_ref => \&Text::Xslate::Util::is_hash_ref, |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
dump => \&Text::Xslate::Util::dump, |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
# aliases |
119
|
|
|
|
|
|
|
raw => 'mark_raw', |
120
|
|
|
|
|
|
|
html => 'html_escape', |
121
|
|
|
|
|
|
|
uri => 'uri_escape', |
122
|
|
|
|
|
|
|
); |
123
|
|
|
|
|
|
|
|
124
|
289
|
|
|
289
|
|
5138
|
sub default_functions { +{} } # overridable |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub parser_option { # overridable |
127
|
632
|
|
|
632
|
|
11386
|
return \%parser_option; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub compiler_option { # overridable |
131
|
632
|
|
|
632
|
|
18161
|
return \%compiler_option; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub replace_option_value_for_magic_token { # overridable |
135
|
|
|
|
|
|
|
#my($self, $name, $value) = @_; |
136
|
|
|
|
|
|
|
#$value; |
137
|
26
|
|
|
26
|
|
52
|
return $_[2]; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
sub options { # overridable |
141
|
292
|
|
|
292
|
|
2550
|
my($self) = @_; |
142
|
|
|
|
|
|
|
return { |
143
|
|
|
|
|
|
|
# name => default |
144
|
|
|
|
|
|
|
suffix => '.tx', |
145
|
|
|
|
|
|
|
path => ['.'], |
146
|
|
|
|
|
|
|
input_layer => $self->input_layer, |
147
|
|
|
|
|
|
|
cache => 1, # 0: not cached, 1: checks mtime, 2: always cached |
148
|
|
|
|
|
|
|
cache_dir => $DEFAULT_CACHE_DIR, |
149
|
|
|
|
|
|
|
module => undef, |
150
|
|
|
|
|
|
|
function => undef, |
151
|
|
|
|
|
|
|
html_builder_module => undef, |
152
|
|
|
|
|
|
|
compiler => 'Text::Xslate::Compiler', |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
verbose => 1, |
155
|
|
|
|
|
|
|
warn_handler => undef, |
156
|
|
|
|
|
|
|
die_handler => undef, |
157
|
|
|
|
|
|
|
pre_process_handler => undef, |
158
|
|
|
|
|
|
|
|
159
|
292
|
|
|
|
|
3458
|
%{ $self->parser_option }, |
160
|
292
|
|
|
|
|
3589
|
%{ $self->compiler_option }, |
|
292
|
|
|
|
|
3135
|
|
161
|
|
|
|
|
|
|
}; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub new { |
165
|
292
|
|
|
292
|
|
3222198
|
my $class = shift; |
166
|
292
|
100
|
|
|
|
4165
|
my %args = (@_ == 1 ? %{$_[0]} : @_); |
|
12
|
|
|
|
|
66
|
|
167
|
|
|
|
|
|
|
|
168
|
292
|
|
|
|
|
3658
|
my $options = $class->options; |
169
|
292
|
|
|
|
|
2644
|
my $used = 0; |
170
|
292
|
|
|
|
|
2555
|
my $nargs = scalar keys %args; |
171
|
292
|
|
|
|
|
2354
|
foreach my $key(keys %{$options}) { |
|
292
|
|
|
|
|
5415
|
|
172
|
6136
|
100
|
|
|
|
19499
|
if(exists $args{$key}) { |
|
|
100
|
|
|
|
|
|
173
|
718
|
|
|
|
|
9704
|
$used++; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
elsif(defined($options->{$key})) { |
176
|
1565
|
|
|
|
|
20448
|
$args{$key} = $options->{$key}; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
|
180
|
292
|
100
|
|
|
|
3291
|
if($used != $nargs) { |
181
|
2
|
|
|
|
|
7
|
my @unknowns = sort grep { !exists $options->{$_} } keys %args; |
|
17
|
|
|
|
|
40
|
|
182
|
2
|
|
|
|
|
600
|
warnings::warnif(misc |
183
|
|
|
|
|
|
|
=> "$class: Unknown option(s): " . join ' ', @unknowns); |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
$args{path} = [ |
187
|
304
|
100
|
|
|
|
23729
|
map { ref($_) ? $_ : File::Spec->rel2abs($_) } |
188
|
248
|
|
|
|
|
4406
|
ref($args{path}) eq 'ARRAY' ? @{$args{path}} : $args{path} |
189
|
291
|
100
|
|
|
|
3397
|
]; |
190
|
|
|
|
|
|
|
|
191
|
291
|
|
|
|
|
2455
|
my $arg_function= $args{function}; |
192
|
|
|
|
|
|
|
|
193
|
291
|
|
|
|
|
2229
|
my %funcs; |
194
|
291
|
|
|
|
|
2696
|
$args{function} = \%funcs; |
195
|
|
|
|
|
|
|
|
196
|
291
|
|
|
|
|
2486
|
$args{template} = {}; # template structures |
197
|
|
|
|
|
|
|
|
198
|
291
|
|
|
|
|
3419
|
my $self = bless \%args, $class; |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# definition of functions and methods |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
# builtin functions |
203
|
290
|
|
|
|
|
5055
|
%funcs = %builtin; |
204
|
290
|
|
|
|
|
8065
|
$self->_register_builtin_methods(\%funcs); |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# per-class functions |
207
|
290
|
|
|
|
|
3681
|
$self->_merge_hash(\%funcs, $class->default_functions()); |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
# user-defined functions |
210
|
290
|
100
|
|
|
|
3142
|
if(defined $args{module}) { |
211
|
|
|
|
|
|
|
$self->_merge_hash(\%funcs, |
212
|
11
|
|
|
|
|
27
|
Text::Xslate::Util::import_from(@{$args{module}})); |
|
11
|
|
|
|
|
59
|
|
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
# user-defined html builder functions |
216
|
288
|
100
|
|
|
|
2814
|
if(defined $args{html_builder_module}) { |
217
|
1
|
|
|
|
|
2
|
my $raw = Text::Xslate::Util::import_from(@{$args{html_builder_module}}); |
|
1
|
|
|
|
|
6
|
|
218
|
|
|
|
|
|
|
my $html_builders = +{ |
219
|
|
|
|
|
|
|
map { |
220
|
1
|
|
|
|
|
4
|
($_ => &Text::Xslate::Util::html_builder($raw->{$_})) |
|
1
|
|
|
|
|
5
|
|
221
|
|
|
|
|
|
|
} keys %$raw |
222
|
|
|
|
|
|
|
}; |
223
|
1
|
|
|
|
|
4
|
$self->_merge_hash(\%funcs, $html_builders); |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
288
|
|
|
|
|
2714
|
$self->_merge_hash(\%funcs, $arg_function); |
227
|
|
|
|
|
|
|
|
228
|
288
|
|
|
|
|
3593
|
$self->_resolve_function_aliases(\%funcs); |
229
|
|
|
|
|
|
|
|
230
|
288
|
|
|
|
|
6110
|
return $self; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
sub _merge_hash { |
234
|
588
|
|
|
588
|
|
4406
|
my($self, $base, $add) = @_; |
235
|
588
|
|
|
|
|
4223
|
foreach my $name(keys %{$add}) { |
|
588
|
|
|
|
|
8474
|
|
236
|
98
|
|
|
|
|
331
|
$base->{$name} = $add->{$name}; |
237
|
|
|
|
|
|
|
} |
238
|
588
|
|
|
|
|
8187
|
return; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub _resolve_function_aliases { |
242
|
288
|
|
|
288
|
|
2422
|
my($self, $funcs) = @_; |
243
|
|
|
|
|
|
|
|
244
|
288
|
|
|
|
|
2290
|
foreach my $f(values %{$funcs}) { |
|
288
|
|
|
|
|
4899
|
|
245
|
7003
|
|
|
|
|
48669
|
my %seen; # to avoid infinite loops |
246
|
7003
|
|
100
|
|
|
75884
|
while(!( ref($f) or Scalar::Util::looks_like_number($f) )) { |
247
|
863
|
50
|
|
|
|
7819
|
my $v = $funcs->{$f} or $self->_error( |
248
|
|
|
|
|
|
|
"Cannot resolve a function alias '$f'," |
249
|
|
|
|
|
|
|
. " which refers nothing", |
250
|
|
|
|
|
|
|
); |
251
|
|
|
|
|
|
|
|
252
|
863
|
50
|
33
|
|
|
8198
|
if( ref($v) or Scalar::Util::looks_like_number($v) ) { |
253
|
863
|
|
|
|
|
6345
|
$f = $v; |
254
|
863
|
|
|
|
|
12076
|
last; |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
else { |
257
|
0
|
0
|
|
|
|
0
|
$seen{$v}++ and $self->_error( |
258
|
|
|
|
|
|
|
"Cannot resolve a function alias '$f'," |
259
|
|
|
|
|
|
|
. " which makes circular references", |
260
|
|
|
|
|
|
|
); |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
288
|
|
|
|
|
4065
|
return; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub load_string { # called in render_string() |
269
|
1349
|
|
|
1349
|
|
245894
|
my($self, $string) = @_; |
270
|
1349
|
100
|
|
|
|
3868
|
if(not defined $string) { |
271
|
1
|
|
|
|
|
7
|
$self->_error("LoadError: Template string is not given"); |
272
|
|
|
|
|
|
|
} |
273
|
1348
|
|
|
|
|
1754
|
$self->note(' _load_string: %s', join '\n', split /\n/, $string) |
274
|
|
|
|
|
|
|
if _DUMP_LOAD; |
275
|
1348
|
|
|
|
|
1662
|
$self->{source}{''} = $string if _SAVE_SRC; |
276
|
1348
|
|
|
|
|
3285
|
$self->{string_buffer} = $string; |
277
|
1348
|
|
|
|
|
4145
|
my $asm = $self->compile($string); |
278
|
1284
|
|
|
|
|
37617
|
$self->_assemble($asm, '', \$string, undef, undef); |
279
|
1284
|
|
|
|
|
1038974
|
return $asm; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
my $updir = File::Spec->updir; |
283
|
|
|
|
|
|
|
sub find_file { |
284
|
2216
|
|
|
2216
|
|
9173
|
my($self, $file) = @_; |
285
|
|
|
|
|
|
|
|
286
|
2216
|
100
|
|
|
|
9471
|
if($file =~ /\Q$updir\E/xmso) { |
287
|
4
|
|
|
|
|
24
|
$self->_error("LoadError: Forbidden component (updir: '$updir') found in file name '$file'"); |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
|
290
|
2212
|
|
|
|
|
4489
|
my $fullpath; |
291
|
|
|
|
|
|
|
my $cachepath; |
292
|
0
|
|
|
|
|
0
|
my $orig_mtime; |
293
|
0
|
|
|
|
|
0
|
my $cache_mtime; |
294
|
2212
|
|
|
|
|
5025
|
foreach my $p(@{$self->{path}}) { |
|
2212
|
|
|
|
|
9520
|
|
295
|
2227
|
|
|
|
|
4045
|
$self->note(" find_file: %s in %s ...\n", $file, $p) if _DUMP_LOAD; |
296
|
|
|
|
|
|
|
|
297
|
2227
|
|
|
|
|
4459
|
my $cache_prefix; |
298
|
2227
|
100
|
|
|
|
6700
|
if(ref $p eq 'HASH') { # virtual path |
299
|
97
|
100
|
|
|
|
405
|
defined(my $content = $p->{$file}) or next; |
300
|
92
|
|
|
|
|
169
|
$fullpath = \$content; |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# NOTE: |
303
|
|
|
|
|
|
|
# Because contents of virtual paths include their digest, |
304
|
|
|
|
|
|
|
# time-dependent cache verifier makes no sense. |
305
|
92
|
|
|
|
|
148
|
$orig_mtime = 0; |
306
|
92
|
|
|
|
|
137
|
$cache_mtime = 0; |
307
|
92
|
|
|
|
|
178
|
$cache_prefix = 'HASH'; |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
else { |
310
|
2130
|
|
|
|
|
32458
|
$fullpath = File::Spec->catfile($p, $file); |
311
|
2130
|
100
|
|
|
|
56312
|
defined($orig_mtime = (stat($fullpath))[_ST_MTIME]) |
312
|
|
|
|
|
|
|
or next; |
313
|
2115
|
|
|
|
|
17778
|
$cache_prefix = Text::Xslate::uri_escape($p); |
314
|
2115
|
50
|
|
|
|
9079
|
if (length $cache_prefix > 127) { |
315
|
|
|
|
|
|
|
# some filesystems refuse a path part with length > 127 |
316
|
0
|
|
|
|
|
0
|
$cache_prefix = $self->_digest($cache_prefix); |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# $file is found |
321
|
|
|
|
|
|
|
$cachepath = File::Spec->catfile( |
322
|
|
|
|
|
|
|
$self->{cache_dir}, |
323
|
2207
|
|
|
|
|
28249
|
$cache_prefix, |
324
|
|
|
|
|
|
|
$file . 'c', |
325
|
|
|
|
|
|
|
); |
326
|
|
|
|
|
|
|
# stat() will be failed if the cache doesn't exist |
327
|
2207
|
|
|
|
|
33078
|
$cache_mtime = (stat($cachepath))[_ST_MTIME]; |
328
|
2207
|
|
|
|
|
7988
|
last; |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
2212
|
100
|
|
|
|
7204
|
if(not defined $orig_mtime) { |
332
|
5
|
|
|
|
|
21
|
$self->_error("LoadError: Cannot find '$file' (path: @{$self->{path}})"); |
|
5
|
|
|
|
|
61
|
|
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
2207
|
|
|
|
|
4371
|
$self->note(" find_file: %s (mtime=%d)\n", |
336
|
|
|
|
|
|
|
$fullpath, $cache_mtime || 0) if _DUMP_LOAD; |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
return { |
339
|
2207
|
100
|
|
|
|
17260
|
name => ref($fullpath) ? $file : $fullpath, |
340
|
|
|
|
|
|
|
fullpath => $fullpath, |
341
|
|
|
|
|
|
|
cachepath => $cachepath, |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
orig_mtime => $orig_mtime, |
344
|
|
|
|
|
|
|
cache_mtime => $cache_mtime, |
345
|
|
|
|
|
|
|
}; |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
sub load_file { |
350
|
2100
|
|
|
2100
|
|
3460912
|
my($self, $file, $mtime, $omit_augment) = @_; |
351
|
|
|
|
|
|
|
|
352
|
2100
|
|
|
|
|
7827
|
local $self->{omit_augment} = $omit_augment; |
353
|
|
|
|
|
|
|
|
354
|
2100
|
|
|
|
|
4198
|
$self->note("%s->load_file(%s)\n", $self, $file) if _DUMP_LOAD; |
355
|
|
|
|
|
|
|
|
356
|
2100
|
100
|
|
|
|
7687
|
if($file eq '') { # simply reload it |
357
|
1
|
|
|
|
|
9
|
return $self->load_string($self->{string_buffer}); |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
|
360
|
2099
|
|
|
|
|
7593
|
my $fi = $self->find_file($file); |
361
|
|
|
|
|
|
|
|
362
|
2093
|
|
100
|
|
|
7913
|
my $asm = $self->_load_compiled($fi, $mtime) || $self->_load_source($fi, $mtime); |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# $cache_mtime is undef : uses caches without any checks |
365
|
|
|
|
|
|
|
# $cache_mtime > 0 : uses caches with mtime checks |
366
|
|
|
|
|
|
|
# $cache_mtime == 0 : doesn't use caches |
367
|
2088
|
|
|
|
|
4562
|
my $cache_mtime; |
368
|
2088
|
100
|
|
|
|
7625
|
if($self->{cache} < 2) { |
369
|
2081
|
|
100
|
|
|
11131
|
$cache_mtime = $fi->{cache_mtime} || 0; |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
|
372
|
2088
|
|
|
|
|
45685
|
$self->_assemble($asm, $file, $fi->{fullpath}, $fi->{cachepath}, $cache_mtime); |
373
|
2088
|
|
|
|
|
70529
|
return $asm; |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub slurp_template { |
377
|
2050
|
|
|
2050
|
|
5325
|
my($self, $input_layer, $fullpath) = @_; |
378
|
|
|
|
|
|
|
|
379
|
2050
|
100
|
|
|
|
6115
|
if (ref $fullpath eq 'SCALAR') { |
380
|
70
|
|
|
|
|
267
|
return $$fullpath; |
381
|
|
|
|
|
|
|
} else { |
382
|
1980
|
50
|
|
2
|
|
89511
|
open my($source), '<' . $input_layer, $fullpath |
|
2
|
|
|
|
|
17
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
16
|
|
383
|
|
|
|
|
|
|
or $self->_error("LoadError: Cannot open $fullpath for reading: $!"); |
384
|
1980
|
|
|
|
|
128336
|
local $/; |
385
|
1980
|
|
|
|
|
69347
|
return scalar <$source>; |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
sub _load_source { |
390
|
2024
|
|
|
2024
|
|
4765
|
my($self, $fi) = @_; |
391
|
2024
|
|
|
|
|
5056
|
my $fullpath = $fi->{fullpath}; |
392
|
2024
|
|
|
|
|
4657
|
my $cachepath = $fi->{cachepath}; |
393
|
|
|
|
|
|
|
|
394
|
2024
|
|
|
|
|
4121
|
$self->note(" _load_source: try %s ...\n", $fullpath) if _DUMP_LOAD; |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
# This routine is called when the cache is no longer valid (or not created yet) |
397
|
|
|
|
|
|
|
# so it should be ensured that the cache, if exists, does not exist |
398
|
2024
|
100
|
|
|
|
27124
|
if(-e $cachepath) { |
399
|
29
|
50
|
|
|
|
3438
|
unlink $cachepath |
400
|
|
|
|
|
|
|
or Carp::carp("Xslate: cannot unlink $cachepath (ignored): $!"); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
2024
|
|
|
|
|
7264
|
my $source = $self->slurp_template($self->input_layer, $fullpath); |
404
|
2024
|
100
|
|
|
|
8704
|
$source = $self->{pre_process_handler}->($source) if $self->{pre_process_handler}; |
405
|
2024
|
|
|
|
|
4403
|
$self->{source}{$fi->{name}} = $source if _SAVE_SRC; |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
my $asm = $self->compile($source, |
408
|
|
|
|
|
|
|
file => $fullpath, |
409
|
|
|
|
|
|
|
name => $fi->{name}, |
410
|
2024
|
|
|
|
|
8066
|
); |
411
|
|
|
|
|
|
|
|
412
|
2019
|
100
|
|
|
|
8414
|
if($self->{cache} >= 1) { |
413
|
88
|
|
|
|
|
1968
|
my($volume, $dir) = File::Spec->splitpath($fi->{cachepath}); |
414
|
88
|
|
|
|
|
937
|
my $cachedir = File::Spec->catpath($volume, $dir, ''); |
415
|
88
|
100
|
|
|
|
2441
|
if(not -e $cachedir) { |
416
|
34
|
|
|
|
|
314
|
require File::Path; |
417
|
34
|
|
|
|
|
12361
|
File::Path::mkpath($cachedir); |
418
|
34
|
50
|
|
|
|
202209
|
if (! -e $cachedir) { |
419
|
0
|
|
|
|
|
0
|
Carp::croak("Xslate: Cannot prepare cache directory $cachepath (ignored): $@"); |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
|
423
|
88
|
|
|
|
|
1032
|
my $tmpfile = sprintf('%s.%d.%d', $cachepath, $$, Scalar::Util::refaddr($self)); |
424
|
|
|
|
|
|
|
|
425
|
88
|
50
|
|
|
|
17388
|
if (open my($out), ">:raw", $tmpfile) { |
426
|
88
|
|
|
|
|
809
|
my $mtime = $self->_save_compiled($out, $asm, $fullpath, utf8::is_utf8($source)); |
427
|
|
|
|
|
|
|
|
428
|
88
|
50
|
|
|
|
13547
|
if(!close $out) { |
|
|
50
|
|
|
|
|
|
429
|
0
|
|
|
|
|
0
|
Carp::carp("Xslate: Cannot close $cachepath (ignored): $!"); |
430
|
0
|
|
|
|
|
0
|
unlink $tmpfile; |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
elsif (rename($tmpfile => $cachepath)) { |
433
|
|
|
|
|
|
|
# set the newest mtime of all the related files to cache mtime |
434
|
88
|
100
|
|
|
|
291
|
if (not ref $fullpath) { |
435
|
62
|
|
|
|
|
1922
|
my $main_mtime = (stat $fullpath)[_ST_MTIME]; |
436
|
62
|
100
|
66
|
|
|
491
|
if (defined($main_mtime) && $main_mtime > $mtime) { |
437
|
52
|
|
|
|
|
102
|
$mtime = $main_mtime; |
438
|
|
|
|
|
|
|
} |
439
|
62
|
|
|
|
|
1675
|
utime $mtime, $mtime, $cachepath; |
440
|
62
|
|
|
|
|
425
|
$fi->{cache_mtime} = $mtime; |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
else { |
443
|
26
|
|
|
|
|
543
|
$fi->{cache_mtime} = (stat $cachepath)[_ST_MTIME]; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
else { |
447
|
0
|
|
|
|
|
0
|
Carp::carp("Xslate: Cannot rename cache file $cachepath (ignored): $!"); |
448
|
0
|
|
|
|
|
0
|
unlink $tmpfile; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
else { |
452
|
0
|
|
|
|
|
0
|
Carp::carp("Xslate: Cannot open $cachepath for writing (ignored): $!"); |
453
|
|
|
|
|
|
|
} |
454
|
|
|
|
|
|
|
} |
455
|
2019
|
|
|
|
|
4053
|
if(_DUMP_LOAD) { |
456
|
|
|
|
|
|
|
$self->note(" _load_source: cache(mtime=%s)\n", |
457
|
|
|
|
|
|
|
defined $fi->{cache_mtime} ? $fi->{cache_mtime} : 'undef'); |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
2019
|
|
|
|
|
11272
|
return $asm; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
# load compiled templates if they are fresh enough |
464
|
|
|
|
|
|
|
sub _load_compiled { |
465
|
2093
|
|
|
2093
|
|
5110
|
my($self, $fi, $threshold) = @_; |
466
|
|
|
|
|
|
|
|
467
|
2093
|
100
|
|
|
|
6959
|
if($self->{cache} >= 2) { |
468
|
|
|
|
|
|
|
# threshold is the most latest modified time of all the related caches, |
469
|
|
|
|
|
|
|
# so if the cache level >= 2, they seems always fresh. |
470
|
7
|
|
|
|
|
20
|
$threshold = 9**9**9; # force to purge the cache |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
else { |
473
|
2086
|
|
100
|
|
|
12800
|
$threshold ||= $fi->{cache_mtime}; |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
# see also tx_load_template() in xs/Text-Xslate.xs |
476
|
2093
|
100
|
66
|
|
|
8979
|
if(!( defined($fi->{cache_mtime}) and $self->{cache} >= 1 |
|
|
|
100
|
|
|
|
|
477
|
|
|
|
|
|
|
and $threshold >= $fi->{orig_mtime} )) { |
478
|
2009
|
|
|
|
|
4076
|
$self->note( " _load_compiled: no fresh cache: %s, %s", |
479
|
|
|
|
|
|
|
$threshold || 0, Text::Xslate::Util::p($fi) ) if _DUMP_LOAD; |
480
|
2009
|
|
|
|
|
4651
|
$fi->{cache_mtime} = undef; |
481
|
2009
|
|
|
|
|
12324
|
return undef; |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
|
484
|
84
|
|
|
|
|
194
|
my $cachepath = $fi->{cachepath}; |
485
|
84
|
50
|
|
|
|
3744
|
open my($in), '<:raw', $cachepath |
486
|
|
|
|
|
|
|
or $self->_error("LoadError: Cannot open $cachepath for reading: $!"); |
487
|
|
|
|
|
|
|
|
488
|
84
|
|
|
|
|
381
|
my $magic = $self->_magic_token($fi->{fullpath}); |
489
|
84
|
|
|
|
|
158
|
my $data; |
490
|
84
|
|
|
|
|
1543
|
read $in, $data, length($magic); |
491
|
84
|
100
|
|
|
|
285
|
if($data ne $magic) { |
492
|
15
|
|
|
|
|
330
|
return undef; |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
else { |
495
|
69
|
|
|
|
|
293
|
local $/; |
496
|
69
|
|
|
|
|
955
|
$data = <$in>; |
497
|
69
|
|
|
|
|
672
|
close $in; |
498
|
|
|
|
|
|
|
} |
499
|
69
|
|
|
|
|
836
|
my $unpacker = Data::MessagePack::Unpacker->new(); |
500
|
69
|
|
|
|
|
296
|
my $offset = $unpacker->execute($data); |
501
|
69
|
|
|
|
|
277
|
my $is_utf8 = $unpacker->data(); |
502
|
69
|
|
|
|
|
202
|
$unpacker->reset(); |
503
|
|
|
|
|
|
|
|
504
|
69
|
|
|
|
|
203
|
$unpacker->utf8($is_utf8); |
505
|
|
|
|
|
|
|
|
506
|
69
|
|
|
|
|
102
|
my @asm; |
507
|
69
|
100
|
|
|
|
377
|
if($is_utf8) { # TODO: move to XS? |
508
|
58
|
|
|
|
|
112
|
my $seed = ""; |
509
|
58
|
|
|
|
|
165
|
utf8::upgrade($seed); |
510
|
58
|
|
|
|
|
227
|
push @asm, ['print_raw_s', $seed, __LINE__, __FILE__]; |
511
|
|
|
|
|
|
|
} |
512
|
69
|
|
|
|
|
234
|
while($offset < length($data)) { |
513
|
1255
|
|
|
|
|
4738
|
$offset = $unpacker->execute($data, $offset); |
514
|
1255
|
|
|
|
|
2418
|
my $c = $unpacker->data(); |
515
|
1255
|
|
|
|
|
2330
|
$unpacker->reset(); |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
# my($name, $arg, $line, $file, $symbol) = @{$c}; |
518
|
1255
|
100
|
|
|
|
3565
|
if($c->[0] eq 'depend') { |
|
|
100
|
|
|
|
|
|
519
|
2
|
|
|
|
|
84
|
my $dep_mtime = (stat $c->[1])[_ST_MTIME]; |
520
|
2
|
50
|
|
|
|
12
|
if(!defined $dep_mtime) { |
521
|
0
|
|
|
|
|
0
|
Carp::carp("Xslate: Failed to stat $c->[1] (ignored): $!"); |
522
|
0
|
|
|
|
|
0
|
return undef; # purge the cache |
523
|
|
|
|
|
|
|
} |
524
|
2
|
50
|
|
|
|
19
|
if($dep_mtime > $threshold){ |
525
|
0
|
|
|
|
|
0
|
$self->note(" _load_compiled: %s(%s) is newer than %s(%s)\n", |
526
|
|
|
|
|
|
|
$c->[1], scalar localtime($dep_mtime), |
527
|
|
|
|
|
|
|
$cachepath, scalar localtime($threshold) ) |
528
|
|
|
|
|
|
|
if _DUMP_LOAD; |
529
|
0
|
|
|
|
|
0
|
return undef; # purge the cache |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
elsif($c->[0] eq 'literal') { |
533
|
|
|
|
|
|
|
# force upgrade to avoid UTF-8 key issues |
534
|
3
|
100
|
|
|
|
12
|
utf8::upgrade($c->[1]) if($is_utf8); |
535
|
|
|
|
|
|
|
} |
536
|
1255
|
|
|
|
|
3038
|
push @asm, $c; |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
|
539
|
69
|
|
|
|
|
108
|
if(_DUMP_LOAD) { |
540
|
|
|
|
|
|
|
$self->note(" _load_compiled: cache(mtime=%s)\n", |
541
|
|
|
|
|
|
|
defined $fi->{cache_mtime} ? $fi->{cache_mtime} : 'undef'); |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
69
|
|
|
|
|
590
|
return \@asm; |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
sub _save_compiled { |
548
|
88
|
|
|
88
|
|
285
|
my($self, $out, $asm, $fullpath, $is_utf8) = @_; |
549
|
88
|
|
|
|
|
831
|
my $mp = Data::MessagePack->new(); |
550
|
88
|
|
|
|
|
876
|
local $\; |
551
|
88
|
|
|
|
|
460
|
print $out $self->_magic_token($fullpath); |
552
|
88
|
100
|
|
|
|
627
|
print $out $mp->pack($is_utf8 ? 1 : 0); |
553
|
|
|
|
|
|
|
|
554
|
88
|
|
|
|
|
187
|
my $newest_mtime = 0; |
555
|
88
|
|
|
|
|
149
|
foreach my $c(@{$asm}) { |
|
88
|
|
|
|
|
269
|
|
556
|
1403
|
|
|
|
|
4748
|
print $out $mp->pack($c); |
557
|
|
|
|
|
|
|
|
558
|
1403
|
100
|
|
|
|
3630
|
if ($c->[0] eq 'depend') { |
559
|
11
|
|
|
|
|
266
|
my $dep_mtime = (stat $c->[1])[_ST_MTIME]; |
560
|
11
|
50
|
|
|
|
48
|
if ($newest_mtime < $dep_mtime) { |
561
|
11
|
|
|
|
|
29
|
$newest_mtime = $dep_mtime; |
562
|
|
|
|
|
|
|
} |
563
|
|
|
|
|
|
|
} |
564
|
|
|
|
|
|
|
} |
565
|
88
|
|
|
|
|
657
|
return $newest_mtime; |
566
|
|
|
|
|
|
|
} |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
sub _magic_token { |
569
|
172
|
|
|
172
|
|
375
|
my($self, $fullpath) = @_; |
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
$self->{serial_opt} ||= Data::MessagePack->pack([ |
572
|
|
|
|
|
|
|
ref($self->{compiler}) || $self->{compiler}, |
573
|
|
|
|
|
|
|
$self->_filter_options_for_magic_token($self->_extract_options($self->parser_option)), |
574
|
|
|
|
|
|
|
$self->_filter_options_for_magic_token($self->_extract_options($self->compiler_option)), |
575
|
|
|
|
|
|
|
$self->input_layer, |
576
|
172
|
|
66
|
|
|
1335
|
[sort keys %{ $self->{function} }], |
|
103
|
|
66
|
|
|
3011
|
|
577
|
|
|
|
|
|
|
]); |
578
|
|
|
|
|
|
|
|
579
|
172
|
100
|
|
|
|
947
|
if(ref $fullpath) { # ref to content string |
580
|
|
|
|
|
|
|
$fullpath = join ':', ref($fullpath), |
581
|
40
|
|
|
|
|
88
|
$self->_digest(${$fullpath}); |
|
40
|
|
|
|
|
186
|
|
582
|
|
|
|
|
|
|
} |
583
|
172
|
|
|
|
|
3312
|
return sprintf $XSLATE_MAGIC, $fullpath, $self->{serial_opt}; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
sub _digest { |
587
|
40
|
|
|
40
|
|
74
|
my($self, $content) = @_; |
588
|
40
|
|
|
|
|
290
|
require 'Digest/MD5.pm'; # we don't want to create its namespace |
589
|
40
|
|
|
|
|
332
|
my $md5 = Digest::MD5->new(); |
590
|
40
|
|
|
|
|
143
|
utf8::encode($content); |
591
|
40
|
|
|
|
|
179
|
$md5->add($content); |
592
|
40
|
|
|
|
|
373
|
return $md5->hexdigest(); |
593
|
|
|
|
|
|
|
} |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
sub _extract_options { |
596
|
680
|
|
|
680
|
|
4867
|
my($self, $opt_ref) = @_; |
597
|
680
|
|
|
|
|
4547
|
my @options; |
598
|
680
|
|
|
|
|
4669
|
foreach my $name(sort keys %{$opt_ref}) { |
|
680
|
|
|
|
|
10749
|
|
599
|
2726
|
100
|
|
|
|
14201
|
if(exists $self->{$name}) { |
600
|
137
|
|
|
|
|
425
|
push @options, $name => $self->{$name}; |
601
|
|
|
|
|
|
|
} |
602
|
|
|
|
|
|
|
} |
603
|
680
|
|
|
|
|
15469
|
return @options; |
604
|
|
|
|
|
|
|
} |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
sub _filter_options_for_magic_token { |
607
|
206
|
|
|
206
|
|
391
|
my($self, @options) = @_; |
608
|
206
|
|
|
|
|
317
|
my @filterd_options; |
609
|
206
|
|
|
|
|
733
|
while (@options) { |
610
|
29
|
|
|
|
|
53
|
my $name = shift @options; |
611
|
29
|
|
|
|
|
143
|
my $value = $self->replace_option_value_for_magic_token($name, shift @options); |
612
|
29
|
|
|
|
|
129
|
push(@filterd_options, $name => $value); |
613
|
|
|
|
|
|
|
} |
614
|
206
|
|
|
|
|
755
|
@filterd_options; |
615
|
|
|
|
|
|
|
} |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
sub _compiler { |
620
|
3442
|
|
|
3442
|
|
10103
|
my($self) = @_; |
621
|
3442
|
|
|
|
|
7626
|
my $compiler = $self->{compiler}; |
622
|
|
|
|
|
|
|
|
623
|
3442
|
100
|
|
|
|
11169
|
if(!ref $compiler){ |
624
|
237
|
|
|
|
|
104874
|
require Mouse; |
625
|
237
|
|
|
|
|
3849564
|
Mouse::load_class($compiler); |
626
|
|
|
|
|
|
|
|
627
|
237
|
|
|
|
|
39615
|
my $input_layer = $self->input_layer; |
628
|
237
|
|
|
|
|
2882
|
$compiler = $compiler->new( |
629
|
|
|
|
|
|
|
engine => $self, |
630
|
|
|
|
|
|
|
input_layer => $input_layer, |
631
|
|
|
|
|
|
|
$self->_extract_options($self->compiler_option), |
632
|
|
|
|
|
|
|
parser_option => { |
633
|
|
|
|
|
|
|
input_layer => $input_layer, |
634
|
|
|
|
|
|
|
$self->_extract_options($self->parser_option), |
635
|
|
|
|
|
|
|
}, |
636
|
|
|
|
|
|
|
); |
637
|
|
|
|
|
|
|
|
638
|
237
|
|
|
|
|
2760
|
$compiler->define_function(keys %{ $self->{function} }); |
|
237
|
|
|
|
|
5840
|
|
639
|
|
|
|
|
|
|
|
640
|
237
|
|
|
|
|
4723
|
$self->{compiler} = $compiler; |
641
|
|
|
|
|
|
|
} |
642
|
|
|
|
|
|
|
|
643
|
3442
|
|
|
|
|
21614
|
return $compiler; |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
sub compile { |
647
|
3435
|
|
|
3435
|
|
63937
|
my $self = shift; |
648
|
|
|
|
|
|
|
return $self->_compiler->compile(@_, |
649
|
3435
|
|
|
|
|
10710
|
omit_augment => $self->{omit_augment}); |
650
|
|
|
|
|
|
|
} |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
sub _error { |
653
|
10
|
|
|
10
|
|
52
|
die make_error(@_); |
654
|
|
|
|
|
|
|
} |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
sub note { |
657
|
0
|
|
|
0
|
|
0
|
my($self, @args) = @_; |
658
|
0
|
|
|
|
|
0
|
printf STDERR @args; |
659
|
|
|
|
|
|
|
} |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
package Text::Xslate; |
662
|
|
|
|
|
|
|
1; |
663
|
|
|
|
|
|
|
__END__ |