line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
## no critic (ProhibitUnusedPrivateSubroutines) |
2
|
|
|
|
|
|
|
package Text::Template::Simple::Base::Compiler; |
3
|
60
|
|
|
60
|
|
288
|
use strict; |
|
60
|
|
|
|
|
65
|
|
|
60
|
|
|
|
|
1334
|
|
4
|
60
|
|
|
60
|
|
198
|
use warnings; |
|
60
|
|
|
|
|
62
|
|
|
60
|
|
|
|
|
1340
|
|
5
|
|
|
|
|
|
|
|
6
|
60
|
|
|
60
|
|
195
|
use Text::Template::Simple::Util qw(:all); |
|
60
|
|
|
|
|
64
|
|
|
60
|
|
|
|
|
7124
|
|
7
|
60
|
|
|
60
|
|
259
|
use Text::Template::Simple::Constants qw(:all); |
|
60
|
|
|
|
|
89
|
|
|
60
|
|
|
|
|
80321
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = '0.90'; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
sub _init_compile_opts { |
12
|
506
|
|
|
506
|
|
485
|
my $self = shift; |
13
|
506
|
|
100
|
|
|
1128
|
my $opt = shift || {}; |
14
|
|
|
|
|
|
|
|
15
|
506
|
50
|
|
|
|
1128
|
fatal('tts.base.compiler._compile.opt') if ref $opt ne 'HASH'; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# set defaults |
18
|
506
|
|
100
|
|
|
1726
|
$opt->{id} ||= EMPTY_STRING; # id is AUTO |
19
|
506
|
|
100
|
|
|
1471
|
$opt->{map_keys} ||= 0; # use normal behavior |
20
|
506
|
|
100
|
|
|
1115
|
$opt->{chkmt} ||= 0; # check mtime of file template? |
21
|
506
|
|
100
|
|
|
1050
|
$opt->{_sub_inc} ||= 0; # are we called from a dynamic include op? |
22
|
506
|
|
100
|
|
|
1303
|
$opt->{_filter} ||= EMPTY_STRING; # any filters? |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# first element is the shared names. if it's not defined, then there |
25
|
|
|
|
|
|
|
# are no shared variables from top level |
26
|
506
|
100
|
100
|
|
|
1179
|
if ( ref $opt->{_share} eq 'ARRAY' && ! defined $opt->{_share}[0] ) { |
27
|
12
|
|
|
|
|
19
|
delete $opt->{_share}; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
506
|
|
100
|
|
|
1550
|
$opt->{as_is} = $opt->{_sub_inc} && $opt->{_sub_inc} == T_STATIC; |
31
|
|
|
|
|
|
|
|
32
|
506
|
|
|
|
|
738
|
return $opt; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub _validate_chkmt { |
36
|
250
|
|
|
250
|
|
316
|
my($self, $chkmt_ref, $tmpx) = @_; |
37
|
250
|
|
|
|
|
315
|
${$chkmt_ref} = $self->[TYPE] eq 'FILE' |
38
|
|
|
|
|
|
|
? (stat $tmpx)[STAT_MTIME] |
39
|
250
|
100
|
|
|
|
2395
|
: do { |
40
|
2
|
50
|
|
|
|
7
|
DEBUG && LOG( DISABLE_MT => |
41
|
|
|
|
|
|
|
'Disabling chkmt. Template is not a file'); |
42
|
2
|
|
|
|
|
6
|
0; |
43
|
|
|
|
|
|
|
}; |
44
|
250
|
|
|
|
|
350
|
return; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub _compile_cache { |
48
|
18
|
|
|
18
|
|
41
|
my($self, $tmp, $opt, $id_ref, $code_ref) = @_; |
49
|
18
|
|
|
|
|
22
|
my $method = $opt->{id}; |
50
|
18
|
|
66
|
|
|
54
|
my $auto_id = ! $method || $method eq 'AUTO'; |
51
|
18
|
100
|
|
|
|
49
|
${ $id_ref } = $self->connector('Cache::ID')->new->generate( |
|
18
|
|
|
|
|
22
|
|
52
|
|
|
|
|
|
|
$auto_id ? ( $tmp ) : ( $method, 'custom' ) |
53
|
|
|
|
|
|
|
); |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# prevent overwriting the compiled version in cache |
56
|
|
|
|
|
|
|
# since we need the non-compiled version |
57
|
18
|
50
|
|
|
|
48
|
${ $id_ref } .= '_1' if $opt->{as_is}; |
|
0
|
|
|
|
|
0
|
|
58
|
|
|
|
|
|
|
|
59
|
18
|
|
|
|
|
56
|
${ $code_ref } = $self->cache->hit( ${$id_ref}, $opt->{chkmt} ); |
|
18
|
|
|
|
|
26
|
|
|
18
|
|
|
|
|
72
|
|
60
|
18
|
50
|
33
|
|
|
36
|
LOG( CACHE_HIT => ${$id_ref} ) if DEBUG && ${$code_ref}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
61
|
18
|
|
|
|
|
32
|
return; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub _compile { |
65
|
506
|
|
|
506
|
|
1422
|
my $self = shift; |
66
|
506
|
|
33
|
|
|
1055
|
my $tmpx = shift || fatal('tts.base.compiler._compile.notmp'); |
67
|
506
|
|
100
|
|
|
1675
|
my $param = shift || []; |
68
|
506
|
|
|
|
|
1070
|
my $opt = $self->_init_compile_opts( shift ); |
69
|
|
|
|
|
|
|
|
70
|
506
|
50
|
|
|
|
977
|
fatal('tts.base.compiler._compile.param') if ref $param ne 'ARRAY'; |
71
|
|
|
|
|
|
|
|
72
|
506
|
|
|
|
|
1469
|
my $tmp = $self->_examine( $tmpx ); |
73
|
502
|
50
|
|
|
|
1017
|
return $tmp if $self->[TYPE] eq 'ERROR'; |
74
|
|
|
|
|
|
|
|
75
|
502
|
100
|
|
|
|
920
|
if ( $opt->{_sub_inc} ) { |
76
|
|
|
|
|
|
|
# TODO:generate a single error handler for includes, merge with _include() |
77
|
|
|
|
|
|
|
# tmpx is a "file" included from an upper level compile() |
78
|
266
|
|
|
|
|
640
|
my $etitle = $self->_include_error( T_DYNAMIC ); |
79
|
266
|
|
|
|
|
566
|
my $exists = $self->io->file_exists( $tmpx ); |
80
|
266
|
50
|
|
|
|
516
|
return $etitle . " '$tmpx' is not a file" if not $exists; |
81
|
|
|
|
|
|
|
# TODO: remove this second call somehow, reduce to a single call |
82
|
266
|
|
|
|
|
499
|
$tmp = $self->_examine( $exists ); # re-examine |
83
|
266
|
|
|
|
|
348
|
$self->[NEEDS_OBJECT]++; # interpolated includes will need that |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
502
|
100
|
|
|
|
1324
|
$self->_validate_chkmt( \$opt->{chkmt}, $tmpx ) if $opt->{chkmt}; |
87
|
|
|
|
|
|
|
|
88
|
502
|
50
|
33
|
|
|
800
|
LOG( COMPILE => $opt->{id} ) if DEBUG && defined $opt->{id}; |
89
|
|
|
|
|
|
|
|
90
|
502
|
|
|
|
|
503
|
my $cache_id = EMPTY_STRING; |
91
|
|
|
|
|
|
|
|
92
|
502
|
|
|
|
|
361
|
my($CODE); |
93
|
502
|
100
|
|
|
|
981
|
$self->_compile_cache( $tmp, $opt, \$cache_id, \$CODE ) if $self->[CACHE]; |
94
|
|
|
|
|
|
|
|
95
|
502
|
|
|
|
|
1066
|
$self->cache->id( $cache_id ); # if $cache_id; |
96
|
502
|
100
|
|
|
|
1023
|
$self->[FILENAME] = $self->[TYPE] eq 'FILE' ? $tmpx : $self->cache->id; |
97
|
|
|
|
|
|
|
|
98
|
502
|
100
|
|
|
|
1010
|
my($shead, @sparam) = $opt->{_share} ? @{$opt->{_share}} : (); |
|
6
|
|
|
|
|
12
|
|
99
|
|
|
|
|
|
|
|
100
|
502
|
50
|
33
|
|
|
764
|
LOG( |
101
|
|
|
|
|
|
|
SHARED_VARS => "Adding shared variables ($shead) from a dynamic include" |
102
|
|
|
|
|
|
|
) if DEBUG && $shead; |
103
|
|
|
|
|
|
|
|
104
|
502
|
100
|
|
|
|
1742
|
$CODE = $self->_cache_miss( $cache_id, $shead, \@sparam, $opt, $tmp ) if ! $CODE; |
105
|
|
|
|
|
|
|
|
106
|
502
|
|
|
|
|
464
|
my @args; |
107
|
502
|
100
|
|
|
|
1032
|
push @args, $self if $self->[NEEDS_OBJECT]; # must be the first |
108
|
502
|
100
|
|
|
|
821
|
push @args, @sparam if @sparam; |
109
|
502
|
100
|
|
|
|
764
|
push @args, @{ $self->[ADD_ARGS] } if $self->[ADD_ARGS]; |
|
12
|
|
|
|
|
26
|
|
110
|
502
|
|
|
|
|
528
|
push @args, @{ $param }; |
|
502
|
|
|
|
|
547
|
|
111
|
502
|
|
|
|
|
9735
|
my $out = $CODE->( @args ); |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
$self->_call_filters( \$out, split RE_FILTER_SPLIT, $opt->{_filter} ) |
114
|
500
|
100
|
|
|
|
5692
|
if $opt->{_filter}; |
115
|
|
|
|
|
|
|
|
116
|
500
|
|
|
|
|
2283
|
return $out; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub _cache_miss { |
120
|
498
|
|
|
498
|
|
681
|
my($self, $cache_id, $shead, $sparam, $opt, $tmp) = @_; |
121
|
|
|
|
|
|
|
# we have a cache miss; parse and compile |
122
|
498
|
50
|
|
|
|
741
|
LOG( CACHE_MISS => $cache_id ) if DEBUG; |
123
|
|
|
|
|
|
|
|
124
|
498
|
|
|
|
|
439
|
my $restore_header; |
125
|
498
|
100
|
|
|
|
752
|
if ( $shead ) { |
126
|
6
|
|
|
|
|
6
|
my $param_x = join q{,}, ('shift') x @{ $sparam }; |
|
6
|
|
|
|
|
13
|
|
127
|
6
|
|
|
|
|
18
|
my $shared = sprintf q~my(%s) = (%s);~, $shead, $param_x; |
128
|
6
|
|
|
|
|
8
|
$restore_header = $self->[HEADER]; |
129
|
6
|
|
50
|
|
|
28
|
$self->[HEADER] = $shared . q{;} . ( $self->[HEADER] || EMPTY_STRING ); |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
498
|
|
|
|
|
388
|
my %popt = ( %{ $opt }, cache_id => $cache_id, as_is => $opt->{as_is} ); |
|
498
|
|
|
|
|
2867
|
|
133
|
498
|
|
|
|
|
1671
|
my $parsed = $self->_parse( $tmp, \%popt ); |
134
|
498
|
|
|
|
|
1439
|
my $CODE = $self->cache->populate( $cache_id, $parsed, $opt->{chkmt} ); |
135
|
498
|
100
|
|
|
|
774
|
$self->[HEADER] = $restore_header if $shead; |
136
|
498
|
|
|
|
|
1245
|
return $CODE; |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub _call_filters { |
140
|
4
|
|
|
4
|
|
9
|
my($self, $oref, @filters) = @_; |
141
|
4
|
|
|
|
|
6
|
my $fname = $self->[FILENAME]; |
142
|
|
|
|
|
|
|
|
143
|
4
|
|
|
|
|
10
|
APPLY_FILTERS: foreach my $filter ( @filters ) { |
144
|
6
|
|
|
|
|
58
|
my $fref = DUMMY_CLASS->can( 'filter_' . $filter ); |
145
|
6
|
50
|
|
|
|
15
|
if ( ! $fref ) { |
146
|
0
|
|
|
|
|
0
|
${$oref} .= "\n[ filter warning ] Can not apply undefined filter" |
|
0
|
|
|
|
|
0
|
|
147
|
|
|
|
|
|
|
. " $filter to $fname\n"; |
148
|
0
|
|
|
|
|
0
|
next; |
149
|
|
|
|
|
|
|
} |
150
|
6
|
|
|
|
|
15
|
$fref->( $self, $oref ); |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
4
|
|
|
|
|
42
|
return; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub _wrap_compile { |
157
|
500
|
|
|
500
|
|
508
|
my $self = shift; |
158
|
500
|
50
|
|
|
|
822
|
my $parsed = shift or fatal('tts.base.compiler._wrap_compile.parsed'); |
159
|
500
|
50
|
33
|
|
|
1111
|
LOG( CACHE_ID => $self->cache->id ) if $self->[WARN_IDS] && $self->cache->id; |
160
|
500
|
0
|
|
|
|
784
|
LOG( COMPILER => $self->[SAFE] ? 'Safe' : 'Normal' ) if DEBUG; |
|
|
50
|
|
|
|
|
|
161
|
500
|
|
|
|
|
414
|
my($CODE, $error); |
162
|
|
|
|
|
|
|
|
163
|
500
|
100
|
|
|
|
788
|
my $compiler = $self->[SAFE] ? COMPILER_SAFE : COMPILER; |
164
|
|
|
|
|
|
|
|
165
|
500
|
|
|
|
|
2258
|
$CODE = $compiler->compile( $parsed ); |
166
|
|
|
|
|
|
|
|
167
|
500
|
50
|
|
|
|
2371
|
if( $error = $@ ) { |
168
|
0
|
|
|
|
|
0
|
my $error2; |
169
|
0
|
0
|
|
|
|
0
|
$error .= $error2 if $error2; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
500
|
|
|
|
|
1336
|
return $CODE, $error; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub _mini_compiler { |
176
|
|
|
|
|
|
|
# little dumb compiler for internal templates |
177
|
280
|
|
|
280
|
|
254
|
my $self = shift; |
178
|
280
|
|
33
|
|
|
465
|
my $template = shift || fatal('tts.base.compiler._mini_compiler.notmp'); |
179
|
280
|
|
33
|
|
|
442
|
my $param = shift || fatal('tts.base.compiler._mini_compiler.noparam'); |
180
|
280
|
|
100
|
|
|
405
|
my $opt = shift || {}; |
181
|
|
|
|
|
|
|
|
182
|
280
|
50
|
|
|
|
543
|
fatal('tts.base.compiler._mini_compiler.opt') if ref $opt ne 'HASH'; |
183
|
280
|
50
|
|
|
|
440
|
fatal('tts.base.compiler._mini_compiler.param') if ref $param ne 'HASH'; |
184
|
|
|
|
|
|
|
|
185
|
280
|
|
|
|
|
202
|
foreach my $var ( keys %{ $param } ) { |
|
280
|
|
|
|
|
796
|
|
186
|
898
|
|
|
|
|
1008
|
my $str = $param->{$var}; |
187
|
898
|
|
|
|
|
7574
|
$template =~ s{<%\Q$var\E%>}{$str}xmsg; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
280
|
100
|
|
|
|
3010
|
$template =~ s{\s+}{ }xmsg if $opt->{flatten}; # remove extra spaces |
191
|
280
|
|
|
|
|
735
|
return $template; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
1; |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
__END__ |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=pod |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head1 NAME |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
Text::Template::Simple::Base::Compiler - Base class for Text::Template::Simple |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=head1 SYNOPSIS |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
Private module. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=head1 DESCRIPTION |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
This document describes version C<0.90> of C<Text::Template::Simple::Base::Compiler> |
211
|
|
|
|
|
|
|
released on C<5 July 2016>. |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
Private module. |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=head1 AUTHOR |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
Burak Gursoy <burak@cpan.org>. |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=head1 COPYRIGHT |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
Copyright 2004 - 2016 Burak Gursoy. All rights reserved. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=head1 LICENSE |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
226
|
|
|
|
|
|
|
it under the same terms as Perl itself, either Perl version 5.24.0 or, |
227
|
|
|
|
|
|
|
at your option, any later version of Perl 5 you may have available. |
228
|
|
|
|
|
|
|
=cut |