line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Template::Like::Processor;
|
2
|
|
|
|
|
|
|
|
3
|
13
|
|
|
13
|
|
8055
|
use Template::Like::Stash;
|
|
13
|
|
|
|
|
46
|
|
|
13
|
|
|
|
|
414
|
|
4
|
13
|
|
|
13
|
|
9855
|
use Template::Like::Filters;
|
|
13
|
|
|
|
|
34
|
|
|
13
|
|
|
|
|
499
|
|
5
|
13
|
|
|
13
|
|
7268
|
use Template::Like::VMethods;
|
|
13
|
|
|
|
|
36
|
|
|
13
|
|
|
|
|
998
|
|
6
|
|
|
|
|
|
|
|
7
|
13
|
|
|
|
|
1541
|
use constant TAG_STYLE_SET => {
|
8
|
|
|
|
|
|
|
template1 => ['[\\[%]%', '%[\\]%]'],
|
9
|
|
|
|
|
|
|
template => ['\\[%', '%\\]'],
|
10
|
|
|
|
|
|
|
metatext => ['%%', '%%'],
|
11
|
|
|
|
|
|
|
star => ['\\[\\*', '\\*\\]'],
|
12
|
|
|
|
|
|
|
php => ['<\\?', '\\?>'],
|
13
|
|
|
|
|
|
|
asp => ['<%', '%>'],
|
14
|
|
|
|
|
|
|
mason => ['<%', '>'],
|
15
|
|
|
|
|
|
|
html => ['']
|
16
|
13
|
|
|
13
|
|
104
|
};
|
|
13
|
|
|
|
|
30
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# CHOMP constants for PRE_CHOMP and POST_CHOMP
|
19
|
13
|
|
|
13
|
|
71
|
use constant CHOMP_NONE => 0; # do not remove whitespace
|
|
13
|
|
|
|
|
26
|
|
|
13
|
|
|
|
|
563
|
|
20
|
13
|
|
|
13
|
|
146
|
use constant CHOMP_ALL => 1; # remove whitespace up to newline
|
|
13
|
|
|
|
|
22
|
|
|
13
|
|
|
|
|
589
|
|
21
|
13
|
|
|
13
|
|
75
|
use constant CHOMP_ONE => 1; # new name for CHOMP_ALL
|
|
13
|
|
|
|
|
23
|
|
|
13
|
|
|
|
|
609
|
|
22
|
13
|
|
|
13
|
|
75
|
use constant CHOMP_COLLAPSE => 2; # collapse whitespace to a single space
|
|
13
|
|
|
|
|
20
|
|
|
13
|
|
|
|
|
672
|
|
23
|
13
|
|
|
13
|
|
64
|
use constant CHOMP_GREEDY => 3; # remove all whitespace including newlines
|
|
13
|
|
|
|
|
30
|
|
|
13
|
|
|
|
|
20450
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# code set.
|
26
|
|
|
|
|
|
|
my $codeSet = {
|
27
|
|
|
|
|
|
|
IF => 'if ( %s ) {',
|
28
|
|
|
|
|
|
|
IF_POST => '}',
|
29
|
|
|
|
|
|
|
UNLESS => 'unless ( %s ) {',
|
30
|
|
|
|
|
|
|
UNLESS_POST => '}',
|
31
|
|
|
|
|
|
|
ELSIF => 'elsif ( %s ) {',
|
32
|
|
|
|
|
|
|
ELSIF_POST => '}',
|
33
|
|
|
|
|
|
|
ELSE => 'else {',
|
34
|
|
|
|
|
|
|
ELSE_POST => '}',
|
35
|
|
|
|
|
|
|
END => '%s',
|
36
|
|
|
|
|
|
|
FILTER => '{ my $filterOffset = length $output;',
|
37
|
|
|
|
|
|
|
FILTER_POST => 'substr($output, $filterOffset) = $self->filter(%s, substr($output, $filterOffset), %s); };',
|
38
|
|
|
|
|
|
|
DUMMY => "\$output.= %s;\n=pod",
|
39
|
|
|
|
|
|
|
DUMMY_POST => "\n=cut\n",
|
40
|
|
|
|
|
|
|
INSERT => '$output.= $self->insert(%s);',
|
41
|
|
|
|
|
|
|
INCLUDE => '$output.= $self->include(%s);',
|
42
|
|
|
|
|
|
|
PROCESS => '$output.= $self->process(%s);',
|
43
|
|
|
|
|
|
|
GET => '$output.= %s;',
|
44
|
|
|
|
|
|
|
SET => '%s;',
|
45
|
|
|
|
|
|
|
USE => '$self->plugin_use(\'%s\', %s);',
|
46
|
|
|
|
|
|
|
CALL => '%s;',
|
47
|
|
|
|
|
|
|
PRE_SPACE => '$output.= "%s" unless $self->PRE_CHOMP;',
|
48
|
|
|
|
|
|
|
POST_SPACE => '$output.= "%s" unless $self->POST_CHOMP;',
|
49
|
|
|
|
|
|
|
FOREACH => 'for ( to_array( %s ) ) {
|
50
|
|
|
|
|
|
|
local $stash->{\'%s\'} = $_;',
|
51
|
|
|
|
|
|
|
FOREACH_POST => '}',
|
52
|
|
|
|
|
|
|
WHILE => '{
|
53
|
|
|
|
|
|
|
my $wc = 0;
|
54
|
|
|
|
|
|
|
while ( %s ) {
|
55
|
|
|
|
|
|
|
die "while " . $self->WHILE_LIMIT . " over."
|
56
|
|
|
|
|
|
|
if $self->WHILE_LIMIT && $self->WHILE_LIMIT < ++$wc;',
|
57
|
|
|
|
|
|
|
WHILE_POST => "} }",
|
58
|
|
|
|
|
|
|
TEXT => '$output.= \'%s\';'
|
59
|
|
|
|
|
|
|
};
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
#=====================================================================
|
62
|
|
|
|
|
|
|
# new
|
63
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
64
|
|
|
|
|
|
|
# - API
|
65
|
|
|
|
|
|
|
# $processor = Template::Like::Processor->new( $init_option, $params, $option );
|
66
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
67
|
|
|
|
|
|
|
# - args
|
68
|
|
|
|
|
|
|
# $init_option ...
|
69
|
|
|
|
|
|
|
# $params ... PARAMS ( HASHREF )
|
70
|
|
|
|
|
|
|
# $option ...
|
71
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
72
|
|
|
|
|
|
|
# - returns
|
73
|
|
|
|
|
|
|
# $processor ... Template::Like::Processor Object.
|
74
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
75
|
|
|
|
|
|
|
# - Example
|
76
|
|
|
|
|
|
|
# $processor = Template::Like::Processor->new( $init_option, $params, $option );
|
77
|
|
|
|
|
|
|
#=====================================================================
|
78
|
|
|
|
|
|
|
sub new {
|
79
|
103
|
|
|
103
|
0
|
193
|
my $class = shift;
|
80
|
103
|
|
|
|
|
162
|
my $init_option = shift;
|
81
|
103
|
|
|
|
|
132
|
my $params = shift;
|
82
|
103
|
|
|
|
|
129
|
my $option = shift;
|
83
|
|
|
|
|
|
|
|
84
|
103
|
|
|
|
|
3775
|
my $self = bless {
|
85
|
|
|
|
|
|
|
OPTION => {
|
86
|
|
|
|
|
|
|
INCLUDE_PATH => [],
|
87
|
|
|
|
|
|
|
OUTPUT_PATH => undef,
|
88
|
|
|
|
|
|
|
ABSOLUTE => undef,
|
89
|
|
|
|
|
|
|
RELATIVE => undef,
|
90
|
|
|
|
|
|
|
TAG_STYLE => 'template',
|
91
|
|
|
|
|
|
|
START_TAG => undef,
|
92
|
|
|
|
|
|
|
END_TAG => undef,
|
93
|
|
|
|
|
|
|
FILTERS => {},
|
94
|
|
|
|
|
|
|
LOAD_FILTERS => [],
|
95
|
|
|
|
|
|
|
NAMESPACE => {},
|
96
|
|
|
|
|
|
|
CONSTANTS => undef,
|
97
|
|
|
|
|
|
|
CONSTANT_NAMESPACE => 'constants',
|
98
|
|
|
|
|
|
|
STASH => undef,
|
99
|
|
|
|
|
|
|
DEBUG => undef,
|
100
|
|
|
|
|
|
|
PLUGIN_BASE => [],
|
101
|
|
|
|
|
|
|
PRE_CHOMP => undef,
|
102
|
|
|
|
|
|
|
POST_CHOMP => undef,
|
103
|
|
|
|
|
|
|
WHILE_LIMIT => 1000
|
104
|
|
|
|
|
|
|
}
|
105
|
|
|
|
|
|
|
}, $class;
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# ---------- marge option ------------------------------------------
|
108
|
|
|
|
|
|
|
|
109
|
103
|
|
|
|
|
459
|
@{ $self->{'OPTION'} }{ keys %{ $init_option } } = values %{ $init_option };
|
|
103
|
|
|
|
|
424
|
|
|
103
|
|
|
|
|
186
|
|
|
103
|
|
|
|
|
536
|
|
110
|
|
|
|
|
|
|
|
111
|
103
|
|
|
|
|
165
|
@{ $self->{'OPTION'} }{ keys %{ $option } } = values %{ $option };
|
|
103
|
|
|
|
|
172
|
|
|
103
|
|
|
|
|
161
|
|
|
103
|
|
|
|
|
848
|
|
112
|
|
|
|
|
|
|
|
113
|
103
|
|
|
|
|
233
|
for my $key ( ('INCLUDE_PATH', 'LOAD_FILTERS', 'PLUGIN_BASE') ) {
|
114
|
309
|
100
|
|
|
|
1724
|
unless ( UNIVERSAL::isa($self->{'OPTION'}->{ $key }, 'ARRAY') ) {
|
115
|
16
|
|
|
|
|
60
|
$self->{'OPTION'}->{ $key } = [ $self->{'OPTION'}->{ $key } ];
|
116
|
|
|
|
|
|
|
}
|
117
|
|
|
|
|
|
|
}
|
118
|
|
|
|
|
|
|
|
119
|
103
|
|
|
|
|
173
|
push @{ $self->{'OPTION'}->{'INCLUDE_PATH'} }, File::Spec->curdir();
|
|
103
|
|
|
|
|
769
|
|
120
|
|
|
|
|
|
|
|
121
|
103
|
|
|
|
|
149
|
push @{ $self->{'OPTION'}->{'LOAD_FILTERS'} }, Template::Like::Filters->new;
|
|
103
|
|
|
|
|
1270
|
|
122
|
|
|
|
|
|
|
|
123
|
103
|
|
|
|
|
164
|
push @{ $self->{'OPTION'}->{'PLUGIN_BASE'} }, 'Template::Like::Plugin';
|
|
103
|
|
|
|
|
242
|
|
124
|
|
|
|
|
|
|
|
125
|
103
|
50
|
|
|
|
598
|
if ( not UNIVERSAL::isa($self->{'OPTION'}->{'STASH'}, 'Template::Like::Stash') ) {
|
126
|
103
|
|
|
|
|
701
|
$self->{'OPTION'}->{'STASH'} = Template::Like::Stash->new;
|
127
|
|
|
|
|
|
|
}
|
128
|
|
|
|
|
|
|
|
129
|
103
|
50
|
|
|
|
295
|
if ( not $self->START_TAG ) {
|
130
|
103
|
|
|
|
|
265
|
$self->{'OPTION'}->{'START_TAG'} = TAG_STYLE_SET->{ $self->TAG_STYLE }->[0];
|
131
|
|
|
|
|
|
|
}
|
132
|
|
|
|
|
|
|
|
133
|
103
|
50
|
|
|
|
253
|
if ( not $self->END_TAG ) {
|
134
|
103
|
|
|
|
|
208
|
$self->{'OPTION'}->{'END_TAG'} = TAG_STYLE_SET->{ $self->TAG_STYLE }->[1];
|
135
|
|
|
|
|
|
|
}
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# ---------- init stash --------------------------------------------
|
138
|
|
|
|
|
|
|
|
139
|
103
|
|
|
|
|
258
|
$self->{'STASH'} = $self->{'OPTION'}->{'STASH'};
|
140
|
|
|
|
|
|
|
|
141
|
103
|
|
|
|
|
1534
|
$self->stash->update( $params );
|
142
|
|
|
|
|
|
|
|
143
|
103
|
|
|
|
|
262
|
$self->stash->update( $self->NAMESPACE );
|
144
|
|
|
|
|
|
|
|
145
|
103
|
|
|
|
|
255
|
$self->stash->set( $self->CONSTANT_NAMESPACE, $self->CONSTANTS );
|
146
|
|
|
|
|
|
|
|
147
|
103
|
|
|
|
|
285
|
return $self;
|
148
|
|
|
|
|
|
|
}
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
#=====================================================================
|
153
|
|
|
|
|
|
|
# clone
|
154
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
155
|
|
|
|
|
|
|
# - API
|
156
|
|
|
|
|
|
|
# $processor = $processor->clone;
|
157
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
158
|
|
|
|
|
|
|
# - args
|
159
|
|
|
|
|
|
|
# none
|
160
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
161
|
|
|
|
|
|
|
# - returns
|
162
|
|
|
|
|
|
|
# $processor ... this clone object.
|
163
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
164
|
|
|
|
|
|
|
# - Example
|
165
|
|
|
|
|
|
|
# use lexical stash.
|
166
|
|
|
|
|
|
|
# $processor->clone->process($input);
|
167
|
|
|
|
|
|
|
#=====================================================================
|
168
|
|
|
|
|
|
|
sub clone {
|
169
|
0
|
|
|
0
|
0
|
0
|
my $self = shift;
|
170
|
|
|
|
|
|
|
|
171
|
0
|
|
|
|
|
0
|
my $clone = bless { %{ $self } }, 'Template::Like::Processor';
|
|
0
|
|
|
|
|
0
|
|
172
|
|
|
|
|
|
|
|
173
|
0
|
|
|
|
|
0
|
$clone->{'STASH'} = $self->stash->clone;
|
174
|
|
|
|
|
|
|
|
175
|
0
|
|
|
|
|
0
|
return $clone;
|
176
|
|
|
|
|
|
|
}
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
#=====================================================================
|
181
|
|
|
|
|
|
|
# process
|
182
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
183
|
|
|
|
|
|
|
# - API
|
184
|
|
|
|
|
|
|
# $buffer = $processor->process( $input );
|
185
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
186
|
|
|
|
|
|
|
# - args
|
187
|
|
|
|
|
|
|
# $input ...
|
188
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
189
|
|
|
|
|
|
|
# - returns
|
190
|
|
|
|
|
|
|
# $buffer ... String.
|
191
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
192
|
|
|
|
|
|
|
# - Example
|
193
|
|
|
|
|
|
|
# $buffer = $processor->process( $input );
|
194
|
|
|
|
|
|
|
#=====================================================================
|
195
|
|
|
|
|
|
|
sub process {
|
196
|
103
|
|
|
103
|
0
|
163
|
my $self = shift;
|
197
|
|
|
|
|
|
|
|
198
|
103
|
|
|
|
|
486
|
return $self->execute( $self->compile( $self->load( @_ ) ) );
|
199
|
|
|
|
|
|
|
}
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
#=====================================================================
|
204
|
|
|
|
|
|
|
# load
|
205
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
206
|
|
|
|
|
|
|
# - API
|
207
|
|
|
|
|
|
|
# $text_ref = $processor->load( $input );
|
208
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
209
|
|
|
|
|
|
|
# - args
|
210
|
|
|
|
|
|
|
# $input ...
|
211
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
212
|
|
|
|
|
|
|
# - returns
|
213
|
|
|
|
|
|
|
# $text_ref ... Template Text.
|
214
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
215
|
|
|
|
|
|
|
# - Example
|
216
|
|
|
|
|
|
|
# $text_ref = $processor->load( $input );
|
217
|
|
|
|
|
|
|
#=====================================================================
|
218
|
|
|
|
|
|
|
sub load {
|
219
|
103
|
|
|
103
|
0
|
119
|
my $self = shift;
|
220
|
103
|
|
|
|
|
135
|
my $data = shift;
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
# data is filename
|
223
|
103
|
100
|
|
|
|
513
|
if ( !ref $data ) {
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
224
|
|
|
|
|
|
|
|
225
|
10
|
|
|
|
|
11
|
my $filename = $data;
|
226
|
|
|
|
|
|
|
|
227
|
10
|
|
|
|
|
22
|
$filename=~s|/{2,}|/|g;
|
228
|
|
|
|
|
|
|
|
229
|
10
|
100
|
|
|
|
23
|
if ( not $self->RELATIVE ) {
|
230
|
8
|
100
|
|
|
|
21
|
if ( $filename=~/(?:^|\/)\.+\// ) {
|
231
|
1
|
|
|
|
|
15
|
die "[$filename]: relative paths are not allowed (set RELATIVE option) ";
|
232
|
|
|
|
|
|
|
}
|
233
|
|
|
|
|
|
|
}
|
234
|
|
|
|
|
|
|
|
235
|
9
|
100
|
|
|
|
18
|
if ( not $self->ABSOLUTE ) {
|
236
|
8
|
100
|
|
|
|
46
|
if ( File::Spec->file_name_is_absolute($filename) ) {
|
237
|
1
|
|
|
|
|
15
|
die "[$filename]: absolute paths are not allowed (set ABSOLUTE option)";
|
238
|
|
|
|
|
|
|
}
|
239
|
|
|
|
|
|
|
}
|
240
|
|
|
|
|
|
|
|
241
|
8
|
|
|
|
|
10
|
my $filepath;
|
242
|
|
|
|
|
|
|
|
243
|
8
|
100
|
|
|
|
35
|
if ( File::Spec->file_name_is_absolute($filename) ) {
|
244
|
1
|
50
|
|
|
|
28
|
$filepath = $filename if -f $filename;
|
245
|
|
|
|
|
|
|
} else {
|
246
|
7
|
|
|
|
|
17
|
for my $dir ( $self->INCLUDE_PATH ) {
|
247
|
10
|
100
|
|
|
|
271
|
if (-f File::Spec->catfile( $dir, $filename )) {
|
248
|
7
|
|
|
|
|
56
|
$filepath = File::Spec->catfile( $dir, $filename );
|
249
|
7
|
|
|
|
|
18
|
last;
|
250
|
|
|
|
|
|
|
}
|
251
|
|
|
|
|
|
|
}
|
252
|
|
|
|
|
|
|
}
|
253
|
|
|
|
|
|
|
|
254
|
8
|
50
|
|
|
|
26
|
die "file not found. filename is [$filename] include_path is ["
|
255
|
|
|
|
|
|
|
. join(',', $self->INCLUDE_PATH)
|
256
|
|
|
|
|
|
|
. "]" if not $filepath;
|
257
|
|
|
|
|
|
|
|
258
|
8
|
50
|
33
|
|
|
28
|
die "file open endless loop [$filepath]"
|
259
|
|
|
|
|
|
|
if ( exists $self->{'OPEND'}->{ $filepath } && $self->{'OPEND'}->{ $filepath } > 10 );
|
260
|
|
|
|
|
|
|
|
261
|
8
|
|
|
|
|
20
|
$self->{'OPEND'}->{ $filepath }++;
|
262
|
|
|
|
|
|
|
|
263
|
8
|
50
|
|
|
|
53
|
my $fh = IO::File->new($filepath) or die "file open failure [$filepath]";
|
264
|
|
|
|
|
|
|
|
265
|
8
|
|
|
|
|
741
|
my $input = join '', <$fh>;
|
266
|
8
|
|
|
|
|
38
|
$fh->close;
|
267
|
8
|
|
|
|
|
135
|
return \$input;
|
268
|
|
|
|
|
|
|
}
|
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
elsif ( UNIVERSAL::isa($data, "SCALAR") ) {
|
271
|
92
|
|
|
|
|
131
|
return \do{ my $str = $$data };
|
|
92
|
|
|
|
|
960
|
|
272
|
|
|
|
|
|
|
}
|
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
elsif ( UNIVERSAL::isa($data, "ARRAY") ) {
|
275
|
0
|
|
|
|
|
0
|
return \do{ my $str = join '', @{$data} };
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
276
|
|
|
|
|
|
|
}
|
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
elsif ( UNIVERSAL::isa($data, "GLOB") ) {
|
279
|
1
|
|
|
|
|
2
|
return \do{ my $str = join '', <$data> };
|
|
1
|
|
|
|
|
34
|
|
280
|
|
|
|
|
|
|
}
|
281
|
|
|
|
|
|
|
}
|
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
#=====================================================================
|
286
|
|
|
|
|
|
|
# compile
|
287
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
288
|
|
|
|
|
|
|
# - API
|
289
|
|
|
|
|
|
|
# $code = $processor->compile( $text_ref );
|
290
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
291
|
|
|
|
|
|
|
# - args
|
292
|
|
|
|
|
|
|
# $text_ref ... Template Text Reference.
|
293
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
294
|
|
|
|
|
|
|
# - returns
|
295
|
|
|
|
|
|
|
# $code ... Perl code.
|
296
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
297
|
|
|
|
|
|
|
# - Example
|
298
|
|
|
|
|
|
|
# $code = $processor->compile( $text_ref );
|
299
|
|
|
|
|
|
|
#=====================================================================
|
300
|
|
|
|
|
|
|
sub compile {
|
301
|
101
|
|
|
101
|
0
|
155
|
my $self = shift;
|
302
|
101
|
|
|
|
|
115
|
my $text_ref = shift;
|
303
|
|
|
|
|
|
|
|
304
|
101
|
|
|
|
|
261
|
my $start = $self->START_TAG;
|
305
|
101
|
|
|
|
|
218
|
my $end = $self->END_TAG;
|
306
|
|
|
|
|
|
|
|
307
|
101
|
|
|
|
|
127
|
my @endTask;
|
308
|
101
|
|
|
|
|
138
|
my $code = '';
|
309
|
|
|
|
|
|
|
|
310
|
13
|
|
|
13
|
|
105
|
no warnings 'uninitialized';
|
|
13
|
|
|
|
|
42
|
|
|
13
|
|
|
|
|
50885
|
|
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
my $appendSet = sub {
|
313
|
301
|
|
|
301
|
|
458
|
my $directive = shift;
|
314
|
301
|
|
|
|
|
465
|
my $directive_post = $directive . '_POST';
|
315
|
301
|
|
|
|
|
550
|
my $format = $codeSet->{ $directive };
|
316
|
301
|
|
|
|
|
777
|
$code.= ' ' x scalar( @endTask );
|
317
|
301
|
|
|
|
|
1376
|
$code.= sprintf $format, @_;
|
318
|
301
|
|
|
|
|
423
|
$code.= "\n";
|
319
|
|
|
|
|
|
|
|
320
|
301
|
100
|
|
|
|
1974
|
if ( exists $codeSet->{ $directive_post } ) {
|
321
|
59
|
|
|
|
|
995
|
push @endTask, sprintf($codeSet->{ $directive_post }, @_);
|
322
|
|
|
|
|
|
|
}
|
323
|
101
|
|
|
|
|
586
|
};
|
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
my $escapeQuote = sub {
|
326
|
88
|
|
|
88
|
|
131
|
my $str = shift;
|
327
|
88
|
|
|
|
|
151
|
$str=~s/\'/\\\'/g;
|
328
|
88
|
|
|
|
|
209
|
return $str;
|
329
|
101
|
|
|
|
|
470
|
};
|
330
|
|
|
|
|
|
|
|
331
|
101
|
|
|
|
|
2646
|
while ( $$text_ref=~ s/^(.*?)(?:$start([-=~+]?)(.*?)([-=~+]?)$end)//sx ) {
|
332
|
|
|
|
|
|
|
|
333
|
181
|
|
|
|
|
1027
|
my ($text, $pre_chomp, $ele, $post_chomp) = ($1, $2, $3, $4);
|
334
|
|
|
|
|
|
|
|
335
|
181
|
50
|
|
|
|
673
|
$text = '' unless defined $text;
|
336
|
181
|
50
|
|
|
|
480
|
$ele = '' unless defined $ele;
|
337
|
181
|
|
50
|
|
|
805
|
$pre_chomp ||= $self->PRE_CHOMP || 0;
|
|
|
|
33
|
|
|
|
|
338
|
181
|
|
100
|
|
|
594
|
$post_chomp ||= $self->POST_CHOMP || 0;
|
|
|
|
66
|
|
|
|
|
339
|
181
|
|
|
|
|
335
|
$pre_chomp =~ tr/-=~+/1230/;
|
340
|
181
|
|
|
|
|
217
|
$post_chomp =~ tr/-=~+/1230/;
|
341
|
|
|
|
|
|
|
|
342
|
181
|
50
|
|
|
|
1144
|
if ($pre_chomp == CHOMP_ALL) {
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
343
|
0
|
|
|
|
|
0
|
$text =~ s{ (\n|^) [^\S\n]* \z }{}mx;
|
344
|
|
|
|
|
|
|
} elsif ($pre_chomp == CHOMP_COLLAPSE) {
|
345
|
0
|
|
|
|
|
0
|
$text =~ s{ (\s+) \z }{ }x;
|
346
|
|
|
|
|
|
|
} elsif ($pre_chomp == CHOMP_GREEDY) {
|
347
|
0
|
|
|
|
|
0
|
$text =~ s{ (\s+) \z }{}x;
|
348
|
|
|
|
|
|
|
}
|
349
|
|
|
|
|
|
|
|
350
|
181
|
100
|
|
|
|
1766
|
if ($post_chomp == CHOMP_ALL) {
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
351
|
13
|
|
|
|
|
20
|
$$text_ref =~ s{ ^ ([^\S\n]* \n) }{}x;
|
352
|
|
|
|
|
|
|
} elsif ($post_chomp == CHOMP_COLLAPSE) {
|
353
|
0
|
|
|
|
|
0
|
$$text_ref =~ s{ ^ (\s+) }{ }x;
|
354
|
|
|
|
|
|
|
} elsif ($post_chomp == CHOMP_GREEDY) {
|
355
|
0
|
|
|
|
|
0
|
$$text_ref =~ s{ ^ (\s+) }{}x;
|
356
|
|
|
|
|
|
|
}
|
357
|
|
|
|
|
|
|
|
358
|
181
|
100
|
|
|
|
550
|
$appendSet->( 'TEXT', $escapeQuote->($text) ) if length $text;
|
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
|
361
|
181
|
|
|
|
|
710
|
$ele=~s/^\s+//;
|
362
|
181
|
|
|
|
|
803
|
$ele=~s/\s+$//;
|
363
|
|
|
|
|
|
|
|
364
|
181
|
|
|
|
|
673
|
while ( length $ele ) {
|
365
|
|
|
|
|
|
|
|
366
|
193
|
|
|
|
|
208
|
my ( $directive, @args );
|
367
|
|
|
|
|
|
|
|
368
|
193
|
|
|
|
|
994
|
( $ele, $directive, @args ) = $self->expansion( $ele );
|
369
|
|
|
|
|
|
|
|
370
|
193
|
100
|
|
|
|
1115
|
if ( $directive eq 'END' ) {
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
371
|
39
|
|
|
|
|
72
|
$appendSet->( $directive, ( pop @endTask ) );
|
372
|
|
|
|
|
|
|
}
|
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
elsif ( $directive eq 'ELSE' ) {
|
375
|
13
|
|
|
|
|
30
|
$appendSet->( 'END', ( pop @endTask ) );
|
376
|
13
|
|
|
|
|
114
|
$appendSet->( $directive );
|
377
|
|
|
|
|
|
|
}
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
elsif ( $directive eq 'ELSIF' ) {
|
380
|
7
|
|
|
|
|
17
|
$appendSet->( 'END', ( pop @endTask ) );
|
381
|
7
|
|
|
|
|
16
|
$appendSet->( $directive, @args );
|
382
|
|
|
|
|
|
|
}
|
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
else {
|
385
|
134
|
|
|
|
|
351
|
$appendSet->( $directive, @args );
|
386
|
|
|
|
|
|
|
}
|
387
|
|
|
|
|
|
|
}
|
388
|
|
|
|
|
|
|
}
|
389
|
|
|
|
|
|
|
|
390
|
101
|
100
|
|
|
|
291
|
$appendSet->( 'TEXT', $escapeQuote->($$text_ref) ) if length $$text_ref;
|
391
|
|
|
|
|
|
|
|
392
|
101
|
|
|
|
|
1217
|
return "{\n$code}\n";
|
393
|
|
|
|
|
|
|
}
|
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
# The contents, possibly including any embedded template directives, are inserted intact.
|
396
|
|
|
|
|
|
|
sub insert {
|
397
|
0
|
|
|
0
|
0
|
0
|
${ shift->load(@_) };
|
|
0
|
|
|
|
|
0
|
|
398
|
|
|
|
|
|
|
}
|
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
#
|
401
|
|
|
|
|
|
|
sub include {
|
402
|
0
|
|
|
0
|
0
|
0
|
shift->clone->process(@_);
|
403
|
|
|
|
|
|
|
}
|
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
sub plugin_use {
|
406
|
11
|
|
|
11
|
0
|
16
|
my $self = shift;
|
407
|
11
|
|
|
|
|
14
|
my $key = shift;
|
408
|
11
|
|
|
|
|
13
|
my $plugin_name = $key;
|
409
|
|
|
|
|
|
|
|
410
|
11
|
100
|
|
|
|
33
|
if ($key=~/(.*)=(.*)/){
|
411
|
3
|
|
|
|
|
6
|
$key = $1;
|
412
|
3
|
|
|
|
|
6
|
$plugin_name = $2;
|
413
|
|
|
|
|
|
|
}
|
414
|
|
|
|
|
|
|
|
415
|
11
|
|
|
|
|
23
|
for my $base ( $self->PLUGIN_BASE ) {
|
416
|
|
|
|
|
|
|
|
417
|
11
|
|
|
|
|
19
|
my $plugin_class = $base.'::'.$plugin_name;
|
418
|
|
|
|
|
|
|
|
419
|
11
|
|
|
2
|
|
623
|
eval "use $plugin_class;";
|
|
2
|
|
|
2
|
|
678
|
|
|
2
|
|
|
2
|
|
4
|
|
|
2
|
|
|
2
|
|
33
|
|
|
2
|
|
|
2
|
|
12
|
|
|
2
|
|
|
1
|
|
7
|
|
|
2
|
|
|
|
|
20
|
|
|
2
|
|
|
|
|
13
|
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
24
|
|
|
2
|
|
|
|
|
11
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
21
|
|
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
20
|
|
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
11
|
|
420
|
|
|
|
|
|
|
|
421
|
11
|
50
|
|
|
|
31
|
unless ($@) {
|
422
|
11
|
|
|
|
|
25
|
$self->stash->set( $key, $plugin_class->new($self, @_) );
|
423
|
11
|
|
|
|
|
273
|
return;
|
424
|
|
|
|
|
|
|
}
|
425
|
|
|
|
|
|
|
}
|
426
|
|
|
|
|
|
|
|
427
|
0
|
0
|
|
|
|
0
|
die ($@) if ($@);
|
428
|
|
|
|
|
|
|
}
|
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
#-----------------------------
|
431
|
|
|
|
|
|
|
# expansion
|
432
|
|
|
|
|
|
|
#-----------------------------
|
433
|
|
|
|
|
|
|
sub expansion {
|
434
|
193
|
|
|
193
|
0
|
234
|
my $self = shift;
|
435
|
193
|
|
|
|
|
259
|
my $expression = shift;
|
436
|
|
|
|
|
|
|
|
437
|
193
|
|
|
|
|
207
|
my ( $directive, @pre_opts, @post_opts );
|
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
# -----------------------------------------------------------------
|
440
|
|
|
|
|
|
|
|
441
|
193
|
100
|
|
|
|
2434
|
if ( $expression=~s/^(CALL|GET|SET|IF|UNLESS|ELSIF|DUMMY|PRE_SPACE|POST_SPACE)\s+//x ) {
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
442
|
48
|
|
|
|
|
222
|
$directive = $1;
|
443
|
|
|
|
|
|
|
}
|
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
# USE
|
446
|
|
|
|
|
|
|
elsif ( $expression=~s/^USE\s+// ) {
|
447
|
|
|
|
|
|
|
|
448
|
11
|
|
|
|
|
13
|
$directive = 'USE';
|
449
|
11
|
|
|
|
|
13
|
my $key = '';
|
450
|
11
|
|
|
|
|
12
|
my $code = '';
|
451
|
11
|
|
|
|
|
20
|
my @gets = '';
|
452
|
11
|
|
|
|
|
14
|
my $text = '';
|
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# SET
|
455
|
11
|
100
|
|
|
|
32
|
if ( $expression=~s/^(\w+)\s*=\s*// ) {
|
456
|
3
|
|
|
|
|
6
|
$key = $1.'=';
|
457
|
|
|
|
|
|
|
}
|
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
# ARGUMENTS
|
460
|
11
|
50
|
|
|
|
46
|
if ( $expression=~s/^([a-zA-Z0-9\.]+)// ) {
|
461
|
11
|
|
|
|
|
19
|
$text = $1;
|
462
|
|
|
|
|
|
|
}
|
463
|
|
|
|
|
|
|
|
464
|
11
|
|
|
|
|
32
|
@pre_opts = ( $key.$text );
|
465
|
|
|
|
|
|
|
}
|
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
elsif ( $expression=~/^(FILTER|INSERT|INCLUDE)\s+(\S.*)$/sx ) {
|
468
|
|
|
|
|
|
|
|
469
|
1
|
|
|
|
|
116
|
$directive = $1;
|
470
|
1
|
|
|
|
|
2
|
$expression = $2;
|
471
|
|
|
|
|
|
|
|
472
|
1
|
50
|
|
|
|
7
|
if ($expression=~s/^\$//) {
|
473
|
|
|
|
|
|
|
}
|
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
else {
|
476
|
1
|
50
|
|
|
|
8
|
if ($expression=~s/([^\(\);\s]+)//) {
|
477
|
1
|
|
|
|
|
6
|
my $name = $1;
|
478
|
1
|
|
|
|
|
3
|
$name=~s/\'/\\\'/g;
|
479
|
1
|
|
|
|
|
6
|
@pre_opts = ( "'$name'" );
|
480
|
|
|
|
|
|
|
}
|
481
|
|
|
|
|
|
|
}
|
482
|
|
|
|
|
|
|
}
|
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
# ELSE
|
485
|
|
|
|
|
|
|
elsif ( $expression=~s/ELSE// ) {
|
486
|
13
|
|
|
|
|
18
|
$directive = 'ELSE';
|
487
|
|
|
|
|
|
|
}
|
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
# END
|
490
|
|
|
|
|
|
|
elsif ( $expression=~s/END// ) {
|
491
|
39
|
|
|
|
|
57
|
$directive = 'END';
|
492
|
|
|
|
|
|
|
}
|
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
# FOREACH
|
495
|
|
|
|
|
|
|
elsif ( $expression=~s/^FOREACH\s*(\w+)\s*(?:\=|IN)\s*// ) {
|
496
|
1
|
|
|
|
|
30
|
$directive = 'FOREACH';
|
497
|
1
|
|
|
|
|
3
|
@post_opts = ($1);
|
498
|
|
|
|
|
|
|
}
|
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
# WHILE (?:(\w+)\s*\=\s*)?
|
501
|
|
|
|
|
|
|
elsif ( $expression=~s/^WHILE\s*// ) {
|
502
|
2
|
|
|
|
|
4
|
$directive = 'WHILE';
|
503
|
|
|
|
|
|
|
}
|
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
# OTHER
|
506
|
|
|
|
|
|
|
else {
|
507
|
78
|
|
|
|
|
181
|
$directive = 'GET';
|
508
|
|
|
|
|
|
|
}
|
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
# -----------------------------------------------------------------
|
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
|
514
|
193
|
|
|
|
|
279
|
my $token;
|
515
|
193
|
|
|
|
|
627
|
my $code = '';
|
516
|
193
|
|
|
|
|
250
|
my $depth = 0;
|
517
|
193
|
|
|
|
|
630
|
my $start = { 0 => 0 };
|
518
|
|
|
|
|
|
|
|
519
|
193
|
|
|
|
|
1929
|
while ($expression =~
|
520
|
|
|
|
|
|
|
s/
|
521
|
|
|
|
|
|
|
# strip out any comments
|
522
|
|
|
|
|
|
|
(\#[^\n]*)
|
523
|
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
# a quoted phrase matches in $3
|
525
|
|
|
|
|
|
|
(["']) # $2 - opening quote, ' or "
|
526
|
|
|
|
|
|
|
( # $3 - quoted text buffer
|
527
|
|
|
|
|
|
|
(?: # repeat group (no backreference)
|
528
|
|
|
|
|
|
|
\\\\ # an escaped backslash \\
|
529
|
|
|
|
|
|
|
| \\\2 # an escaped quote \" or \' (match $1)
|
530
|
|
|
|
|
|
|
| . # any other character
|
531
|
|
|
|
|
|
|
| \n # \n
|
532
|
|
|
|
|
|
|
)*? # non-greedy repeat
|
533
|
|
|
|
|
|
|
) # end of $3
|
534
|
|
|
|
|
|
|
\2 # match opening quote
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
# an unquoted number matches in $4
|
537
|
|
|
|
|
|
|
(-?\d+(?:\.\d+)?) # numbers
|
538
|
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
# filename matches in $5
|
540
|
|
|
|
|
|
|
((?!))
|
541
|
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
# an identifier matches in $6
|
543
|
|
|
|
|
|
|
\s*\|\s*([\w]+)\( # variable identifier
|
544
|
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
# an identifier matches in $7
|
546
|
|
|
|
|
|
|
\s*\|\s*([\w]+) # variable identifier
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
# an identifier matches in $8
|
549
|
|
|
|
|
|
|
((?!\_)[\$\.]?\w+)\( # variable identifier
|
550
|
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
# an identifier matches in $9
|
552
|
|
|
|
|
|
|
((?!\_)[\$\.]?\w+)\s*\=(?![=>]) # variable identifier
|
553
|
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
# an identifier matches in $10
|
555
|
|
|
|
|
|
|
((?!\_)[\$\.]?\w+) # variable identifier
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
# an unquoted word or symbol matches in $11
|
558
|
|
|
|
|
|
|
( [(){}\[\]:;,\/\\] # misc parenthesis and symbols
|
559
|
|
|
|
|
|
|
| [+\-*] # math operations
|
560
|
|
|
|
|
|
|
| \$\{? # dollar with option left brace
|
561
|
|
|
|
|
|
|
| != # like 'ne'
|
562
|
|
|
|
|
|
|
| == # like 'eq'
|
563
|
|
|
|
|
|
|
| => # like '='
|
564
|
|
|
|
|
|
|
| [=!<>]?= | [!<>] # equality tests
|
565
|
|
|
|
|
|
|
| &&? | \|\|? # boolean ops
|
566
|
|
|
|
|
|
|
| \.\.? # n..n sequence
|
567
|
|
|
|
|
|
|
| \S+ # something unquoted
|
568
|
|
|
|
|
|
|
| \s+ # something unquoted
|
569
|
|
|
|
|
|
|
) # end of $11
|
570
|
|
|
|
|
|
|
//mxo) {
|
571
|
|
|
|
|
|
|
|
572
|
348
|
100
|
100
|
|
|
4601
|
if (defined ($token = $3)) {
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
573
|
21
|
|
|
|
|
156
|
$code.= $2 . $token . $2;
|
574
|
|
|
|
|
|
|
}
|
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
elsif (defined ($token = $4)) {
|
577
|
8
|
|
|
|
|
918
|
$code.= $token;
|
578
|
|
|
|
|
|
|
}
|
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
elsif (defined ($token = $5)) {
|
581
|
0
|
|
|
|
|
0
|
$token=~s/\'/\\\'/g;
|
582
|
0
|
|
|
|
|
0
|
$code.= "'$token'";
|
583
|
|
|
|
|
|
|
}
|
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
elsif (defined ($token = $6)) {
|
586
|
7
|
|
|
|
|
32
|
$code = sprintf q{$self->filter('%s', %s, }, $token, $code;
|
587
|
7
|
|
|
|
|
53
|
$depth++;
|
588
|
|
|
|
|
|
|
}
|
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
elsif (defined ($token = $7)) {
|
591
|
12
|
|
|
|
|
155
|
$code = sprintf q{$self->filter('%s', %s)}, $token, $code;
|
592
|
|
|
|
|
|
|
}
|
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
elsif (defined ($token = $8)) {
|
595
|
|
|
|
|
|
|
# method after dot.
|
596
|
13
|
50
|
33
|
|
|
93
|
if ( $token=~/^\./ && $code=~/\)$/ ) {
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
597
|
13
|
|
|
|
|
25
|
$token = substr($token, 1);
|
598
|
13
|
|
|
|
|
52
|
substr($code, $start->{ $depth }) =
|
599
|
|
|
|
|
|
|
'$stash->next(' . substr($code, $start->{ $depth }) . ", '$token', ";
|
600
|
|
|
|
|
|
|
}
|
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
# first dollar.
|
603
|
|
|
|
|
|
|
elsif ( $token=~/^\$(.*)$/ ) {
|
604
|
0
|
|
|
|
|
0
|
$start->{ $depth } = length $code;
|
605
|
0
|
|
|
|
|
0
|
$code.= "\$stash->get('$1', ";
|
606
|
|
|
|
|
|
|
}
|
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
# first dot.
|
609
|
|
|
|
|
|
|
elsif ( $token=~/^\.(.*)$/ ) {
|
610
|
0
|
|
|
|
|
0
|
substr($code, $start->{ $depth }) =
|
611
|
|
|
|
|
|
|
'$stash->next(' . substr($code, $start->{ $depth }) . ", '$1', ";
|
612
|
|
|
|
|
|
|
}
|
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
# directive which can omit the dollar.
|
615
|
|
|
|
|
|
|
else {
|
616
|
0
|
|
|
|
|
0
|
$start->{ $depth } = length $code;
|
617
|
0
|
|
|
|
|
0
|
$code.= "\$stash->get('$token', ";
|
618
|
|
|
|
|
|
|
}
|
619
|
13
|
|
|
|
|
88
|
$depth++;
|
620
|
|
|
|
|
|
|
}
|
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
elsif (defined ($token = $9) && $directive eq 'USE') {
|
623
|
|
|
|
|
|
|
|
624
|
2
|
|
|
|
|
15
|
$code.= "$token =>";
|
625
|
|
|
|
|
|
|
}
|
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
elsif (defined ($token = $9)) {
|
628
|
|
|
|
|
|
|
|
629
|
4
|
100
|
|
|
|
15
|
if ( $directive eq 'GET' ) {
|
630
|
1
|
|
|
|
|
2
|
$directive = 'SET';
|
631
|
|
|
|
|
|
|
}
|
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
# method after dot.
|
634
|
4
|
100
|
66
|
|
|
40
|
if ( $token=~/^\./ && $code=~/\)$/ ) {
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
635
|
1
|
|
|
|
|
3
|
$token = substr($token, 1);
|
636
|
1
|
|
|
|
|
17
|
$code.= "->{'$token'} =";
|
637
|
|
|
|
|
|
|
}
|
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
# first dollar.
|
640
|
|
|
|
|
|
|
elsif ( $token=~/^\$(.*)$/ ) {
|
641
|
0
|
|
|
|
|
0
|
$code.= "\$stash->{'$1'} =";
|
642
|
|
|
|
|
|
|
}
|
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
# first dot.
|
645
|
|
|
|
|
|
|
elsif ( $token=~/^\.(.*)$/ ) {
|
646
|
0
|
|
|
|
|
0
|
$code.= "->{'$1'} =";
|
647
|
|
|
|
|
|
|
}
|
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
else {
|
650
|
3
|
|
|
|
|
26
|
$code.= "\$stash->{'$token'} =";
|
651
|
|
|
|
|
|
|
}
|
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
# $start->{ $depth } = length $code;
|
654
|
|
|
|
|
|
|
}
|
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
elsif (defined ($token = $10)) {
|
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
# method after dot.
|
659
|
168
|
100
|
66
|
|
|
1925
|
if ( $token=~/^\./ && $code=~/\)$/ ) {
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
660
|
27
|
|
|
|
|
55
|
$token = substr($token, 1);
|
661
|
27
|
|
|
|
|
673
|
substr($code, $start->{ $depth }) =
|
662
|
|
|
|
|
|
|
'$stash->next(' . substr($code, $start->{ $depth }) . ", '$token')";
|
663
|
|
|
|
|
|
|
}
|
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
# first dollar.
|
666
|
|
|
|
|
|
|
elsif ( $token=~/^\$(.*)$/ ) {
|
667
|
0
|
|
|
|
|
0
|
$start->{ $depth } = length $code;
|
668
|
0
|
|
|
|
|
0
|
$code.= "\$stash->get('$1')";
|
669
|
|
|
|
|
|
|
}
|
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
# first dot.
|
672
|
|
|
|
|
|
|
elsif ( $token=~/^\.(.*)$/ ) {
|
673
|
0
|
|
|
|
|
0
|
substr($code, $start->{ $depth }) =
|
674
|
|
|
|
|
|
|
'$stash->next(' . substr($code, $start->{ $depth }) . ", '$1')";
|
675
|
|
|
|
|
|
|
}
|
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
else {
|
678
|
141
|
|
|
|
|
259
|
$start->{ $depth } = length $code;
|
679
|
141
|
|
|
|
|
1197
|
$code.= "\$stash->get('$token')";
|
680
|
|
|
|
|
|
|
}
|
681
|
|
|
|
|
|
|
}
|
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
elsif (defined ($token = $11)) {
|
684
|
113
|
100
|
|
|
|
979
|
if ( $token eq '==' ) {
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
685
|
6
|
|
|
|
|
44
|
$code.= ' eq ';
|
686
|
|
|
|
|
|
|
} elsif ( $token eq '!=' ) {
|
687
|
2
|
|
|
|
|
15
|
$code.= ' ne ';
|
688
|
|
|
|
|
|
|
} elsif ( $token eq '_' ) {
|
689
|
0
|
|
|
|
|
0
|
$code.= '.';
|
690
|
|
|
|
|
|
|
} elsif ( $token eq ')' ) {
|
691
|
23
|
|
|
|
|
29
|
$code.= ')';
|
692
|
23
|
|
|
|
|
146
|
$depth--;
|
693
|
|
|
|
|
|
|
} elsif ( $token eq ';' ) {
|
694
|
12
|
|
|
|
|
124
|
return ( $expression, $directive, @pre_opts, $code, @post_opts );
|
695
|
|
|
|
|
|
|
} else {
|
696
|
70
|
|
|
|
|
449
|
$code.= $token;
|
697
|
|
|
|
|
|
|
}
|
698
|
|
|
|
|
|
|
}
|
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
# warn "depth: " . $depth;
|
701
|
|
|
|
|
|
|
# warn "start: " . $start->{ $depth };
|
702
|
|
|
|
|
|
|
# warn "token: $token";
|
703
|
|
|
|
|
|
|
# warn "code: " . $code . "\n";
|
704
|
|
|
|
|
|
|
}
|
705
|
|
|
|
|
|
|
|
706
|
181
|
|
|
|
|
1075
|
return ( $expression, $directive, @pre_opts, $code, @post_opts );
|
707
|
|
|
|
|
|
|
}
|
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
#=====================================================================
|
712
|
|
|
|
|
|
|
# filter
|
713
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
714
|
|
|
|
|
|
|
# - API
|
715
|
|
|
|
|
|
|
# $buffer = $processor->filter( $name, $buffer, @ARGS... );
|
716
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
717
|
|
|
|
|
|
|
# - args
|
718
|
|
|
|
|
|
|
# $name ... Filter Name.
|
719
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
720
|
|
|
|
|
|
|
# - returns
|
721
|
|
|
|
|
|
|
# $buffer ... buffer.
|
722
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
723
|
|
|
|
|
|
|
# - Example
|
724
|
|
|
|
|
|
|
# $buffer = $processor->filter( $name );
|
725
|
|
|
|
|
|
|
#=====================================================================
|
726
|
|
|
|
|
|
|
sub filter {
|
727
|
22
|
|
|
22
|
0
|
36
|
my $self = shift;
|
728
|
22
|
|
|
|
|
33
|
my $name = shift;
|
729
|
|
|
|
|
|
|
|
730
|
22
|
100
|
|
|
|
61
|
if ( exists $self->FILTERS->{ $name } ) {
|
731
|
4
|
|
|
|
|
11
|
return $self->FILTERS->{ $name }->( @_ );
|
732
|
|
|
|
|
|
|
}
|
733
|
|
|
|
|
|
|
|
734
|
18
|
|
|
|
|
54
|
for my $filter ( $self->LOAD_FILTERS ) {
|
735
|
18
|
50
|
|
|
|
161
|
if ( UNIVERSAL::can($filter, $name) ) {
|
736
|
18
|
|
|
|
|
236
|
return $filter->$name( @_ );
|
737
|
|
|
|
|
|
|
}
|
738
|
|
|
|
|
|
|
}
|
739
|
|
|
|
|
|
|
|
740
|
0
|
|
|
|
|
0
|
die "not defined filter [$name].";
|
741
|
|
|
|
|
|
|
}
|
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
#=====================================================================
|
746
|
|
|
|
|
|
|
# execute
|
747
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
748
|
|
|
|
|
|
|
# - API
|
749
|
|
|
|
|
|
|
# $buffer = $processor->execute( $code );
|
750
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
751
|
|
|
|
|
|
|
# - args
|
752
|
|
|
|
|
|
|
# $code ... Perl code.
|
753
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
754
|
|
|
|
|
|
|
# - returns
|
755
|
|
|
|
|
|
|
# $buffer ... buffer.
|
756
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
757
|
|
|
|
|
|
|
# - Example
|
758
|
|
|
|
|
|
|
# $buffer = $processor->execute( $code );
|
759
|
|
|
|
|
|
|
#=====================================================================
|
760
|
|
|
|
|
|
|
sub execute {
|
761
|
101
|
|
|
101
|
0
|
222
|
my $self = shift;
|
762
|
101
|
|
|
|
|
138
|
my $code = shift;
|
763
|
|
|
|
|
|
|
|
764
|
101
|
|
|
|
|
142
|
my $output = '';
|
765
|
101
|
|
|
|
|
220
|
my $stash = $self->stash;
|
766
|
|
|
|
|
|
|
|
767
|
101
|
50
|
|
|
|
416
|
warn $code if $self->DEBUG;
|
768
|
|
|
|
|
|
|
|
769
|
13
|
|
|
13
|
|
119
|
no warnings 'uninitialized';
|
|
13
|
|
|
|
|
27
|
|
|
13
|
|
|
|
|
11890
|
|
770
|
101
|
|
|
|
|
14356
|
eval $code;
|
771
|
101
|
50
|
|
|
|
765
|
die sprintf("Template::Like Error: %s\ncode: \n%s", $@, $code) if $@;
|
772
|
|
|
|
|
|
|
|
773
|
101
|
|
|
|
|
571
|
return $output;
|
774
|
|
|
|
|
|
|
}
|
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
#=====================================================================
|
777
|
|
|
|
|
|
|
# filalize
|
778
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
779
|
|
|
|
|
|
|
# - API
|
780
|
|
|
|
|
|
|
# $processor->finalize( $buffer, $output );
|
781
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
782
|
|
|
|
|
|
|
# - args
|
783
|
|
|
|
|
|
|
# $buffer ... Perl code.
|
784
|
|
|
|
|
|
|
# $output ... Perl code.
|
785
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
786
|
|
|
|
|
|
|
# - returns
|
787
|
|
|
|
|
|
|
# none.
|
788
|
|
|
|
|
|
|
#---------------------------------------------------------------------
|
789
|
|
|
|
|
|
|
# - Example
|
790
|
|
|
|
|
|
|
# $processor->finalize( $buffer, $output );
|
791
|
|
|
|
|
|
|
#=====================================================================
|
792
|
|
|
|
|
|
|
sub finalize {
|
793
|
101
|
|
|
101
|
0
|
248
|
my $self = shift;
|
794
|
101
|
|
|
|
|
143
|
my $buffer = shift;
|
795
|
101
|
|
|
|
|
115
|
my $output = shift;
|
796
|
|
|
|
|
|
|
|
797
|
101
|
100
|
|
|
|
253
|
if ( ref $output ) {
|
798
|
|
|
|
|
|
|
|
799
|
98
|
100
|
|
|
|
301
|
if ( UNIVERSAL::isa($output, 'SCALAR') ) {
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
800
|
95
|
|
|
|
|
117
|
${ $output }.= $buffer;
|
|
95
|
|
|
|
|
1199
|
|
801
|
|
|
|
|
|
|
}
|
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
elsif ( UNIVERSAL::isa($output, 'ARRAY') ) {
|
804
|
1
|
|
|
|
|
2
|
push @{ $output }, $buffer;
|
|
1
|
|
|
|
|
7
|
|
805
|
|
|
|
|
|
|
}
|
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
elsif ( UNIVERSAL::isa($output, 'CODE') ) {
|
808
|
1
|
|
|
|
|
5
|
$output->($buffer);
|
809
|
|
|
|
|
|
|
}
|
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
# filehandle
|
812
|
|
|
|
|
|
|
elsif ( UNIVERSAL::isa($output, 'GLOB') ) {
|
813
|
0
|
|
|
|
|
0
|
print $output $buffer;
|
814
|
|
|
|
|
|
|
}
|
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
# Apache::Request, Apache2::Request ...
|
817
|
|
|
|
|
|
|
elsif ( UNIVERSAL::can($output, 'print') ) {
|
818
|
1
|
|
|
|
|
4
|
$output->print($buffer);
|
819
|
|
|
|
|
|
|
}
|
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
else {
|
822
|
0
|
|
|
|
|
0
|
die "no support output [$output]";
|
823
|
|
|
|
|
|
|
}
|
824
|
|
|
|
|
|
|
}
|
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
# filename
|
827
|
|
|
|
|
|
|
else {
|
828
|
|
|
|
|
|
|
|
829
|
3
|
100
|
|
|
|
7
|
my $path = $self->OUTPUT_PATH
|
830
|
|
|
|
|
|
|
? File::Spec->catfile( $self->OUTPUT_PATH, $output )
|
831
|
|
|
|
|
|
|
: $output;
|
832
|
|
|
|
|
|
|
|
833
|
3
|
50
|
|
|
|
75
|
my $mark = -f $path ? '+<' : '>';
|
834
|
3
|
50
|
|
|
|
24
|
my $fh = new IO::File $mark.$path
|
835
|
|
|
|
|
|
|
or $self->error("output file open failure [".$path."]");
|
836
|
|
|
|
|
|
|
|
837
|
3
|
|
|
|
|
353
|
seek $fh, 0, 0;
|
838
|
3
|
|
|
|
|
29
|
print $fh $buffer;
|
839
|
3
|
|
|
|
|
185
|
truncate $fh, tell($fh);
|
840
|
3
|
|
|
|
|
61
|
close $fh;
|
841
|
|
|
|
|
|
|
}
|
842
|
|
|
|
|
|
|
}
|
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
sub to_array {
|
845
|
1
|
50
|
33
|
1
|
0
|
15
|
return @{ $_[0] } if @_ == 1 && UNIVERSAL::isa($_[0], 'ARRAY');
|
|
1
|
|
|
|
|
32
|
|
846
|
0
|
|
|
|
|
0
|
return @_;
|
847
|
|
|
|
|
|
|
}
|
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
#-----------------------------
|
851
|
|
|
|
|
|
|
# Accessors
|
852
|
|
|
|
|
|
|
#-----------------------------
|
853
|
421
|
|
|
421
|
0
|
1541
|
sub stash { $_[0]->{'STASH'}; }
|
854
|
0
|
|
|
0
|
0
|
0
|
sub error { die @_; };
|
855
|
|
|
|
|
|
|
|
856
|
101
|
|
|
101
|
0
|
321
|
sub DEBUG { $_[0]->{'OPTION'}->{'DEBUG'} }
|
857
|
5
|
|
|
5
|
0
|
43
|
sub OUTPUT_PATH { $_[0]->{'OPTION'}->{'OUTPUT_PATH'} }
|
858
|
9
|
|
|
9
|
0
|
24
|
sub ABSOLUTE { $_[0]->{'OPTION'}->{'ABSOLUTE'} }
|
859
|
10
|
|
|
10
|
0
|
28
|
sub RELATIVE { $_[0]->{'OPTION'}->{'RELATIVE'} }
|
860
|
206
|
|
|
206
|
0
|
16371
|
sub TAG_STYLE { $_[0]->{'OPTION'}->{'TAG_STYLE'} }
|
861
|
204
|
|
|
204
|
0
|
647
|
sub START_TAG { $_[0]->{'OPTION'}->{'START_TAG'} }
|
862
|
204
|
|
|
204
|
0
|
504
|
sub END_TAG { $_[0]->{'OPTION'}->{'END_TAG'} }
|
863
|
26
|
|
|
26
|
0
|
120
|
sub FILTERS { $_[0]->{'OPTION'}->{'FILTERS'} }
|
864
|
103
|
|
|
103
|
0
|
381
|
sub NAMESPACE { $_[0]->{'OPTION'}->{'NAMESPACE'} }
|
865
|
103
|
|
|
103
|
0
|
407
|
sub CONSTANTS { $_[0]->{'OPTION'}->{'CONSTANTS'} }
|
866
|
103
|
|
|
103
|
0
|
675
|
sub CONSTANT_NAMESPACE { $_[0]->{'OPTION'}->{'CONSTANT_NAMESPACE'} }
|
867
|
7
|
|
|
7
|
0
|
7
|
sub INCLUDE_PATH { @{ $_[0]->{'OPTION'}->{'INCLUDE_PATH'} } }
|
|
7
|
|
|
|
|
23
|
|
868
|
18
|
|
|
18
|
0
|
23
|
sub LOAD_FILTERS { @{ $_[0]->{'OPTION'}->{'LOAD_FILTERS'} } }
|
|
18
|
|
|
|
|
59
|
|
869
|
11
|
|
|
11
|
0
|
11
|
sub PLUGIN_BASE { @{ $_[0]->{'OPTION'}->{'PLUGIN_BASE'} } }
|
|
11
|
|
|
|
|
36
|
|
870
|
181
|
|
|
181
|
0
|
1008
|
sub PRE_CHOMP { $_[0]->{'OPTION'}->{'PRE_CHOMP'} }
|
871
|
181
|
|
|
181
|
0
|
1654
|
sub POST_CHOMP { $_[0]->{'OPTION'}->{'POST_CHOMP'} }
|
872
|
12
|
|
|
12
|
0
|
691
|
sub WHILE_LIMIT { $_[0]->{'OPTION'}->{'WHILE_LIMIT'} }
|
873
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
1; |