line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl -w |
2
|
|
|
|
|
|
|
# $Id: BasicTemplate.pm,v 1.31 2000/02/22 01:55:52 aqua Exp $ |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package Text::BasicTemplate; |
5
|
|
|
|
|
|
|
|
6
|
7
|
|
|
7
|
|
8135
|
use strict; |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
597
|
|
7
|
7
|
|
|
7
|
|
36
|
use re 'taint'; |
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
461
|
|
8
|
|
|
|
|
|
|
require 5; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
require Exporter; |
11
|
|
|
|
|
|
|
require AutoLoader; |
12
|
|
|
|
|
|
|
|
13
|
7
|
|
|
7
|
|
195
|
use vars qw($VERSION); |
|
7
|
|
|
|
|
22
|
|
|
7
|
|
|
|
|
492
|
|
14
|
|
|
|
|
|
|
$VERSION = "2.006.1"; |
15
|
|
|
|
|
|
|
|
16
|
7
|
|
|
7
|
|
36
|
use Fcntl qw(:DEFAULT :flock); |
|
7
|
|
|
|
|
10
|
|
|
7
|
|
|
|
|
71605
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 NAME |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
Text::BasicTemplate -- Simple lexical text/html/etc template parser |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=cut |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 SYNOPSIS |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
use Text::BasicTemplate; |
27
|
|
|
|
|
|
|
$bt = Text::BasicTemplate->new; |
28
|
|
|
|
|
|
|
my %dict = ( |
29
|
|
|
|
|
|
|
name => 'John', |
30
|
|
|
|
|
|
|
location => sub { hostname() }, |
31
|
|
|
|
|
|
|
condiments => [ 'Salt', 'Pepper', 'Catsup' ], |
32
|
|
|
|
|
|
|
sideeffects => { 'Salt' => 'causes high blood pressure', |
33
|
|
|
|
|
|
|
'Pepper' => 'causes mariachi music', |
34
|
|
|
|
|
|
|
'Catsup' => 'brings on warner bros. cartoons' }, |
35
|
|
|
|
|
|
|
new => int rand 2 |
36
|
|
|
|
|
|
|
); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
$tmpl = "Hello, %name%; your mail is in %$MAIL%. Welcome to %location%!"; |
39
|
|
|
|
|
|
|
print $bt->parse(\$tmpl,\%dict); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
$tmpl = "%if new%First time, %name%?%fi%". |
42
|
|
|
|
|
|
|
" Care for some %condiments%? ". |
43
|
|
|
|
|
|
|
" They are bad for you. %sideeffects%." |
44
|
|
|
|
|
|
|
$bt->{hash_specifier}->{condiments} = ' '; |
45
|
|
|
|
|
|
|
print $bt->parse(\$tmpl,\%dict); |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 DESCRIPTION |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
B is a relatively straightforward template |
50
|
|
|
|
|
|
|
parsing module. Its overall function is to permit the separation |
51
|
|
|
|
|
|
|
of format-dependent output from code. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
This module provides standard key/value substitutions, lexical |
54
|
|
|
|
|
|
|
evaluation/parsing, customizable formatting of perl datatypes, |
55
|
|
|
|
|
|
|
and assorted utility functions. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
Templates may be structured by the use of arbitrarily nestable |
58
|
|
|
|
|
|
|
if-conditions (including elsif and else), and by the use of |
59
|
|
|
|
|
|
|
subroutine substitutions to provide list parsing. In general, |
60
|
|
|
|
|
|
|
the syntax for conditionals is that of perl itself. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
Text::BasicTemplate attempts to be as fast and as secure as |
63
|
|
|
|
|
|
|
possible. It may be safely used upon tainted templates and |
64
|
|
|
|
|
|
|
with tainted substitutions without fear of execution of any |
65
|
|
|
|
|
|
|
malicious code. |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head1 GETTING STARTED |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
If you have previously used Text::BasicTemplate v0.x, it is |
70
|
|
|
|
|
|
|
important to read the COMPATIBILITY section -- many things |
71
|
|
|
|
|
|
|
have changed, and compatibility is not guaranteed to be |
72
|
|
|
|
|
|
|
preserved in future versions. |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
In general, start with the SYNTAX section, and be sure to |
75
|
|
|
|
|
|
|
at least skim the new() section (for configuration settings) |
76
|
|
|
|
|
|
|
and parse() section (for an explanation of the dictionary). |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head1 SYNTAX |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
One of the difficulties in employing a new template parser is |
81
|
|
|
|
|
|
|
picking up the apropriate syntax. Text::BasicTemplate does |
82
|
|
|
|
|
|
|
not spare you that, but it does adhere fairly closely to |
83
|
|
|
|
|
|
|
the syntax of perl itself with respect to operators, |
84
|
|
|
|
|
|
|
conditional operations, template subroutine calls, etc. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Anything to which Text::BasicTemplate should pay attention in |
87
|
|
|
|
|
|
|
a template is enclosed in percentage signs (%) -- any such |
88
|
|
|
|
|
|
|
segments will be interpreted as identifiers, operations, |
89
|
|
|
|
|
|
|
conditionals, or apropriate combinations thereof. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
The simplest of these are variable substitutions; if parse() |
92
|
|
|
|
|
|
|
was passed a dictionary containing the pair (foo => "bar"), any instances |
93
|
|
|
|
|
|
|
of %foo% in the template will be evaluated as "bar." Other |
94
|
|
|
|
|
|
|
variable substitutions are available for lists and hashes, |
95
|
|
|
|
|
|
|
passed by reference in the parse() dictionary, as in |
96
|
|
|
|
|
|
|
(bar => \@r, snaf => \%h). In such a case %bar% will be |
97
|
|
|
|
|
|
|
evaluated to the contents of @r, and %snaf% to the contents |
98
|
|
|
|
|
|
|
of %h. Both will be formatted according to the configured |
99
|
|
|
|
|
|
|
delimiters (see B). Subroutine |
100
|
|
|
|
|
|
|
references may also be included in the dictionary; in their |
101
|
|
|
|
|
|
|
simple form, given ( subref => \&myfunction ), %subref% in |
102
|
|
|
|
|
|
|
the template will be evaluated to whatever is returned from |
103
|
|
|
|
|
|
|
&myfunction(). For more detail and features in subroutine |
104
|
|
|
|
|
|
|
handling, see B. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
In v0.9.7, BasicTemplate introduced simple conditional |
107
|
|
|
|
|
|
|
evaluation, providing one-level equality/inequality |
108
|
|
|
|
|
|
|
comparisons. In 2.0, after a total rewrite, the conditional |
109
|
|
|
|
|
|
|
evaluation was replaced with a lexically parsed scoping |
110
|
|
|
|
|
|
|
evaluation, providing arbitrarily deep nesting, most major |
111
|
|
|
|
|
|
|
unary and binary perl comparison operators, arbitrary |
112
|
|
|
|
|
|
|
combination of operations, nonconditional evaluation, etc. |
113
|
|
|
|
|
|
|
For the full explanation, read on: |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head2 SCOPING |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
Scoped evaluation is available to arbitrary depths, following |
118
|
|
|
|
|
|
|
the usual if/elsif/else pattern. B conditions are terminated |
119
|
|
|
|
|
|
|
by a B. By example: |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# single if |
122
|
|
|
|
|
|
|
%if % |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
%fi% |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# if-else |
127
|
|
|
|
|
|
|
%if % |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
%else% |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
%fi% |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
# if-elsif |
134
|
|
|
|
|
|
|
%if % |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
%elsif % |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
%fi% |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
# if-else-elsif |
141
|
|
|
|
|
|
|
%if % |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
%elsif % |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
%else% |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
%fi% |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
A B above is some amount of further template contents, including |
150
|
|
|
|
|
|
|
none (%if %%fi% is perfectly valid, albeit not generally |
151
|
|
|
|
|
|
|
useful). A block may contain further conditions. Dictionary variables |
152
|
|
|
|
|
|
|
used in a conditional will only be evaluated if they come into scope -- |
153
|
|
|
|
|
|
|
for example, an elsif will not be evaluated unless its preceeding if or |
154
|
|
|
|
|
|
|
elsif evaluted false -- the principal consequence of this is that |
155
|
|
|
|
|
|
|
subroutines referenced in a conditional will be called only if they |
156
|
|
|
|
|
|
|
come into scope per the above. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=head2 IDENTIFIERS |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
Numeric literals may be given without alteration, e.g. %123%. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
String literals should be given in double quotes, e.g. %"hello"%, |
163
|
|
|
|
|
|
|
or in single quotes, e.g. %'goodbye'%. Either sort may contain |
164
|
|
|
|
|
|
|
quotes of the other sort. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
Scalar, list and hash variables should be given by name, |
167
|
|
|
|
|
|
|
e.g. %foo%. |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
%% gives a literal % sign and is considered normal text. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Environment variables may be used as %$PATH%. |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
Subroutine references should generally be referenced as %&foo%, |
174
|
|
|
|
|
|
|
or %&foo(arg1,arg2,...)% as apropriate. %foo% may be used for |
175
|
|
|
|
|
|
|
subroutines that return a scalar and will not require further |
176
|
|
|
|
|
|
|
parsing of their output -- see B. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head2 EVALUATION |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Statements, conditional or otherwise, may be used outside of if/else |
182
|
|
|
|
|
|
|
contexts, and will have the results of the evaluation inserted at |
183
|
|
|
|
|
|
|
the point in which they occurred in the template. If used in an |
184
|
|
|
|
|
|
|
if/else statement, they will be evaluated, but the apropriate block |
185
|
|
|
|
|
|
|
will be output instead (pretty much the usual, IOW). |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
I |
188
|
|
|
|
|
|
|
%1 || 2% will evaluate both 1 and 2 (and return 2). Evaluation order |
189
|
|
|
|
|
|
|
is not guaranteed. For all matters requiring precedence, parentheses |
190
|
|
|
|
|
|
|
should be employed (e.g. %1 && (0 || 3)%). |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Most of the perl unary and binary operators are supported; the trinary |
193
|
|
|
|
|
|
|
conditional is not. Operators presently provided are as follows: |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
B -- identical to their perl equivalents. Return |
196
|
|
|
|
|
|
|
1 or false. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
B<=~ !~> -- also equivalent to the perl versions, but must be enabled |
199
|
|
|
|
|
|
|
by setting B true (see new()), as a malformed |
200
|
|
|
|
|
|
|
pattern may kill the script -- so do not use them if you think you might |
201
|
|
|
|
|
|
|
be evaluating untrusted untrusted templates. The form for these is |
202
|
|
|
|
|
|
|
=~ pattern, not =~ /pattern/. |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
B<== != E E= E E= E=E> -- perl equivalent |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
B<&& and || or> -- the two ands and the two ors are considered |
207
|
|
|
|
|
|
|
equivalent, as there is no operator precedence in BasicTemplate. |
208
|
|
|
|
|
|
|
&& and and return the value of the last operand. |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
B<. x> -- perl equivalent; operand for x must be numeric. |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
B<+ - * / **> -- perl equivalent, divide-by-zero will be checked. |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
B -- equivalent to int(x/y) and x % y respectively. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
B<^ & | EE EE> -- perl equivalent |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
B -- perl equivalent. |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Examples: |
221
|
|
|
|
|
|
|
%foo + bar% -- evaluates to result of foo+bar, where foo and bar |
222
|
|
|
|
|
|
|
are variables given in the dictionary. |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
%if foo && (bar || snaf)% |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
%fi% -- evaluates foo, bar and snaf, outputs the block if the |
227
|
|
|
|
|
|
|
foo and one or more of bar and snaf were true. |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
%"your name: " . &yourname% -- outputs the string "your name: ", |
230
|
|
|
|
|
|
|
followed by whatever was returned by the subroutine referenced |
231
|
|
|
|
|
|
|
by the dictionary entry for yourname. |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
%if $MAIL =~ Maildir% |
234
|
|
|
|
|
|
|
Bernstein would be proud. |
235
|
|
|
|
|
|
|
%else% |
236
|
|
|
|
|
|
|
Eric Allman wants you for a sunbeam. |
237
|
|
|
|
|
|
|
%fi% -- evaluates according to whether the environment variable |
238
|
|
|
|
|
|
|
$MAIL contains the pattern 'Maildir.' |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Note that blocks inside conditional statements begin immediately |
241
|
|
|
|
|
|
|
following the closing %, so in the above examples, the newline |
242
|
|
|
|
|
|
|
and spaces would be considered part of the block and output if |
243
|
|
|
|
|
|
|
the condition evaluated true. This is acceptable for most |
244
|
|
|
|
|
|
|
whitespace-independent usages, but you should not include whitespace |
245
|
|
|
|
|
|
|
in a conditional block if you do not want it in the output. |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=head2 LIST/HASH FORMATTING |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
List references will be parsed and delimited according to |
250
|
|
|
|
|
|
|
$obj->{list_delimiter}->{listname} if supplied, and |
251
|
|
|
|
|
|
|
$obj->{list_delimiter}->{__default} if not (the latter is |
252
|
|
|
|
|
|
|
set with the default_list_delimiter argument to new()). The default |
253
|
|
|
|
|
|
|
is ", ". |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
Hash references will be delimited using $obj->{hash_delimiter}->{hashname} |
256
|
|
|
|
|
|
|
between pairs, and $obj->{hash_specifier}->{hashname} between key and |
257
|
|
|
|
|
|
|
value. As above, __default will be used if a delimiter has not |
258
|
|
|
|
|
|
|
been specified for the specific variable. The defaults are ", " and |
259
|
|
|
|
|
|
|
"=" respectively. |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
Example: |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
$bt = Text::BasicTemplate->new(default_list_delimiter => ' and'); |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
$ss = "path: %path%" . "\n" . "env: %env%"; |
266
|
|
|
|
|
|
|
$bt->{hash_specifier}->{env} = " is "; |
267
|
|
|
|
|
|
|
$bt->{hash_delimiter}->{env} = ", "; |
268
|
|
|
|
|
|
|
print $bt->parse(\$ss, { path => [ split(/:/,$ENV{PATH}) ], |
269
|
|
|
|
|
|
|
env => \%ENV }); |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
Output from the above would be of the form: |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
/bin and /usr/bin and /usr/local/bin |
274
|
|
|
|
|
|
|
SHELL is bash, VISUAL is emacs, RSYNC_RSH is ssh |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=head2 SUBROUTINE SUBSTITUTIONS |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
Subroutine references are something of a special-case in Text::BasicTemplate. |
279
|
|
|
|
|
|
|
In a simple form, they can be used thusly: |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub heart_of_oak { |
282
|
|
|
|
|
|
|
return "me lads, 'tis to glory we steer"; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
$bt = Text::BasicTemplate->new(); |
285
|
|
|
|
|
|
|
$ss = "come cheer up %&rest_of_verse%"; |
286
|
|
|
|
|
|
|
%ov = ( rest_of_verse => \&heart_of_oak ); |
287
|
|
|
|
|
|
|
print $bt->parse(\$ss,\%ov); |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
This would output "come cheer up me lads, 'tis to glory we steer," by calling |
290
|
|
|
|
|
|
|
&heart_of_oak() and inserting its return value into the template. |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
You can pass literals and variables defined in the template to a subroutine, as follows: |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub heart_of_oak { |
295
|
|
|
|
|
|
|
my @lines = ( "come cheer up me lads", |
296
|
|
|
|
|
|
|
"'tis to glory we steer", |
297
|
|
|
|
|
|
|
"to find something new in this wonderful year" ); |
298
|
|
|
|
|
|
|
my $which = shift; |
299
|
|
|
|
|
|
|
my $loud = shift || 0; |
300
|
|
|
|
|
|
|
return $loud ? uc $lines[$which] : $lines[$which]; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
$bt = Text::BasicTemplate->new(); |
303
|
|
|
|
|
|
|
$ss = "song: %&song(1,$loud)%, %&song(2,$loud)%, %&song(3,$loud)%"; |
304
|
|
|
|
|
|
|
print $bt->parse(\$ss, { song => \&heart_of_oak, loud => 1 }); |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
This would produce the lines of the song, separated by ", "; as |
307
|
|
|
|
|
|
|
written above (with loud == 1 in the dictionary), it will be |
308
|
|
|
|
|
|
|
shouted (inserted in capitals, as per the call to uc()) -- in |
309
|
|
|
|
|
|
|
the template, the use of $variable in a subroutine call indicates |
310
|
|
|
|
|
|
|
that $variable should be gotten from the dictionary rather than |
311
|
|
|
|
|
|
|
interpreted literally. Use of $ is not the normal BasicTemplate |
312
|
|
|
|
|
|
|
syntax -- %variable% would be more proper, but introduces a nasty |
313
|
|
|
|
|
|
|
parsing mess until the re engine gains balancing abilities |
314
|
|
|
|
|
|
|
(scheduled for perl5.6 as of this writing). |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
The argument $_bt_dict has special meaning, and will be replaced |
317
|
|
|
|
|
|
|
with the hashref being used as the active substitution dictionary, |
318
|
|
|
|
|
|
|
thus giving your routines access to it -- it will be passed in |
319
|
|
|
|
|
|
|
the form of a hashref, which you are free to alter during the call, |
320
|
|
|
|
|
|
|
so long as you keep the effects of your caching options in mind. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
The available formatting of arguments passed to these subroutines |
323
|
|
|
|
|
|
|
is any combination of: |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
word, word, |
326
|
|
|
|
|
|
|
word => word, word |
327
|
|
|
|
|
|
|
word => "word \"word\" 'word'" |
328
|
|
|
|
|
|
|
word => 'word "word"' |
329
|
|
|
|
|
|
|
word => "word\nword", |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
# as in: |
332
|
|
|
|
|
|
|
%&mysubroutine(foo,bar,snaf => 3,str => "foo bar", word => 'k"ib"o', flap => "\"ing\"")% |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
In the first case, each word argument may contain anything but [,=>] |
335
|
|
|
|
|
|
|
(that is, a comma, an = or a >; yes, that is not entirely proper). |
336
|
|
|
|
|
|
|
If you need to use any of those characters, put the arguments in |
337
|
|
|
|
|
|
|
quotes. Parsing with quotations is more accurate, but depends on |
338
|
|
|
|
|
|
|
lookbehind assertions and is accordingly slow (the parse |
339
|
|
|
|
|
|
|
results are cached, so this is mostly an issue in repetitive |
340
|
|
|
|
|
|
|
executions rather than use of many instances in one template). |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
When performing database queries, which may return in increments and |
343
|
|
|
|
|
|
|
have separate beginning and ending operations, you can use three code |
344
|
|
|
|
|
|
|
references in a single list reference, for beginning, middle and end. |
345
|
|
|
|
|
|
|
The first will be called once at the beginning, the second repeatedly |
346
|
|
|
|
|
|
|
until it returns false, and the third once afterward. For example: |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
sub $number_count = 10; |
350
|
|
|
|
|
|
|
sub numbers_start { "Countdown, kinda like BASIC: " } |
351
|
|
|
|
|
|
|
sub numbers_list { $number_count-- } |
352
|
|
|
|
|
|
|
sub numbers_end { "\"blastoff. whee.\"" } |
353
|
|
|
|
|
|
|
my %ov = ( |
354
|
|
|
|
|
|
|
numbers => [ \&numbers_start, \&numbers_list, \&numbers_end ] |
355
|
|
|
|
|
|
|
); |
356
|
|
|
|
|
|
|
$bt = Text::BasicTemplate->new(); |
357
|
|
|
|
|
|
|
$ss = '%numbers%'; |
358
|
|
|
|
|
|
|
print $bt->parse(\$ss,\%ov); |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
This would call &numbers_start and insert the result, then call and |
361
|
|
|
|
|
|
|
insert &numbers_list until it $number_count reached zero, then call |
362
|
|
|
|
|
|
|
&numbers_end once and insert that. This may easily be applied, for |
363
|
|
|
|
|
|
|
example, to an execute, fetch, fetch, fetch, ..., finish sequence in |
364
|
|
|
|
|
|
|
DBI. If you need only part of these three functions (e.g. a routine |
365
|
|
|
|
|
|
|
that does not need a finish function), you can pass any one as an |
366
|
|
|
|
|
|
|
empty code reference (e.g. \ sub { }). |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
The real use of subroutine references becomes apparent when you need |
369
|
|
|
|
|
|
|
the output from a function parsed into a template of its own. As noted |
370
|
|
|
|
|
|
|
above in the song() example, you can pass arguments to a subroutine via |
371
|
|
|
|
|
|
|
the template. This extends to passing hashes, e.g. %&foo(name => value)%, |
372
|
|
|
|
|
|
|
in which (name,value) will be passed to the subroutine referenced as foo |
373
|
|
|
|
|
|
|
in the parse() dictionary. You may also pass an argument (bt_template => filename), |
374
|
|
|
|
|
|
|
in which case the output from the coderef will be assumed to be a hashref; |
375
|
|
|
|
|
|
|
this hashref will then be added to the current parse() dictionary (where |
376
|
|
|
|
|
|
|
duplication occurs, the hashref will take precedence) and used as the |
377
|
|
|
|
|
|
|
dictionary given to a recursive call of parse() on the file specified by |
378
|
|
|
|
|
|
|
bt_template. So... |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
sub start { |
382
|
|
|
|
|
|
|
return "hello, "; |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
my $pcount = 0; |
385
|
|
|
|
|
|
|
sub getname { |
386
|
|
|
|
|
|
|
my @people = ( { firstname => 'John', lastname => 'Doe' }, |
387
|
|
|
|
|
|
|
{ firstname => 'Susan', lastname => 'Smith' } |
388
|
|
|
|
|
|
|
); |
389
|
|
|
|
|
|
|
return $people[$pcount++]; |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
sub end { |
392
|
|
|
|
|
|
|
return "Nice to see you."; |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
# assume that /path/hello-template contains |
395
|
|
|
|
|
|
|
# The Esteemed %firstname% %lastname%, Lord of All You Survey |
396
|
|
|
|
|
|
|
$bt = Text::BasicTemplate->new(); |
397
|
|
|
|
|
|
|
$ss = "Greeting: \"%&greeting(bt_template => /path/hello-template)%\""; |
398
|
|
|
|
|
|
|
print $bt->parse(\$ss, { greeting => [ \&start, \&getname, \&end ] }); |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
In this instance, the return values of &start and &end will be used as-is. |
401
|
|
|
|
|
|
|
&getname will be called until it reaches undef (on the third call); the |
402
|
|
|
|
|
|
|
hashrefs returned will be parsed into two copies of /tmp/hello-template. |
403
|
|
|
|
|
|
|
The final output would therefore be: |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
hello, The Esteemed John Doe, Lord of All You Survey |
406
|
|
|
|
|
|
|
The Esteemed Susan Smith, Lord of All You Survey |
407
|
|
|
|
|
|
|
Nice to see you. |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
This has obvious usefulness in terms of taking database output and |
410
|
|
|
|
|
|
|
making presentable (e.g. HTML) output from it, amongst other uses. |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
=head1 PRAGMA/PREPROCESS FUNCTIONS |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
Some basic pragma functions are provided for use in templates. These |
415
|
|
|
|
|
|
|
follow the same syntactical conventions as subroutine substitutions, |
416
|
|
|
|
|
|
|
but correspond to programs internal to Text::BasicTemplate rather |
417
|
|
|
|
|
|
|
than supplied by calling code. Pragmas should not be used on untrusted |
418
|
|
|
|
|
|
|
templates -- when templates are not trustworthy, they should be disabled |
419
|
|
|
|
|
|
|
by setting $object->{pragma_enable}->{name_of_pragma} to false, or more |
420
|
|
|
|
|
|
|
simply disabling all pragmas by setting $object->{pragma_enable} = {}. |
421
|
|
|
|
|
|
|
If an option pragma_enable is passed to new(), it will be taken as |
422
|
|
|
|
|
|
|
a substitute for the enabled list and not overridden. |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
Individual pragmas may be added or overridden with code of your own by |
425
|
|
|
|
|
|
|
setting $object->{pragma_functions}->{name_of_pragma} to a CODE reference. |
426
|
|
|
|
|
|
|
The referenced routine should expect to be passed a list containing |
427
|
|
|
|
|
|
|
a reference to the Text::BasicTemplate object, a hashref to the active |
428
|
|
|
|
|
|
|
dictionary (which may be {}), followed by any arguments passed in |
429
|
|
|
|
|
|
|
the template. Pragma routines must match ^bt_, or they will not be |
430
|
|
|
|
|
|
|
interpreted as pragmas. |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
Pragmas provided are as follows. Note that they follow, to a reasonable |
433
|
|
|
|
|
|
|
extent, the format given by the Apache 1.3 mod_include specification, with |
434
|
|
|
|
|
|
|
a few additions. Options in [ square brackets ] are optional. |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
=head2 bt_include({ file | virtual }, filename, [ noparse ]) |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
Includes a file in the given location in the template. The first option |
439
|
|
|
|
|
|
|
specifies from where the file should be loaded, equivalent to the Apache |
440
|
|
|
|
|
|
|
mod_include form. B means any regular path and filename. |
441
|
|
|
|
|
|
|
B is interpreted as relative to $object->{include_document_root} |
442
|
|
|
|
|
|
|
or $ENV{DOCUMENT_ROOT} in that order of precedence; if no document root is |
443
|
|
|
|
|
|
|
specified, no include is done. B is a restricted form of the |
444
|
|
|
|
|
|
|
B form, in which files must match \w[\w\-.]{0,254} to be included |
445
|
|
|
|
|
|
|
(this means, generally, that the included files must be in the working |
446
|
|
|
|
|
|
|
directory, unless you chdir() or something). |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
If B is supplied, the included file will be inserted as-is |
449
|
|
|
|
|
|
|
without further adjustment. Otherwise it will be run through parse() |
450
|
|
|
|
|
|
|
as would any normal template. You should use the noparse option when |
451
|
|
|
|
|
|
|
including an untrusted template from a trusted one. |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
bt_include() will only include readable regular files (that is, those |
454
|
|
|
|
|
|
|
passing C<-e>, C<-f> and C<-r>). Note that this is suceptible to race conditions, |
455
|
|
|
|
|
|
|
so it does not confer any security where a race could be exploited by |
456
|
|
|
|
|
|
|
the usual file/symlink swapping. |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
Examples: |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
%&bt_include(file,templates/boxscores.html)% |
461
|
|
|
|
|
|
|
Includes the file, parses according to the active dictionary |
462
|
|
|
|
|
|
|
%&bt_include(file,orders/summary.txt,noparse)% |
463
|
|
|
|
|
|
|
Includes the file but without any parsing on the way |
464
|
|
|
|
|
|
|
%&bt_include(virtual,index.html)% |
465
|
|
|
|
|
|
|
Includes the file index.html from the document_root directory, |
466
|
|
|
|
|
|
|
with parsing. |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
bt_include() is one the user might want to override if template files |
469
|
|
|
|
|
|
|
are stored in a database or other non-file mechanism. |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
=head2 bt_exec({ cmd | cgi }, command, parse) |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
Analogous to the Apache mod_include 'exec' directive. Executes the |
474
|
|
|
|
|
|
|
specified command and inserts its stdout output into the template |
475
|
|
|
|
|
|
|
in place of the directive. If B is specified, this output |
476
|
|
|
|
|
|
|
will be handed to parse() as if it were a template file. |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
If B is given, the command will be read, parsed if selected, |
479
|
|
|
|
|
|
|
and inserted as-is without validation on the command. If B |
480
|
|
|
|
|
|
|
is given, the output will be skipped up and including the first |
481
|
|
|
|
|
|
|
blank line to remove HTTP headers. |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
bt_exec() is not secure and should not be used except with trusted |
484
|
|
|
|
|
|
|
templates and on trusted binaries. For this reason it is disabled |
485
|
|
|
|
|
|
|
by default and must be manually enabled by setting $object->{pragma_enable}->{bt_exec} true either when calling new() or subsequently. |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=head1 COMPATIBILITY |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
Text::BasicTemplate 2.0 is a major rewrite from v0.9.8 and previous |
491
|
|
|
|
|
|
|
versions. Compatibility has been preserved to a degree, enough that |
492
|
|
|
|
|
|
|
with compatibility mode enabled, there should be no difference in |
493
|
|
|
|
|
|
|
either output or calling conventions. |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
I
|
496
|
|
|
|
|
|
|
will be disabled in some future version, possibly without notice.> |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
Backwards compatibility is a concern in two respects, that of template |
499
|
|
|
|
|
|
|
format and calling conventions. |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
=head2 TEMPLATE FORMAT |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
The BasicTemplate 2.0 template format is only minimally compatible |
504
|
|
|
|
|
|
|
with the older form. If your templates include conditionals or |
505
|
|
|
|
|
|
|
simple_ssi HTML-style include directives, you will need to update |
506
|
|
|
|
|
|
|
your templates and/or use compatibility mode. A template that uses |
507
|
|
|
|
|
|
|
only variable substitution (e.g. "Hello %name%") will not need |
508
|
|
|
|
|
|
|
compatibility mode. |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
Compatibility mode is enabled by passing 'compatibility_mode_0x => 1' |
511
|
|
|
|
|
|
|
to new() (see the POD for new()). Note that compatibility mode is |
512
|
|
|
|
|
|
|
slower than standard mode, because of conversion overhead. |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
The convert_template_0x_2x() function can convert a 0.x template to |
515
|
|
|
|
|
|
|
a 2.0 template -- see the POD for that function for the details. |
516
|
|
|
|
|
|
|
This function can easily be placed in a script to convert your |
517
|
|
|
|
|
|
|
templates in place, and it is likely that such a script will be |
518
|
|
|
|
|
|
|
provided with Text::BasicTemplate releases. |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=head2 CALLING CONVENTIONS |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
In general, there should be no necessary change between 0.x calls |
523
|
|
|
|
|
|
|
and 2.x calls. All the old calls have been replaced with stubs |
524
|
|
|
|
|
|
|
which call the new versions. These are roughly as follows: |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
push(), parse_push() -- replaced by parse() |
527
|
|
|
|
|
|
|
print(), parse_print() -- replaced by print parse() |
528
|
|
|
|
|
|
|
list_cache() -- replaced by list_lexicon_cache() |
529
|
|
|
|
|
|
|
purge_cache() -- replaced by purge_*_cache() |
530
|
|
|
|
|
|
|
uncache() -- replaced by purge_lexicon_cache(), purge_file_cache() |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
=cut |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
my $errstr; |
536
|
|
|
|
|
|
|
my $debug = 0; |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
my %reserved_words = ( |
539
|
|
|
|
|
|
|
'if' => 1, '%if%' => 1, |
540
|
|
|
|
|
|
|
'else' => 1, '%else%' => 1, |
541
|
|
|
|
|
|
|
'elsif' => 1, '%elsif%' => 1, |
542
|
|
|
|
|
|
|
'fi' => 1, '%fi%' => 1, |
543
|
|
|
|
|
|
|
); |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
my %lexeme_types = ( |
546
|
|
|
|
|
|
|
0 => 'plain', |
547
|
|
|
|
|
|
|
1 => 'condi', |
548
|
|
|
|
|
|
|
2 => 'ident', |
549
|
|
|
|
|
|
|
3 => 'liter', |
550
|
|
|
|
|
|
|
4 => 'uoper', |
551
|
|
|
|
|
|
|
5 => 'boper', |
552
|
|
|
|
|
|
|
6 => 'coper', |
553
|
|
|
|
|
|
|
); |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
=head1 USEFUL FUNCTIONS |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
=item B |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
Make a Text::BasicTemplate object. Syntax is as follows: |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
$bt = Text::BasicTemplate->new( |
562
|
|
|
|
|
|
|
max_parse_recursion => 32, |
563
|
|
|
|
|
|
|
use_file_cache => 0, |
564
|
|
|
|
|
|
|
use_lexicon_cache => 1, |
565
|
|
|
|
|
|
|
use_scalarref_lexicon_cache => 0, |
566
|
|
|
|
|
|
|
use_full_cond_cache => 1, |
567
|
|
|
|
|
|
|
use_cond2rpn_cache => 1, |
568
|
|
|
|
|
|
|
use_dynroutine_arg_cache => 1, |
569
|
|
|
|
|
|
|
use_flock => 1, |
570
|
|
|
|
|
|
|
default_list_delimiter => ", ", |
571
|
|
|
|
|
|
|
default_hash_delimiter => ", ", |
572
|
|
|
|
|
|
|
default_hash_specifier => "=", |
573
|
|
|
|
|
|
|
default_undef_identifier => "", |
574
|
|
|
|
|
|
|
compatibility_mode_0x => 1, |
575
|
|
|
|
|
|
|
eval_subroutine_refs => 1, |
576
|
|
|
|
|
|
|
strip_html_comments => 0, |
577
|
|
|
|
|
|
|
strip_c_comments => 0, |
578
|
|
|
|
|
|
|
strip_cpp_comments => 0, |
579
|
|
|
|
|
|
|
strip_perl_comments => 0, |
580
|
|
|
|
|
|
|
condense_whitespace => 0, |
581
|
|
|
|
|
|
|
simple_ssi => 1 |
582
|
|
|
|
|
|
|
); |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
All explicit arguments to new() are optional; the values shown above are |
585
|
|
|
|
|
|
|
the defaults. |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
Configuration arguments given to new() have the following meanings: |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
=over 4 |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
=item B: |
592
|
|
|
|
|
|
|
When performing a recursive parse() on a template, as |
593
|
|
|
|
|
|
|
in the case of a subroutine substitution with a bt_template parameter (see |
594
|
|
|
|
|
|
|
the B section), parsing will stop if recursion goes more than this |
595
|
|
|
|
|
|
|
depth -- the typical cause would be a template A that included a subroutine |
596
|
|
|
|
|
|
|
reference that used a template B, which used a C, which used A again. |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
=item B: |
599
|
|
|
|
|
|
|
Templates specified to parse() by filename are read into |
600
|
|
|
|
|
|
|
memory before being given to the lexer. If this option is set, the contents |
601
|
|
|
|
|
|
|
of the file will be cached in a hash after being read. This is largely |
602
|
|
|
|
|
|
|
unnecessary if (as per default) lexicon caching is enabled. Do not turn this |
603
|
|
|
|
|
|
|
on unless you have disabled lexicon caching, or are doing something dubious |
604
|
|
|
|
|
|
|
to the cache yourself. |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
=item B: |
607
|
|
|
|
|
|
|
If true, the lexicon generated from an input template |
608
|
|
|
|
|
|
|
will be cached prior to parsing. This is the normal form of caching, and |
609
|
|
|
|
|
|
|
enables subsequent calls to parse() to skip over the lexical parsing of |
610
|
|
|
|
|
|
|
templates, generally the most expensive part of the process. |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
=item B: |
613
|
|
|
|
|
|
|
If true, the above lexicon caching applies |
614
|
|
|
|
|
|
|
to templates given to parse() via scalar reference, as well as by filename. |
615
|
|
|
|
|
|
|
This is generally fine, but if you pass the contents of multiple templates |
616
|
|
|
|
|
|
|
by a reference to the same scalar, you may get cache mismatching. |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
=item B: |
619
|
|
|
|
|
|
|
Controls caching of the results of evaluation of conditionals. Has three |
620
|
|
|
|
|
|
|
settings, off (0), normal (1), and persistent (2). If set off, every |
621
|
|
|
|
|
|
|
conditional will be reevaluated every time it is executed (this is not |
622
|
|
|
|
|
|
|
very expensive unless use_cond2rpn_cache is set off also; see documentation |
623
|
|
|
|
|
|
|
for that option). This is necessary only if you intend to change the |
624
|
|
|
|
|
|
|
values in the dictionary during a parse(), as in the case of a |
625
|
|
|
|
|
|
|
template-referenced subroutine calling a method that changes the dictionary. |
626
|
|
|
|
|
|
|
This cache adds some speed; the operation normally requires O(n) where n is |
627
|
|
|
|
|
|
|
the number of operators in the conditional, plus the cond2rpn conversion |
628
|
|
|
|
|
|
|
overhead, if applicable. When use_full_cond_cache is set to 1 (on, as per |
629
|
|
|
|
|
|
|
normal), conditionals are cached only for the span of one parse() call; if |
630
|
|
|
|
|
|
|
a template-referenced routine changes the dictionary for a variable already |
631
|
|
|
|
|
|
|
used in a conditional, the change will have no effect until the next call |
632
|
|
|
|
|
|
|
to parse(). When set to 2 (persistent), the conditional cache does not |
633
|
|
|
|
|
|
|
expire when parse() completes a single template, and indeed will not expire |
634
|
|
|
|
|
|
|
at all unless you call purge_fullcond_cache() manually. This setting can |
635
|
|
|
|
|
|
|
be useful for fast repeated parsing of the same data into multiple |
636
|
|
|
|
|
|
|
templates, but is not suitable when the dictionary is changing. |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
=item B: |
639
|
|
|
|
|
|
|
Subroutine substitutions in templates may be |
640
|
|
|
|
|
|
|
passed arguments; these arguments are parsed into a suitable list before |
641
|
|
|
|
|
|
|
being handed to the subroutine in question. If this is enabled, the results |
642
|
|
|
|
|
|
|
of that parsing will be cached to speed future use. This does not incur |
643
|
|
|
|
|
|
|
cache mismatches; leave enabled unless you have a good reason not to. |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
=item B: |
646
|
|
|
|
|
|
|
If set true, template files will be flock()ed with a LOCK_SH |
647
|
|
|
|
|
|
|
while being read. Otherwise, they will be read blindly. Win32 afflictees |
648
|
|
|
|
|
|
|
might wish to disable this; in general, leave it alone. Note that files |
649
|
|
|
|
|
|
|
generally will need to be read only once each if either lexicon or file |
650
|
|
|
|
|
|
|
caching is enabled (see above). |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
=item B: |
653
|
|
|
|
|
|
|
When listrefs are substituted into a template, |
654
|
|
|
|
|
|
|
they will be join()ed with the contents of $self->{list_delimiter}->{name} |
655
|
|
|
|
|
|
|
if defined, or with this default value otherwise. If you wish your listrefs |
656
|
|
|
|
|
|
|
contatenated with no delimiting, set this to ''. Default is ', '. |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
=item B: |
659
|
|
|
|
|
|
|
As above, but separates key/value pairs in hashref |
660
|
|
|
|
|
|
|
substitution. If %x = (y => z, x => p), this delimiter will be placed |
661
|
|
|
|
|
|
|
between y=z and x=p. Overridden by $self->{hash_delimiter}->{name}. Deault ', '. |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
=item B: |
664
|
|
|
|
|
|
|
As above, separating keys and values in hashref |
665
|
|
|
|
|
|
|
substitution. In the above %x, this delimiter goes between y and z, and |
666
|
|
|
|
|
|
|
between x and p. Overriden by $self->{hash_specifier}->{name}. Default '='. |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
=item B: |
669
|
|
|
|
|
|
|
When a template calls for a substitution key |
670
|
|
|
|
|
|
|
which is undefined in the dictionary, this value will be substituted instead. |
671
|
|
|
|
|
|
|
Default is ''. Something obvious like '**undefined**' might be a good choice |
672
|
|
|
|
|
|
|
for debugging purposes. |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
=item B: |
675
|
|
|
|
|
|
|
This option enables evaluation of subroutine reference |
676
|
|
|
|
|
|
|
substitutions, e.g. %&myroutine()%. Generally a safe option, but you might |
677
|
|
|
|
|
|
|
want to disable it if parsing untrustworthy templates. |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
=item B: |
680
|
|
|
|
|
|
|
Enables compatibility with templates written |
681
|
|
|
|
|
|
|
for Text::BasicTemplate v0.x. See B section. |
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
=item B: |
684
|
|
|
|
|
|
|
If set true, HTML comments (E!-- ... --E) will be |
685
|
|
|
|
|
|
|
removed from the parse results. Note that nested comments are not properly |
686
|
|
|
|
|
|
|
stripped. Default off. |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
=item B: |
689
|
|
|
|
|
|
|
If true, C comments (/* ... */) will be removed from |
690
|
|
|
|
|
|
|
parse results. Default off. |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
=item B: |
693
|
|
|
|
|
|
|
If true, C and C++ comments (/* ... */ and // ...\n) will |
694
|
|
|
|
|
|
|
be removed from parse results. Default off. |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
=item B: |
697
|
|
|
|
|
|
|
If true, perl and similar style comments (# ... \n) will |
698
|
|
|
|
|
|
|
be removed from parse results. Default off. |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
=item B: |
701
|
|
|
|
|
|
|
If true, whitespace in parse results will be condensed to |
702
|
|
|
|
|
|
|
the first byte of each, as would be done by most web browsers. Useful for |
703
|
|
|
|
|
|
|
tightening bandwidth usage on HTML templates without making the input templates |
704
|
|
|
|
|
|
|
themselves unreadable. Default off. |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
=item B: |
707
|
|
|
|
|
|
|
If true, server-parsed HTML directives of the #include persuasion |
708
|
|
|
|
|
|
|
will have the file referenced in their file="" or virtual="" arguments inserted |
709
|
|
|
|
|
|
|
in their place. The form is . This usage is deprecated |
710
|
|
|
|
|
|
|
in favor of the %&bt_include()% function -- see the B section. Default off; |
711
|
|
|
|
|
|
|
this should not be enabled when using untrusted templates. |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
=back |
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
=cut |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
sub new { |
718
|
7
|
|
|
7
|
1
|
1337
|
my $class = shift; |
719
|
7
|
|
|
|
|
24
|
my %params = @_; |
720
|
7
|
|
|
|
|
33
|
my $self = { %params }; |
721
|
7
|
|
|
|
|
27
|
bless $self, $class; |
722
|
|
|
|
|
|
|
|
723
|
7
|
|
50
|
|
|
104
|
$self->{max_parse_recursion} ||= 32; |
724
|
7
|
|
50
|
|
|
53
|
$self->{reserved_words} ||= \%reserved_words; |
725
|
7
|
50
|
|
|
|
240
|
!defined $self->{use_full_cond_cache} and $self->{use_full_cond_cache} = 1; |
726
|
7
|
50
|
|
|
|
670
|
!defined $self->{use_cond2rpn_cache} and $self->{use_cond2rpn_cache}=1; |
727
|
7
|
50
|
|
|
|
46
|
!defined $self->{use_dynroutine_arg_cache} and $self->{use_dynroutine_arg_cache}=1; |
728
|
|
|
|
|
|
|
|
729
|
7
|
50
|
|
|
|
57
|
!defined $self->{taint_enabled} and |
730
|
|
|
|
|
|
|
$self->{taint_enabled} = $self->taint_enabled(); |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
# the file cache should be enabled if the lexicon cache isn't, |
733
|
|
|
|
|
|
|
# but we don't need to cache files if the lexicons themselves are |
734
|
|
|
|
|
|
|
# being cached, since the file cache would never be used anyway. |
735
|
|
|
|
|
|
|
|
736
|
7
|
50
|
|
|
|
38
|
if (!defined $self->{use_file_cache}) { |
737
|
7
|
|
|
|
|
36
|
$self->{use_file_cache} = !$self->{use_lexicon_cache}; |
738
|
|
|
|
|
|
|
} |
739
|
7
|
|
50
|
|
|
56
|
$self->{use_scalarref_lexicon_cache} ||= 0; |
740
|
|
|
|
|
|
|
|
741
|
7
|
50
|
|
|
|
33
|
!defined $self->{use_flock} and $self->{use_flock} = 1; |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
# caches conversions of conditionals into their RPN conversions |
744
|
|
|
|
|
|
|
# for cond_evaluate() |
745
|
7
|
|
|
|
|
17
|
$self->{cond2rpn_cache} = (); |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
# caches the actual returns from cond_evaluate(); |
748
|
7
|
|
|
|
|
25
|
$self->{fullcond_cache} = (); |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
# caches argument lists passed to subrefs (saves reparsing) |
751
|
7
|
|
|
|
|
16
|
$self->{dynroutine_arg_cache} = (); |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
# caches lexicons |
754
|
7
|
|
|
|
|
21
|
$self->{lexicon_cache} = (); |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
# caches files in the absence of lexicon caching |
757
|
7
|
|
|
|
|
21
|
$self->{file_cache} = (); |
758
|
|
|
|
|
|
|
|
759
|
7
|
|
|
|
|
24
|
$self->{enable_pattern_operator} = !$self->{taint_enabled}; |
760
|
|
|
|
|
|
|
|
761
|
7
|
50
|
50
|
|
|
97
|
!defined $self->{list_delimiter}->{__default} and |
762
|
|
|
|
|
|
|
$self->{list_delimiter}->{__default} = $self->{default_list_delimiter} || ', '; |
763
|
7
|
50
|
50
|
|
|
86
|
!defined $self->{hash_delimiter}->{__default} and |
764
|
|
|
|
|
|
|
$self->{hash_delimiter}->{__default} = $self->{default_hash_delimiter} || ', '; |
765
|
7
|
50
|
50
|
|
|
231
|
!defined $self->{hash_specifier}->{__default} and |
766
|
|
|
|
|
|
|
$self->{hash_specifier}->{__default} = $self->{default_hash_specifier} || '='; |
767
|
|
|
|
|
|
|
|
768
|
7
|
|
|
|
|
22
|
$self->{default_undef_identifier} = ''; |
769
|
7
|
|
|
|
|
19
|
$self->{disabled_pragma_identifier} = '[pragma not enabled]'; |
770
|
7
|
|
|
|
|
27
|
$self->{disabled_subref_identifier} = '[subroutine not enabled]'; |
771
|
7
|
|
|
|
|
14
|
$self->{tainted_content_identififer} = '[tainted template contents]'; |
772
|
|
|
|
|
|
|
|
773
|
7
|
50
|
|
|
|
107
|
$self->{pragma_enable} = {} unless ref $self->{pragma_enable} eq 'HASH'; |
774
|
7
|
50
|
|
|
|
35
|
$self->{pragma_functions} = {} unless ref $self->{pragma_functions} eq 'HASH'; |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
# v0.x backwards-compatibility settings |
777
|
7
|
50
|
|
|
|
32
|
!defined $self->{compatibility_mode_0x} |
778
|
|
|
|
|
|
|
and $self->{compatibility_mode_0x} = 1; |
779
|
|
|
|
|
|
|
|
780
|
7
|
50
|
|
|
|
47
|
if ($self->{compatibility_mode_0x}) { |
781
|
7
|
|
|
|
|
14
|
$self->{taint_enabled} = 0; |
782
|
|
|
|
|
|
|
|
783
|
7
|
100
|
|
|
|
32
|
!defined $self->{simple_ssi} and $self->{simple_ssi} = 1; |
784
|
7
|
50
|
|
|
|
29
|
if ($self->{simple_ssi}) { |
785
|
7
|
|
|
|
|
47
|
$self->{pragma_enable}->{bt_include} = 1; |
786
|
|
|
|
|
|
|
} |
787
|
|
|
|
|
|
|
} |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
|
790
|
7
|
|
50
|
|
|
53
|
$self->{bt_include_allow_tainted} ||= 0; |
791
|
7
|
50
|
|
|
|
27
|
if (!defined $self->{pragma_enable}->{bt_include}) { |
792
|
0
|
0
|
|
|
|
0
|
if (!$self->{taint_enabled}) { |
793
|
|
|
|
|
|
|
# if taint checking is enabled, we can't safely |
794
|
|
|
|
|
|
|
# do include. |
795
|
0
|
|
|
|
|
0
|
$self->{pragma_enable}->{bt_include} = 1; |
796
|
|
|
|
|
|
|
} |
797
|
|
|
|
|
|
|
} |
798
|
7
|
|
|
|
|
33
|
$self->{pragma_functions}->{bt_include} = \&bt_include; |
799
|
7
|
|
|
|
|
39
|
$self->{pragma_functions}->{bt_exec} = \&bt_exec; |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
|
802
|
7
|
|
|
|
|
26
|
$self->{eval_subroutine_refs} = 1; |
803
|
7
|
|
|
|
|
21
|
for ('strip_html_comments','strip_c_comments','strip_cpp_comments', |
804
|
|
|
|
|
|
|
'strip_perl_comments','condense_whitespace','simple_ssi') { |
805
|
42
|
|
100
|
|
|
195
|
$self->{$_} ||= 0; |
806
|
|
|
|
|
|
|
} |
807
|
7
|
|
|
|
|
33
|
$self; |
808
|
|
|
|
|
|
|
} |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
=item B |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
Given a source template in SOURCE_TEMPLATE, parses that template according |
813
|
|
|
|
|
|
|
to the key/value hash referenced by $ovr, then returns the result. |
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
If SOURCE_TEMPLATE is given as a scalar, it will be interpreted as a filename, |
816
|
|
|
|
|
|
|
and the contents of that file will be read, parsed, and returned. If given as |
817
|
|
|
|
|
|
|
a scalar reference, it will be interpreted as a reference to a buffer |
818
|
|
|
|
|
|
|
containing the template (the referenced template will not be modified, and |
819
|
|
|
|
|
|
|
copies of the relevant parts will be used to build the lexicon). If |
820
|
|
|
|
|
|
|
SOURCE_TEMPLATE contains an array reference, that array will be used instead |
821
|
|
|
|
|
|
|
of generating a new lexicon. |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
If use_file_template_cache is true and the source template is loaded from a |
824
|
|
|
|
|
|
|
file, or if use_scalarref_lexicon_cache is true and the source template is |
825
|
|
|
|
|
|
|
given in a scalar reference, the lexicon will be cached to accelerate future |
826
|
|
|
|
|
|
|
parsing of the template. If the contents of either the file or the |
827
|
|
|
|
|
|
|
referenced buffer changes during the lifespan of the Text::BasicTemplate |
828
|
|
|
|
|
|
|
object, the code will not notice -- if you need to change the templates in |
829
|
|
|
|
|
|
|
this fashion, use B to delete the cached lexicon. Lexicon |
830
|
|
|
|
|
|
|
references are not cached, since the code assumes if you make your own |
831
|
|
|
|
|
|
|
templates you are capable of caching them, too. |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
For templates stored in and loaded from files, note that they will be |
834
|
|
|
|
|
|
|
read and parsed in core, so you probably should not try to parse templates |
835
|
|
|
|
|
|
|
that would occupy a significant amount of your available memory. For |
836
|
|
|
|
|
|
|
large seldom-used templates, also consider disabling lexicon caching or |
837
|
|
|
|
|
|
|
calling B afterwards. |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
B is a euphemism for some arbitrary combination of lists, scalar paris, |
840
|
|
|
|
|
|
|
hashrefs and listrefs. These should cumulatively amount to the substitution |
841
|
|
|
|
|
|
|
dictionary -- the simple form is { x => 'y' }, in which all %x% in the |
842
|
|
|
|
|
|
|
template will be replaced with y. (x,y) will work also (and by extension, |
843
|
|
|
|
|
|
|
you may pass lists of these, or raw hashes). The dictionary is parsed |
844
|
|
|
|
|
|
|
once, start-to-finish, so in the event of duplicated entries, the last |
845
|
|
|
|
|
|
|
entry of a given name will be the only one retained. |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
Note on backwards-compatibility: in v0.x, it was possible to pass scalars |
848
|
|
|
|
|
|
|
of the form "x=y". This is deprecated, and is only available if |
849
|
|
|
|
|
|
|
B is set true. Further, as references are now legal |
850
|
|
|
|
|
|
|
fodder for substitutions, ("x",\%y) means that %x% will parse to the |
851
|
|
|
|
|
|
|
contents of %y -- if %y contains part of your substitution dictionary, |
852
|
|
|
|
|
|
|
then the above will present an error in any case, and ("x","y",\%y) is likely |
853
|
|
|
|
|
|
|
what you intended. |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
=cut |
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
sub parse { |
858
|
145
|
|
|
145
|
1
|
263700
|
my $self = shift; |
859
|
145
|
|
50
|
|
|
446
|
my $isrc = shift || return undef; |
860
|
145
|
|
|
|
|
342
|
my @dict = (@_); |
861
|
145
|
|
|
|
|
258
|
my $ovr = {}; |
862
|
145
|
|
|
|
|
200
|
my $L; |
863
|
|
|
|
|
|
|
my $ss; |
864
|
0
|
|
|
|
|
0
|
my ($d,$e,$src,$tsrc); ## |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
|
867
|
145
|
|
|
|
|
415
|
while ($d = shift @dict) { |
868
|
732
|
100
|
|
|
|
2240
|
if (ref $d eq 'HASH') { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
869
|
145
|
|
|
|
|
190
|
unshift @dict, map { ($_,$d->{$_}) } keys %{$d}; |
|
580
|
|
|
|
|
1834
|
|
|
145
|
|
|
|
|
577
|
|
870
|
|
|
|
|
|
|
} elsif (ref $d eq 'ARRAY') { |
871
|
0
|
|
|
|
|
0
|
unshift @dict,@{$d}; |
|
0
|
|
|
|
|
0
|
|
872
|
|
|
|
|
|
|
} elsif (!ref $d) { |
873
|
587
|
100
|
66
|
|
|
2844
|
if ($self->{compatibility_mode_0x} and $d =~ /^([\w\.\-]+)=(.*)/s) { |
874
|
2
|
|
|
|
|
10
|
$ovr->{$1} = $2; |
875
|
2
|
|
|
|
|
5
|
next; |
876
|
|
|
|
|
|
|
} |
877
|
585
|
50
|
|
|
|
926
|
if (@dict) { |
878
|
585
|
|
|
|
|
773
|
$e = shift @dict; |
879
|
585
|
|
|
|
|
2864
|
$ovr->{$d} = $e; |
880
|
|
|
|
|
|
|
} else { |
881
|
0
|
|
|
|
|
0
|
print STDERR "Text::BasicTemplate::parse($isrc): Stack underflow while flattening dictionary; odd number of elements, last was '$d'"; |
882
|
|
|
|
|
|
|
} |
883
|
|
|
|
|
|
|
} |
884
|
|
|
|
|
|
|
} |
885
|
145
|
|
100
|
|
|
1098
|
$ovr->{_bt_recurse_count} ||= 0; |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
# horrible hack |
888
|
145
|
50
|
|
|
|
334
|
if ($self->{compatibility_mode_0x}) { |
889
|
145
|
|
|
|
|
282
|
$self->{compat_0x_ovr} = $ovr; |
890
|
|
|
|
|
|
|
} |
891
|
|
|
|
|
|
|
|
892
|
145
|
50
|
33
|
|
|
715
|
return '[Text::BasicTemplate::parse() recursion limit exceeded]' |
893
|
|
|
|
|
|
|
if $self->{max_parse_recursion} and |
894
|
|
|
|
|
|
|
$ovr->{_bt_recurse_count} > $self->{max_parse_recursion}; |
895
|
|
|
|
|
|
|
# print STDERR "ovr = {".join(',',map { "$_=$ovr->{$_}" } keys %{$ovr})."}"; |
896
|
145
|
50
|
|
|
|
21304
|
if (ref $isrc eq 'ARRAY') { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
897
|
0
|
|
|
|
|
0
|
$L = $isrc; |
898
|
|
|
|
|
|
|
} elsif (ref $isrc eq 'SCALAR') { |
899
|
97
|
50
|
33
|
|
|
326
|
if ($self->{use_scalarref_lexicon_cache} and |
900
|
|
|
|
|
|
|
defined $self->{lexicon_cache}{$isrc}) { |
901
|
0
|
0
|
|
|
|
0
|
$debug && print STDERR "]using lexicon cache for $isrc]"; |
902
|
0
|
|
|
|
|
0
|
$L = $self->{lexicon_cache}{$isrc}; |
903
|
|
|
|
|
|
|
} else { |
904
|
97
|
|
|
|
|
321
|
$L = $self->lex($src = $isrc); |
905
|
97
|
50
|
|
|
|
292
|
if ($self->{use_scalarref_lexicon_cache}) { |
906
|
0
|
|
|
|
|
0
|
$self->{lexicon_cache}{$isrc} = $L; |
907
|
|
|
|
|
|
|
} |
908
|
|
|
|
|
|
|
} |
909
|
|
|
|
|
|
|
} elsif (!ref $isrc) { |
910
|
48
|
50
|
33
|
|
|
139
|
if ($self->{use_scalarref_lexicon_cache} and |
911
|
|
|
|
|
|
|
defined $self->{lexicon_cache}{$isrc}) { |
912
|
0
|
|
|
|
|
0
|
$L = $self->{lexicon_cache}{$isrc}; |
913
|
|
|
|
|
|
|
} else { |
914
|
48
|
50
|
|
|
|
186
|
unless ($tsrc = $self->load_from_file($isrc)) { |
915
|
0
|
|
|
|
|
0
|
warn "Text::BasicTemplate::parse($isrc): File not available"; |
916
|
0
|
|
|
|
|
0
|
return undef; |
917
|
|
|
|
|
|
|
} |
918
|
48
|
|
|
|
|
146
|
$L = $self->lex($isrc = $tsrc); |
919
|
48
|
100
|
|
|
|
123
|
if ($self->{use_scalarref_template_cache}) { |
920
|
4
|
|
|
|
|
15
|
$self->{lexicon_cache}{$isrc} = $L; |
921
|
|
|
|
|
|
|
} |
922
|
|
|
|
|
|
|
} |
923
|
|
|
|
|
|
|
} |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
# horrible hack |
926
|
145
|
50
|
|
|
|
369
|
if ($self->{compatibility_mode_0x}) { |
927
|
145
|
|
|
|
|
919
|
delete $self->{compat_0x_ovr}; |
928
|
|
|
|
|
|
|
} |
929
|
|
|
|
|
|
|
|
930
|
145
|
|
|
|
|
209
|
$ss = $self->parse_range($L,0,$#{$L},$ovr); |
|
145
|
|
|
|
|
634
|
|
931
|
145
|
100
|
|
|
|
409
|
$$ss =~ s///mg if $self->{strip_html_comments}; |
932
|
145
|
100
|
66
|
|
|
700
|
$$ss =~ s/\/\*.*?\*\///mg if $self->{strip_c_comments} or |
933
|
|
|
|
|
|
|
$self->{strip_cpp_comments}; |
934
|
145
|
100
|
|
|
|
324
|
$$ss =~ s/\/\/.*?\n/\n/mg if $self->{strip_cpp_comments}; |
935
|
145
|
100
|
|
|
|
360
|
$$ss =~ s/\#.*?\n/\n/mg if $self->{strip_perl_comments}; |
936
|
145
|
100
|
|
|
|
369
|
$$ss =~ s/(\s)\s+/$1/mg if $self->{condense_whitespace}; |
937
|
145
|
50
|
|
|
|
335
|
if ($self->{use_full_cond_cache} == 1) { |
938
|
145
|
|
|
|
|
382
|
$self->purge_fullcond_cache; |
939
|
|
|
|
|
|
|
} |
940
|
145
|
|
|
|
|
3834
|
$$ss; |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
=item parse_range \@lexicon $start $end [ \@ov ] |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
Parses and returns the relevant parts of the specified lexicon |
947
|
|
|
|
|
|
|
over the given range. This has the happy side effect of eliminating |
948
|
|
|
|
|
|
|
the obnoxious passing around of chunks of the lexicon. Instead one |
949
|
|
|
|
|
|
|
need only pass references to a single lexicon and the range over which |
950
|
|
|
|
|
|
|
it should be parsed. This routine does the actual work of parse(), |
951
|
|
|
|
|
|
|
but is really only useful internally. |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
=cut |
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
sub parse_range { |
956
|
174
|
|
|
174
|
1
|
256
|
my $self = shift; |
957
|
174
|
|
|
|
|
186
|
my $L = shift; |
958
|
174
|
|
|
|
|
315
|
my ($start_pos,$end_pos,$ovr) = @_; |
959
|
174
|
|
|
|
|
205
|
my ($lexeme); |
960
|
|
|
|
|
|
|
my $out; |
961
|
0
|
|
|
|
|
0
|
my ($i,$i1,$i2,$s); |
962
|
0
|
|
|
|
|
0
|
my ($cond,$subcond,$rcond); |
963
|
|
|
|
|
|
|
|
964
|
7
|
|
|
7
|
|
101
|
use re 'taint'; |
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
82064
|
|
965
|
174
|
50
|
|
|
|
465
|
ref $ovr eq 'HASH' or $ovr = {}; |
966
|
174
|
50
|
|
|
|
388
|
ref $L eq 'ARRAY' or $L = []; |
967
|
174
|
50
|
33
|
|
|
1035
|
return \ '' unless defined $start_pos and defined $end_pos and $end_pos >= $start_pos; |
|
|
|
33
|
|
|
|
|
968
|
174
|
50
|
33
|
|
|
383
|
return \ '' if ($end_pos<0 || !@{$L}); |
|
174
|
|
|
|
|
585
|
|
969
|
|
|
|
|
|
|
|
970
|
174
|
50
|
|
|
|
393
|
$debug and print STDERR "\nlexicon[$start_pos,$end_pos, #L=$#{$L}]:\n"; |
|
0
|
|
|
|
|
0
|
|
971
|
174
|
50
|
|
|
|
348
|
$debug and |
972
|
|
|
|
|
|
|
print STDERR $self->dump_lexicon($L,$start_pos,$end_pos); |
973
|
|
|
|
|
|
|
|
974
|
174
|
|
66
|
|
|
2994
|
for ($i=$start_pos; $i<=$end_pos && $i<=$#{$L}; $i++) { |
|
366
|
|
|
|
|
2641
|
|
975
|
|
|
|
|
|
|
# print " start loop iteration, \$i=$i, end_pos=$end_pos, #L=$#{$L}\n"; |
976
|
366
|
|
|
|
|
805
|
$lexeme = $L->[$i]; |
977
|
366
|
50
|
|
|
|
865
|
next if ($lexeme->[0] > $self->{max_parse_recursion}); |
978
|
|
|
|
|
|
|
|
979
|
366
|
50
|
|
|
|
1310
|
$debug and print STDERR "[L$lexeme->[0]] $lexeme->[1]"; |
980
|
366
|
100
|
50
|
|
|
984
|
$debug and print STDERR " -- op" if $lexeme->[2]; |
981
|
366
|
100
|
|
|
|
680
|
if (!$lexeme->[2]) { |
982
|
195
|
|
|
|
|
563
|
$out .= $lexeme->[1]; |
983
|
195
|
50
|
|
|
|
365
|
$debug and print STDERR "\n"; |
984
|
195
|
|
|
|
|
745
|
next; |
985
|
|
|
|
|
|
|
} |
986
|
|
|
|
|
|
|
|
987
|
171
|
100
|
|
|
|
494
|
if ($lexeme->[2] == 2) { # is_identifier |
|
|
100
|
|
|
|
|
|
988
|
38
|
50
|
|
|
|
69
|
$debug and print STDERR " [ $lexeme->[1] is identifier, passing $lexeme->[3]/$lexeme->[4] ]"; |
989
|
38
|
|
|
|
|
261
|
$out .= $self->identifier_evaluate($lexeme->[1], |
990
|
|
|
|
|
|
|
$ovr,$lexeme->[3],$lexeme->[4]); |
991
|
38
|
|
|
|
|
144
|
next; |
992
|
|
|
|
|
|
|
} elsif ($lexeme->[2] == 6) { #is_nonconditional_operation |
993
|
84
|
50
|
|
|
|
172
|
$debug and print STDERR "[ nco lexeme: ".join(',',@{$lexeme}),"]"; |
|
0
|
|
|
|
|
0
|
|
994
|
84
|
|
|
|
|
328
|
$out .= $self->cond_evaluate($lexeme->[1],$ovr); |
995
|
|
|
|
|
|
|
} |
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
# For these purposes, if and elsif are roughly equivalent, and |
998
|
|
|
|
|
|
|
# |
999
|
133
|
100
|
100
|
|
|
1243
|
if ($lexeme->[2] == 1 and |
1000
|
|
|
|
|
|
|
$lexeme->[1] =~ /^%(else|(if|elsif)\s+([^%]+))%$/) { |
1001
|
45
|
|
|
|
|
73
|
$cond = $3; |
1002
|
45
|
100
|
|
|
|
100
|
$1 eq 'else' and $cond = 1; |
1003
|
45
|
50
|
|
|
|
72
|
$debug and print STDERR " [if '$cond' from $lexeme->[1]]"; |
1004
|
45
|
100
|
|
|
|
127
|
if ($self->cond_evaluate($cond,$ovr)) { |
1005
|
29
|
50
|
|
|
|
55
|
$debug and print STDERR " [eval true]"; |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
# find end of block, and skip over else/elsifs; if we drop down a level, |
1008
|
|
|
|
|
|
|
# there's likely something wrong with the lexer. |
1009
|
29
|
|
66
|
|
|
48
|
BLOCKLEXEME: for ($i1=$i+1, $i2 = 0; |
|
78
|
|
66
|
|
|
482
|
|
1010
|
|
|
|
|
|
|
$i1<=$#{$L} && |
1011
|
|
|
|
|
|
|
$L->[$i1]->[0] >= $lexeme->[0] && |
1012
|
|
|
|
|
|
|
$i1<=$end_pos; $i1++) { |
1013
|
|
|
|
|
|
|
|
1014
|
|
|
|
|
|
|
# conditional components are a matter for concern iff they're on the |
1015
|
|
|
|
|
|
|
# same level as the if we started from; if we find them from higher |
1016
|
|
|
|
|
|
|
# levels, the recursive call will handle them, and we should not be |
1017
|
|
|
|
|
|
|
# able to get to a lower level by loop conditions immediately above. |
1018
|
77
|
100
|
100
|
|
|
627
|
if ($L->[$i1]->[0] == $L->[$i]->[0] && |
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
1019
|
|
|
|
|
|
|
$L->[$i1]->[1] eq '%fi%') { |
1020
|
17
|
|
|
|
|
24
|
last BLOCKLEXEME; |
1021
|
|
|
|
|
|
|
} elsif ($L->[$i1]->[0] == $L->[$i]->[0] and |
1022
|
|
|
|
|
|
|
$L->[$i1]->[1] eq '%else%' or |
1023
|
|
|
|
|
|
|
substr($L->[$i1]->[1],0,7) eq '%elsif ') { |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
# if we actually find an else or elsif, we can skip to the end of |
1026
|
|
|
|
|
|
|
# the block, since the condition from which we started was true, |
1027
|
|
|
|
|
|
|
# and everything including and after an else/elsif is not going |
1028
|
|
|
|
|
|
|
# to get parsed this trip anyway. |
1029
|
|
|
|
|
|
|
|
1030
|
11
|
|
33
|
|
|
36
|
for ($i2=0; $i1+$i2 <= $end_pos && |
|
41
|
|
66
|
|
|
426
|
|
|
|
|
100
|
|
|
|
|
1031
|
|
|
|
|
|
|
$i1+$i2 <= $#{$L} && |
1032
|
|
|
|
|
|
|
defined $L->[$i1+$i2+1]->[0] && |
1033
|
|
|
|
|
|
|
$L->[$i1+$i2+1]->[0] >= $L->[$i1]->[0]; $i2++) { |
1034
|
|
|
|
|
|
|
# print STDERR "\ni1=$i1 i2=$i2 end_pos=$end_pos #L=$#{$L}", |
1035
|
|
|
|
|
|
|
# " L->[".($i1+$i2+1)."]->[0]=".$L->[$i1+$i2+1]->[0], |
1036
|
|
|
|
|
|
|
# " L->[$i1]->[0]=".$L->[$i1]->[0],"\n"; |
1037
|
|
|
|
|
|
|
} |
1038
|
11
|
|
|
|
|
18
|
last BLOCKLEXEME; |
1039
|
|
|
|
|
|
|
} |
1040
|
|
|
|
|
|
|
} |
1041
|
|
|
|
|
|
|
# $debug and print STDERR " [recurs over ".($i+1)."..".($i1-1).", then skip $i2]"; |
1042
|
|
|
|
|
|
|
# $debug and print STDERR " lexdump passed on: ".$self->dump_lexicon($L,$i+1,$i1-1); |
1043
|
|
|
|
|
|
|
|
1044
|
29
|
|
|
|
|
130
|
$s = $self->parse_range($L,$i+1,$i1-1,$ovr); |
1045
|
29
|
50
|
33
|
|
|
136
|
$s and ref $s eq 'SCALAR' and $out .= $$s; |
1046
|
|
|
|
|
|
|
# $debug and print STDERR " back from recursion, i=$i i1=$i1 i2=$i2"; |
1047
|
|
|
|
|
|
|
# $out .= ${ $self->parse([ $L->[($i+1)..$i1] ]) }; |
1048
|
|
|
|
|
|
|
|
1049
|
|
|
|
|
|
|
# adjust parse position to the end of the if {} block plus the |
1050
|
|
|
|
|
|
|
# distance from that position to the end of the else/elsifs. |
1051
|
29
|
|
|
|
|
37
|
$i = $i1 + $i2; |
1052
|
|
|
|
|
|
|
} else { |
1053
|
16
|
50
|
|
|
|
30
|
$debug and print STDERR " [eval false]"; |
1054
|
|
|
|
|
|
|
# if the condition didn't pass, just advance to the next conditional, unless |
1055
|
|
|
|
|
|
|
# we need to go down a level to find it. If we hit an %elsif%, %fi% or %else%, |
1056
|
|
|
|
|
|
|
# stop seeking and resume parsing from that point. |
1057
|
|
|
|
|
|
|
# $debug and print STDERR " [ranging !if block from $i+1 for level $lexeme->[0]: "; |
1058
|
16
|
|
33
|
|
|
170
|
for ($i1=$i+1; ($L->[$i1]->[0] >= $lexeme->[0]) && |
|
18
|
|
66
|
|
|
277
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
1059
|
|
|
|
|
|
|
($i1<=$end_pos) and |
1060
|
|
|
|
|
|
|
!($L->[$i1]->[0] == $L->[$i]->[0] && |
1061
|
|
|
|
|
|
|
$L->[$i1]->[1] =~ /^%(elsif\s|fi%|else%)/) && |
1062
|
|
|
|
|
|
|
$i1<=$#{$L}; $i1++) {} |
1063
|
|
|
|
|
|
|
# $debug and print STDERR "[$i1 computed]"; |
1064
|
16
|
50
|
33
|
|
|
87
|
$1 and $1 eq 'fi' and $i1++; |
1065
|
16
|
50
|
|
|
|
23
|
$debug and print STDERR "[if-false offset computed, adjusting i from $i to $i1 ($L->[$i1]->[1])]"; |
1066
|
16
|
|
|
|
|
35
|
$i = $i1-1; |
1067
|
|
|
|
|
|
|
} |
1068
|
|
|
|
|
|
|
} |
1069
|
133
|
50
|
|
|
|
493
|
$debug and print STDERR " \n"; |
1070
|
|
|
|
|
|
|
} |
1071
|
|
|
|
|
|
|
# $debug and print STDERR " [parse over $start_pos-$end_pos complete]\n"; |
1072
|
174
|
|
|
|
|
9940
|
\$out; |
1073
|
|
|
|
|
|
|
} |
1074
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
=item cond_evaluate CONDITIONAL [ \%ovr ] |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
Evaluates the specified conditional left-to-right. At present it does |
1078
|
|
|
|
|
|
|
not handle operators also, just boolean/scalar evaluation. |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
=cut |
1081
|
|
|
|
|
|
|
|
1082
|
|
|
|
|
|
|
sub cond_evaluate { |
1083
|
132
|
|
|
132
|
1
|
368
|
my $self = shift; |
1084
|
132
|
|
|
|
|
174
|
my $cond = shift; |
1085
|
132
|
|
50
|
|
|
283
|
my $ovr = shift || []; |
1086
|
132
|
|
|
|
|
197
|
my @cstack = (); |
1087
|
132
|
|
|
|
|
142
|
my ($psc,$subcond,$rcond); |
1088
|
132
|
|
|
|
|
175
|
my $binop_leftover = ''; |
1089
|
132
|
|
|
|
|
136
|
my ($x,$y); |
1090
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
# first recursively evaluate according to parentheses |
1092
|
|
|
|
|
|
|
|
1093
|
132
|
50
|
|
|
|
451
|
$debug and print STDERR " [cond_evaluate(): $cond]"; |
1094
|
132
|
50
|
|
|
|
250
|
defined $cond or return undef; |
1095
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
# have we computed this condition all the way before? |
1097
|
|
|
|
|
|
|
# Generally we can't use this because $ovr may change, but |
1098
|
|
|
|
|
|
|
# if the user wants it, it's fast. |
1099
|
132
|
100
|
66
|
|
|
868
|
$self->{use_full_cond_cache} and $self->{fullcond_cache}{"$ovr\t$cond"} and |
1100
|
|
|
|
|
|
|
return $self->{fullcond_cache}{"$ovr\t$cond"}; |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
## BUG: the cond2rpn cache breaks things. It should live for at most one parse() call, not |
1103
|
|
|
|
|
|
|
## the life of the module. |
1104
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
# Are we supposed to use the conditional -> RPN conversion cache, and if so, |
1106
|
|
|
|
|
|
|
# have we already parsed this one before? |
1107
|
131
|
100
|
66
|
|
|
2844
|
if ($self->{use_cond2rpn_cache} && $self->{cond2rpn_cache}{$cond}) { |
1108
|
22
|
50
|
|
|
|
43
|
$debug and print STDERR "[cache hit on cond '$cond' \@ $self->{cond2rpn_cache}{$cond}]"; |
1109
|
|
|
|
|
|
|
|
1110
|
22
|
|
|
|
|
28
|
@cstack = map { [ $_->[0], $_->[1] ] } @{ $self->{cond2rpn_cache}{$cond} }; |
|
32
|
|
|
|
|
148
|
|
|
22
|
|
|
|
|
63
|
|
1111
|
|
|
|
|
|
|
# for $x (@{ $self->{cond2rpn_cache}{$cond} }) { |
1112
|
|
|
|
|
|
|
# push @cstack, [ $_->[0], $_->[1] ]; |
1113
|
|
|
|
|
|
|
# } |
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
# @cstack = @{ $self->{cond2rpn_cache}{$cond} }; |
1117
|
|
|
|
|
|
|
} else { |
1118
|
109
|
50
|
|
|
|
475
|
$debug and print STDERR "[cache miss on cond '$cond']"; |
1119
|
109
|
|
|
|
|
564
|
while ($cond =~ /(^| |\()\(([^\)]+)\)/) { |
1120
|
3
|
|
|
|
|
9
|
($psc,$subcond) = ($1,$2); |
1121
|
3
|
|
|
|
|
18
|
$rcond = $self->cond_evaluate($subcond,$ovr); |
1122
|
3
|
50
|
|
|
|
8
|
$debug and print STDERR " [eval $subcond-> $rcond in $cond]"; |
1123
|
|
|
|
|
|
|
# $cond =~ s/($&)/$rcond/g; |
1124
|
|
|
|
|
|
|
# fix in 2.005: Shouldn't have permitted active metachars here: |
1125
|
3
|
|
|
|
|
66
|
$cond =~ s/\(\Q$subcond\E\)/$rcond/g; |
1126
|
3
|
50
|
|
|
|
11
|
$debug and print STDERR " [reduced to $cond]"; |
1127
|
|
|
|
|
|
|
} |
1128
|
109
|
50
|
|
|
|
191
|
$debug and print STDERR " [simplified cond: $cond]"; |
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
# stdvar, !func, &cgivar, $envvar, 42 |
1131
|
|
|
|
|
|
|
# $cond =~ s/(^| )(\w+)\(/$1&$2/g; |
1132
|
109
|
|
|
|
|
1220
|
while ($cond =~ m/(defined |\!| not )?\s*([\$]?([A-Za-z_]\w*|\"[^\"]*\"|\d+|\&\w+\([^)]*\))) |
1133
|
|
|
|
|
|
|
\s*(&&|\|\|| (and|or) | # logical binary ops |
1134
|
|
|
|
|
|
|
\&|\||\^|\<\<|\>\>| # bitwise binary ops |
1135
|
|
|
|
|
|
|
==|!=|<=>|<=|>=|<|>| (eq|ne|lt|le|gt|ge) | # comparison binary ops |
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
\=~|\!~| x |\.|\+|\-|\*\*|\*| (mod|div) |\/)?/gmx) { # arithmetic and string ops |
1138
|
190
|
50
|
|
|
|
392
|
$debug and print STDERR " [ conditional ($1,$2,$3,$4,$5,$6,$7,$8)]"; |
1139
|
|
|
|
|
|
|
|
1140
|
190
|
|
|
|
|
12743
|
my ($unaryop,$operand,$binaryop) = ($1,$2,$4); |
1141
|
|
|
|
|
|
|
# print STDERR " [unaryop=",($unaryop || 'undef'),", calling ident_eval($operand)]"; |
1142
|
|
|
|
|
|
|
|
1143
|
190
|
|
|
|
|
232
|
if (1) { |
1144
|
190
|
50
|
|
|
|
903
|
defined $operand and push @cstack, [ 2, $operand ]; |
1145
|
|
|
|
|
|
|
} elsif ($unaryop && $unaryop eq 'defined') { |
1146
|
|
|
|
|
|
|
defined $operand and push @cstack, [ 2, $self->identifier_evaluate($operand,$ovr,undef,undef,undef,1) ]; |
1147
|
|
|
|
|
|
|
} else { |
1148
|
|
|
|
|
|
|
defined $operand and push @cstack, [ 2, $self->identifier_evaluate($operand,$ovr) ]; |
1149
|
|
|
|
|
|
|
} |
1150
|
|
|
|
|
|
|
# print STDERR "ident_eval($operand): ".$self->identifier_evaluate($operand,$ovr)."\n"; |
1151
|
190
|
100
|
|
|
|
514
|
$unaryop and push @cstack, [ 4, $unaryop ]; |
1152
|
190
|
100
|
|
|
|
558
|
if ($binop_leftover) { |
1153
|
82
|
|
|
|
|
341
|
push @cstack, [ 5, $binop_leftover ]; |
1154
|
82
|
|
|
|
|
125
|
$binop_leftover = ''; |
1155
|
|
|
|
|
|
|
} |
1156
|
190
|
100
|
|
|
|
393
|
$binaryop and $binop_leftover=$binaryop; |
1157
|
|
|
|
|
|
|
|
1158
|
190
|
50
|
|
|
|
7975
|
$debug and print STDERR "[unary=$unaryop operand=$operand binaryop=$binaryop lo=$binop_leftover, new cstack={". |
1159
|
|
|
|
|
|
|
$self->dump_stack(\@cstack,1)."} ]"; |
1160
|
|
|
|
|
|
|
} |
1161
|
|
|
|
|
|
|
|
1162
|
109
|
50
|
|
|
|
234
|
$binop_leftover and push @cstack, [ 5, $binop_leftover ]; |
1163
|
|
|
|
|
|
|
|
1164
|
109
|
50
|
|
|
|
301
|
if ($self->{use_cond2rpn_cache}) { |
1165
|
109
|
|
|
|
|
208
|
$self->{cond2rpn_cache}{$cond} = [ map { [ $_->[0], $_->[1] ] } @cstack ]; |
|
278
|
|
|
|
|
1747
|
|
1166
|
|
|
|
|
|
|
} |
1167
|
|
|
|
|
|
|
} |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
# print STDERR "[cache for $cond was: ".$self->dump_stack($self->{cond2rpn_cache}{$cond},1)."]"; |
1170
|
|
|
|
|
|
|
# print STDERR "[cstack pre-eval {".$self->dump_stack(\@cstack,1)."} count=$#cstack]"; |
1171
|
131
|
|
|
|
|
286
|
for (@cstack) { |
1172
|
310
|
100
|
|
|
|
4000
|
if ($_->[0] == 2) { |
1173
|
216
|
100
|
|
|
|
1112
|
if ($_->[1] eq 'cacheablething') { |
1174
|
|
|
|
|
|
|
# print STDERR "[item = $ovr->{cacheablething}]"; |
1175
|
|
|
|
|
|
|
} |
1176
|
|
|
|
|
|
|
# print STDERR "[stack eval ident $_->[1] -> "; |
1177
|
216
|
|
|
|
|
662
|
$_->[1] = $self->identifier_evaluate($_->[1],$ovr,undef,undef,undef,1); |
1178
|
|
|
|
|
|
|
# print STDERR "$_->[1]]"; |
1179
|
|
|
|
|
|
|
} |
1180
|
|
|
|
|
|
|
} |
1181
|
|
|
|
|
|
|
# print STDERR "[cstack post-eval {".$self->dump_stack(\@cstack,1)."} count=$#cstack]"; |
1182
|
|
|
|
|
|
|
# print STDERR "[cache for $cond now: ".$self->dump_stack($self->{cond2rpn_cache}{$cond},1)."]"; |
1183
|
|
|
|
|
|
|
|
1184
|
|
|
|
|
|
|
# now put in the stuff to handle boolean chaining (and/or) |
1185
|
131
|
100
|
|
|
|
472
|
return '' unless @cstack; |
1186
|
130
|
|
|
|
|
192
|
my ($lvalue,$op,$operand,$n,@ostack); |
1187
|
130
|
50
|
|
|
|
232
|
$debug and print STDERR " [pre-loop: cstack contains {".$self->dump_stack(\@cstack,1)."} count=$#cstack]"; |
1188
|
|
|
|
|
|
|
|
1189
|
130
|
50
|
|
|
|
237
|
$debug and |
1190
|
|
|
|
|
|
|
print STDERR "[preloop #cstack = $#cstack]"; |
1191
|
|
|
|
|
|
|
|
1192
|
130
|
|
|
|
|
857
|
while ($#cstack != 0) { |
1193
|
94
|
50
|
|
|
|
1429
|
$debug and |
1194
|
|
|
|
|
|
|
print STDERR " [cstack contains {".$self->dump_stack(\@cstack,1)."} count=$#cstack]"; |
1195
|
94
|
|
|
|
|
188
|
$n = shift @cstack; |
1196
|
94
|
50
|
|
|
|
377
|
if ($n->[0] != 2) { |
1197
|
0
|
|
|
|
|
0
|
print STDERR "Got $lexeme_types{$n->[0]} $n->[1] where identifier expected in '$cond'"; |
1198
|
0
|
|
|
|
|
0
|
return undef; |
1199
|
|
|
|
|
|
|
} |
1200
|
|
|
|
|
|
|
# $operand = $n->[1]; |
1201
|
|
|
|
|
|
|
# print STDERR "[operand $n->[1] -> "; |
1202
|
94
|
|
|
|
|
146
|
$operand = $n->[1]; |
1203
|
|
|
|
|
|
|
# print STDERR "$operand]"; |
1204
|
94
|
50
|
|
|
|
189
|
!@cstack and return $operand; |
1205
|
|
|
|
|
|
|
|
1206
|
94
|
|
|
|
|
137
|
$n = shift @cstack; |
1207
|
94
|
100
|
|
|
|
333
|
if ($n->[0] == 4) { # unary op |
|
|
50
|
|
|
|
|
|
1208
|
7
|
|
|
|
|
13
|
$op = $n->[1]; |
1209
|
7
|
|
|
|
|
25
|
unshift @cstack, [ 2, $self->unaryop_evaluate($op,$operand) ]; |
1210
|
7
|
|
|
|
|
24
|
next; |
1211
|
|
|
|
|
|
|
} elsif ($n->[0] == 2) { # another identififer |
1212
|
87
|
|
|
|
|
108
|
$lvalue = $operand; |
1213
|
87
|
|
|
|
|
460
|
$operand = $n->[1]; |
1214
|
|
|
|
|
|
|
# print STDERR "[new operand $n->[1] -> "; |
1215
|
|
|
|
|
|
|
# $operand = $self->identifier_evaluate($n->[1],$ovr); |
1216
|
|
|
|
|
|
|
# print STDERR "$operand]"; |
1217
|
|
|
|
|
|
|
|
1218
|
87
|
|
|
|
|
107
|
$n = shift @cstack; |
1219
|
87
|
100
|
|
|
|
207
|
if ($n->[0] == 5) { # binaryop? |
|
|
50
|
|
|
|
|
|
1220
|
86
|
|
|
|
|
139
|
$op = $n->[1]; |
1221
|
86
|
|
|
|
|
267
|
unshift @cstack, [ 2, $self->binaryop_evaluate($lvalue,$op,$operand) ]; |
1222
|
86
|
|
|
|
|
258
|
next; |
1223
|
|
|
|
|
|
|
} elsif ($n->[0] == 4) { # unaryop (to work on operand, ignoring lvalue) |
1224
|
1
|
|
|
|
|
2
|
$op = $n->[1]; |
1225
|
1
|
|
|
|
|
5
|
unshift @cstack, [ 2, $self->unaryop_evaluate($op,$operand) ]; |
1226
|
1
|
|
|
|
|
3
|
unshift @cstack, [ 2, $lvalue ]; |
1227
|
1
|
|
|
|
|
3
|
next; |
1228
|
|
|
|
|
|
|
} else { |
1229
|
0
|
|
|
|
|
0
|
print STDERR "Got $lexeme_types{$n->[0]} $n->[1] where operator expected in '$cond'"; |
1230
|
0
|
|
|
|
|
0
|
return ''; |
1231
|
|
|
|
|
|
|
} |
1232
|
0
|
|
|
|
|
0
|
next; |
1233
|
|
|
|
|
|
|
} else { |
1234
|
0
|
|
|
|
|
0
|
print STDERR "Got $lexeme_types{$n->[0]} $n->[1] where unaryop or identifier expected in '$cond'"; |
1235
|
0
|
|
|
|
|
0
|
return ''; |
1236
|
|
|
|
|
|
|
} |
1237
|
|
|
|
|
|
|
} |
1238
|
130
|
|
|
|
|
206
|
$n = $cstack[0]; |
1239
|
130
|
50
|
|
|
|
289
|
$debug and |
1240
|
|
|
|
|
|
|
print STDERR "[postloop n={$n->[0],$n->[1]}]"; |
1241
|
|
|
|
|
|
|
|
1242
|
130
|
50
|
|
|
|
343
|
if ($self->{use_full_cond_cache}) { |
1243
|
130
|
|
|
|
|
624
|
$self->{fullcond_cache}{"$ovr\t$cond"} = $n->[1]; |
1244
|
|
|
|
|
|
|
} |
1245
|
130
|
100
|
|
|
|
1890
|
defined $n->[1] and return $n->[1]; |
1246
|
2
|
|
|
|
|
8
|
''; |
1247
|
|
|
|
|
|
|
} |
1248
|
|
|
|
|
|
|
|
1249
|
|
|
|
|
|
|
sub binaryop_evaluate { |
1250
|
86
|
|
|
86
|
0
|
105
|
my $self = shift; |
1251
|
86
|
|
|
|
|
214
|
my ($lvalue,$op,$operand) = @_; |
1252
|
|
|
|
|
|
|
|
1253
|
86
|
50
|
|
|
|
190
|
$debug and |
1254
|
|
|
|
|
|
|
print STDERR "[binaryop_eval($lvalue,$op,$operand)]"; |
1255
|
86
|
50
|
|
|
|
171
|
if (!defined $op) { |
1256
|
|
|
|
|
|
|
# print STDERR "[missing operator in binaryop_evaluate]"; |
1257
|
0
|
|
|
|
|
0
|
return undef; |
1258
|
|
|
|
|
|
|
} |
1259
|
86
|
100
|
|
|
|
146
|
if (!defined $lvalue) { |
1260
|
|
|
|
|
|
|
# print STDERR "[lvalue undefined in binaryop_evaluate]"; |
1261
|
1
|
|
|
|
|
4
|
return undef; |
1262
|
|
|
|
|
|
|
} |
1263
|
85
|
50
|
|
|
|
143
|
if (!defined $operand) { |
1264
|
|
|
|
|
|
|
# print STEDRR "[operand undefined in binaryop_evaluate]"; |
1265
|
0
|
|
|
|
|
0
|
return undef; |
1266
|
|
|
|
|
|
|
} |
1267
|
|
|
|
|
|
|
# string comparison ops |
1268
|
85
|
100
|
66
|
|
|
1367
|
if ($op eq 'eq') { |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1269
|
18
|
|
|
|
|
64
|
return $lvalue eq $operand; |
1270
|
|
|
|
|
|
|
} elsif ($op eq 'ne') { |
1271
|
1
|
|
|
|
|
4
|
return $lvalue ne $operand; |
1272
|
|
|
|
|
|
|
} elsif ($op eq 'lt') { |
1273
|
2
|
|
|
|
|
9
|
return $lvalue lt $operand; |
1274
|
|
|
|
|
|
|
} elsif ($op eq 'le') { |
1275
|
1
|
|
|
|
|
5
|
return $lvalue le $operand; |
1276
|
|
|
|
|
|
|
} elsif ($op eq 'gt') { |
1277
|
2
|
|
|
|
|
11
|
return $lvalue gt $operand; |
1278
|
|
|
|
|
|
|
} elsif ($op eq 'ge') { |
1279
|
3
|
|
|
|
|
12
|
return $lvalue ge $operand; |
1280
|
|
|
|
|
|
|
} elsif ($op eq '=~' and $self->{enable_pattern_operator}) { |
1281
|
2
|
|
|
|
|
41
|
return $lvalue =~ m/$operand/; |
1282
|
|
|
|
|
|
|
} elsif ($op eq '!~' and $self->{enable_pattern_operator}) { |
1283
|
3
|
|
|
|
|
39
|
return $lvalue !~ m/$operand/; |
1284
|
|
|
|
|
|
|
} |
1285
|
|
|
|
|
|
|
# numeric comparison ops |
1286
|
|
|
|
|
|
|
elsif ($op eq '==') { |
1287
|
5
|
|
|
|
|
20
|
return $lvalue == $operand; |
1288
|
|
|
|
|
|
|
} elsif ($op eq '!=') { |
1289
|
2
|
|
|
|
|
9
|
return $lvalue != $operand; |
1290
|
|
|
|
|
|
|
} elsif ($op eq '<') { |
1291
|
2
|
|
|
|
|
9
|
return $lvalue < $operand; |
1292
|
|
|
|
|
|
|
} elsif ($op eq '<=') { |
1293
|
2
|
|
|
|
|
11
|
return $lvalue <= $operand; |
1294
|
|
|
|
|
|
|
} elsif ($op eq '>') { |
1295
|
1
|
|
|
|
|
17
|
return $lvalue > $operand; |
1296
|
|
|
|
|
|
|
} elsif ($op eq '>=') { |
1297
|
1
|
|
|
|
|
5
|
return $lvalue >= $operand; |
1298
|
|
|
|
|
|
|
} elsif ($op eq '<=>') { |
1299
|
2
|
|
|
|
|
12
|
return $lvalue <=> $operand; |
1300
|
|
|
|
|
|
|
} |
1301
|
|
|
|
|
|
|
# logical ops |
1302
|
|
|
|
|
|
|
elsif ($op eq '&&' or $op eq 'and') { |
1303
|
11
|
|
66
|
|
|
58
|
return ($lvalue && $operand); |
1304
|
|
|
|
|
|
|
} elsif ($op eq '||' or $op eq 'or') { |
1305
|
3
|
|
33
|
|
|
53
|
return ($lvalue || $operand); |
1306
|
|
|
|
|
|
|
} |
1307
|
|
|
|
|
|
|
|
1308
|
|
|
|
|
|
|
# string combination ops |
1309
|
|
|
|
|
|
|
elsif ($op eq '.') { |
1310
|
1
|
|
|
|
|
4
|
return $lvalue . $operand; |
1311
|
|
|
|
|
|
|
} elsif ($op eq 'x') { |
1312
|
1
|
|
|
|
|
6
|
return $lvalue x $operand; |
1313
|
|
|
|
|
|
|
} |
1314
|
|
|
|
|
|
|
|
1315
|
|
|
|
|
|
|
# arithmetic ops |
1316
|
|
|
|
|
|
|
elsif ($op eq '+') { |
1317
|
1
|
|
|
|
|
4
|
return $lvalue + $operand; |
1318
|
|
|
|
|
|
|
} elsif ($op eq '-') { |
1319
|
1
|
|
|
|
|
5
|
return $lvalue - $operand; |
1320
|
|
|
|
|
|
|
} elsif ($op eq '*') { |
1321
|
1
|
|
|
|
|
56
|
return $lvalue * $operand; |
1322
|
|
|
|
|
|
|
} elsif ($op eq '/' and $operand) { |
1323
|
2
|
|
|
|
|
13
|
return $lvalue / $operand; |
1324
|
|
|
|
|
|
|
} elsif ($op eq 'div' and $operand) { |
1325
|
1
|
|
|
|
|
6
|
return int($lvalue/$operand); |
1326
|
|
|
|
|
|
|
} elsif ($op eq 'mod' and $operand) { # % is reserved |
1327
|
1
|
|
|
|
|
5
|
return $lvalue % $operand; |
1328
|
|
|
|
|
|
|
} elsif ($op eq '**') { |
1329
|
2
|
|
|
|
|
12
|
return $lvalue ** $operand; |
1330
|
|
|
|
|
|
|
} |
1331
|
|
|
|
|
|
|
# bitwise ops |
1332
|
|
|
|
|
|
|
elsif ($op eq '^') { |
1333
|
2
|
|
|
|
|
10
|
return 1*$lvalue ^ 1*$operand; |
1334
|
|
|
|
|
|
|
} elsif ($op eq '&') { |
1335
|
2
|
|
|
|
|
12
|
return 1*$lvalue & 1*$operand; |
1336
|
|
|
|
|
|
|
} elsif ($op eq '|') { |
1337
|
1
|
|
|
|
|
5
|
return 1*$lvalue | 1*$operand; |
1338
|
|
|
|
|
|
|
} elsif ($op eq '<<') { |
1339
|
4
|
|
|
|
|
19
|
return 1*$lvalue << 1*$operand; |
1340
|
|
|
|
|
|
|
} elsif ($op eq '>>') { |
1341
|
4
|
|
|
|
|
23
|
return 1*$lvalue >> 1*$operand; |
1342
|
|
|
|
|
|
|
} |
1343
|
0
|
|
|
|
|
0
|
undef; |
1344
|
|
|
|
|
|
|
} |
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
sub unaryop_evaluate { |
1347
|
8
|
|
|
8
|
0
|
13
|
my $self = shift; |
1348
|
8
|
|
|
|
|
13
|
my ($op,$operand) = @_; |
1349
|
|
|
|
|
|
|
|
1350
|
8
|
50
|
|
|
|
20
|
$debug and |
1351
|
|
|
|
|
|
|
print STDERR " [unary_eval $op, $operand]"; |
1352
|
8
|
50
|
33
|
|
|
34
|
if (!$op) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1353
|
0
|
|
|
|
|
0
|
return (!(!($operand))); |
1354
|
|
|
|
|
|
|
} elsif ($op eq '!') { |
1355
|
6
|
|
|
|
|
20
|
return !$operand; |
1356
|
|
|
|
|
|
|
} elsif ($op eq 'defined' || $op =~ /^defined\s+/) { |
1357
|
2
|
|
|
|
|
11
|
return defined $operand; |
1358
|
|
|
|
|
|
|
} |
1359
|
|
|
|
|
|
|
# fill in other ops here |
1360
|
0
|
|
|
|
|
0
|
undef; |
1361
|
|
|
|
|
|
|
} |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
=item identifier_evaluate $identifier \%ovr [ $type, $name ] |
1364
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
Evaluates the specified identifier and returns its value. Literals, |
1366
|
|
|
|
|
|
|
being of the form \d+, "[...]" and '[...]', are returned as-is (leading |
1367
|
|
|
|
|
|
|
and trailing quotes will be removed from string literals). |
1368
|
|
|
|
|
|
|
|
1369
|
|
|
|
|
|
|
Identifiers of standard (no special type) form are returned as they appear |
1370
|
|
|
|
|
|
|
in \%ovr; if those stored values are listrefs or hashrefs, they will be |
1371
|
|
|
|
|
|
|
returned in formatted form -- listrefs will be returned as a scalar |
1372
|
|
|
|
|
|
|
delimited by the value of $self->{list_delimiter}->{B}, hashes will |
1373
|
|
|
|
|
|
|
be mapped into a scalar using $self->{hash_specifier}->{B} and |
1374
|
|
|
|
|
|
|
$self->{hash_delimiter}->{B}, which three have the form ", ", |
1375
|
|
|
|
|
|
|
"=" and ", " respectively by default. |
1376
|
|
|
|
|
|
|
|
1377
|
|
|
|
|
|
|
Identifiers of the form $name will be checked against the environment |
1378
|
|
|
|
|
|
|
variable of the same name, and if present, that value will be returned, |
1379
|
|
|
|
|
|
|
otherwise undef will be returned. |
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
Identififers of the form &name will be returned according to those entries |
1382
|
|
|
|
|
|
|
in \%ovr of the form &name -- this is used to provide a separate namespace |
1383
|
|
|
|
|
|
|
for substitutions, e.g. for CGI parameters. |
1384
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
Identifiers of the form !name will be evaluated according to the return |
1386
|
|
|
|
|
|
|
value(s) from whatever stored procedure(s) have been registered under that |
1387
|
|
|
|
|
|
|
name, if any. See C for details. |
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
=cut |
1390
|
|
|
|
|
|
|
|
1391
|
|
|
|
|
|
|
sub identifier_evaluate { |
1392
|
254
|
|
|
254
|
1
|
318
|
my $self = shift; |
1393
|
254
|
|
|
|
|
367
|
my $identifier = shift; |
1394
|
254
|
|
50
|
|
|
520
|
my $ovr = shift || {}; |
1395
|
254
|
|
|
|
|
715
|
my ($type,$name,$args,$undef_asis) = @_; |
1396
|
|
|
|
|
|
|
|
1397
|
|
|
|
|
|
|
# undef is an OK value, but undef |
1398
|
|
|
|
|
|
|
# is also the correct thing to return in such a case. |
1399
|
254
|
50
|
0
|
|
|
3758
|
$debug and print STDERR " [identifier $identifier(",$type || '',',',$name || '',")]"; |
|
|
|
0
|
|
|
|
|
1400
|
254
|
50
|
|
|
|
531
|
!defined $identifier and return $self->{default_undef_identifier}; |
1401
|
254
|
100
|
|
|
|
454
|
!$identifier and return $identifier; |
1402
|
238
|
100
|
66
|
|
|
868
|
unless (defined $type && $name) { |
1403
|
200
|
100
|
|
|
|
1057
|
return $1 if $identifier =~ /^(\d+)$/; |
1404
|
108
|
100
|
|
|
|
537
|
return $1 if $identifier =~ /^\"(.*)\"$/; |
1405
|
56
|
50
|
|
|
|
118
|
return $1 if $identifier =~ /^\'(.*)\'$/; |
1406
|
56
|
100
|
|
|
|
391
|
if ($identifier =~ /^([&\$\"]?)([A-Za-z_]\w*)$/) { |
|
|
50
|
|
|
|
|
|
1407
|
42
|
|
|
|
|
125
|
($type,$name) = ($1,$2); |
1408
|
|
|
|
|
|
|
} elsif ($identifier =~ /^&(\w+)\((.*)\)$/) { |
1409
|
14
|
|
|
|
|
62
|
($type,$name,$args) = ('&',$1,$2); |
1410
|
|
|
|
|
|
|
} else { |
1411
|
0
|
|
|
|
|
0
|
print STDERR "Malformed identifier '$identifier'"; |
1412
|
0
|
|
|
|
|
0
|
return undef; |
1413
|
|
|
|
|
|
|
} |
1414
|
|
|
|
|
|
|
} |
1415
|
94
|
50
|
|
|
|
198
|
$debug and print STDERR " [identifier_evaluate: type=$type name=$name]"; |
1416
|
94
|
100
|
|
|
|
270
|
if (!$type) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1417
|
78
|
100
|
|
|
|
330
|
if (!defined $ovr->{$name}) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
# print STDERR "!defined $name, undef_asis=$undef_asis"; |
1419
|
2
|
50
|
|
|
|
12
|
return ($undef_asis ? undef : $self->{default_undef_identifier} ); |
1420
|
|
|
|
|
|
|
} elsif (!ref $ovr->{$name}) { |
1421
|
62
|
|
|
|
|
251
|
return $ovr->{$name}; |
1422
|
|
|
|
|
|
|
} elsif (ref $ovr->{$name} eq 'ARRAY') { |
1423
|
4
|
|
|
|
|
18
|
return join($self->{list_delimiter}->{$name} || |
1424
|
|
|
|
|
|
|
$self->{list_delimiter}->{__default}, |
1425
|
4
|
|
66
|
|
|
18
|
@{ $ovr->{$name} }); |
1426
|
|
|
|
|
|
|
} elsif (ref $ovr->{$name} eq 'SCALAR') { |
1427
|
0
|
|
|
|
|
0
|
return ${ $ovr->{$name} }; |
|
0
|
|
|
|
|
0
|
|
1428
|
|
|
|
|
|
|
} elsif (ref $ovr->{$name} eq 'HASH') { |
1429
|
12
|
|
33
|
|
|
66
|
return join($self->{hash_delimiter}->{$name} || |
1430
|
|
|
|
|
|
|
$self->{hash_delimiter}->{__default}, |
1431
|
4
|
|
|
|
|
11
|
map { $_. |
1432
|
|
|
|
|
|
|
($self->{hash_specifier}->{$name} || |
1433
|
|
|
|
|
|
|
$self->{hash_specifier}->{__default}). |
1434
|
|
|
|
|
|
|
$ovr->{$name}->{$_} |
1435
|
4
|
|
33
|
|
|
27
|
} keys %{$ovr->{$name}} |
1436
|
|
|
|
|
|
|
); |
1437
|
|
|
|
|
|
|
} elsif (ref $ovr->{$name} eq 'CODE') { |
1438
|
6
|
50
|
|
|
|
40
|
!$self->{eval_subroutine_refs} and return $self->{disabled_subref_identifier}; |
1439
|
6
|
|
|
|
|
34
|
return $self->evaluate_dynroutine($name,'',$ovr); |
1440
|
|
|
|
|
|
|
} |
1441
|
0
|
|
|
|
|
0
|
return $ovr->{$name}; |
1442
|
|
|
|
|
|
|
# } elsif ($type eq '&') { |
1443
|
|
|
|
|
|
|
# return $ovr->{'&'.$name}; |
1444
|
|
|
|
|
|
|
} elsif ($type eq "\$") { |
1445
|
0
|
|
|
|
|
0
|
return $ENV{$name}; |
1446
|
|
|
|
|
|
|
} elsif ($type eq '&') { |
1447
|
16
|
|
100
|
|
|
44
|
$args ||= ''; |
1448
|
16
|
50
|
|
|
|
39
|
$debug and print STDERR " [returning \$self->evaluate_dynroutine($name,$args,$ovr)]"; |
1449
|
16
|
50
|
|
|
|
52
|
!$self->{eval_subroutine_refs} and return $self->{disabled_subref_identifier}; |
1450
|
16
|
|
|
|
|
55
|
return $self->evaluate_dynroutine($name,$args,$ovr); |
1451
|
|
|
|
|
|
|
} |
1452
|
0
|
|
|
|
|
0
|
return undef; |
1453
|
|
|
|
|
|
|
} |
1454
|
|
|
|
|
|
|
|
1455
|
|
|
|
|
|
|
=item evaluate_dynroutine $name, $args, \%ovr |
1456
|
|
|
|
|
|
|
|
1457
|
|
|
|
|
|
|
Evalutes a routine referenced by a template. The general form gives the |
1458
|
|
|
|
|
|
|
name of the routine in $name (if no such named routine is available, |
1459
|
|
|
|
|
|
|
returns undef), any arguments as a scalar $args, and the key-sub list |
1460
|
|
|
|
|
|
|
in $ovr. |
1461
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
$args should be given as a scalar -- it will be parsed in |
1463
|
|
|
|
|
|
|
B and the result cached against future use. |
1464
|
|
|
|
|
|
|
|
1465
|
|
|
|
|
|
|
=cut |
1466
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
sub evaluate_dynroutine { |
1468
|
22
|
|
|
22
|
1
|
39
|
my $self = shift; |
1469
|
22
|
|
|
|
|
70
|
my ($name,$args,$ovr) = @_; |
1470
|
22
|
|
|
|
|
27
|
my @real_args; |
1471
|
22
|
|
|
|
|
42
|
my ($buf,$seg,$sseg) = (''); |
1472
|
22
|
|
|
|
|
28
|
my $use_recursive_parse = 0; |
1473
|
22
|
|
|
|
|
27
|
my %ra; |
1474
|
|
|
|
|
|
|
|
1475
|
22
|
50
|
33
|
|
|
118
|
$name && $ovr or return undef; |
1476
|
22
|
100
|
|
|
|
15914
|
$name =~ /^bt_/ and return $self->evaluate_pragma(@_); |
1477
|
16
|
50
|
|
|
|
53
|
$ovr->{$name} or return undef; |
1478
|
16
|
|
100
|
|
|
65
|
$args ||= ''; |
1479
|
16
|
50
|
|
|
|
46
|
$debug && print STDERR " [evaluate_dynroutine: name=$name args=$args ovr=$ovr]"; |
1480
|
16
|
100
|
|
|
|
647
|
if ($args) { |
1481
|
7
|
50
|
|
|
|
30
|
if ($self->{dynroutine_arg_cache}{$args}) { |
1482
|
0
|
|
|
|
|
0
|
$args = $self->{dynroutine_arg_cache}{$args}; |
1483
|
|
|
|
|
|
|
} else { |
1484
|
7
|
|
|
|
|
32
|
my $targs = $self->parse_dynroutine_args($args); |
1485
|
7
|
|
|
|
|
22
|
$self->{dynroutine_arg_cache}{$args} = $targs; |
1486
|
7
|
|
|
|
|
23
|
$args = $targs; |
1487
|
|
|
|
|
|
|
} |
1488
|
|
|
|
|
|
|
} |
1489
|
16
|
100
|
|
|
|
53
|
if (ref $args eq 'ARRAY') { |
1490
|
7
|
|
|
|
|
12
|
for (0..$#{$args}) { |
|
7
|
|
|
|
|
26
|
|
1491
|
25
|
50
|
|
|
|
158
|
if ($args->[$_] eq '$_bt_dict') { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1492
|
0
|
|
|
|
|
0
|
$args->[$_] = $ovr; |
1493
|
|
|
|
|
|
|
} elsif ($args->[$_] =~ /^\\(.*)$/) { |
1494
|
|
|
|
|
|
|
# escaped anything |
1495
|
0
|
|
|
|
|
0
|
$args->[$_] = $1; |
1496
|
|
|
|
|
|
|
} elsif ($args->[$_] =~ /^\$([\$\&]?\w+)$/) { |
1497
|
|
|
|
|
|
|
# scalar |
1498
|
0
|
|
|
|
|
0
|
$args->[$_] = $self->identifier_evaluate($1,$ovr); |
1499
|
|
|
|
|
|
|
} elsif ($args->[$_] =~ /^\$\{([^\}]+)\}$/) { |
1500
|
0
|
|
|
|
|
0
|
$args->[$_] = $self->cond_evaluate($1,$ovr); |
1501
|
|
|
|
|
|
|
} |
1502
|
|
|
|
|
|
|
} |
1503
|
7
|
|
|
|
|
14
|
@real_args = @{ $args }; |
|
7
|
|
|
|
|
26
|
|
1504
|
|
|
|
|
|
|
} else { |
1505
|
9
|
|
|
|
|
20
|
@real_args = (); |
1506
|
|
|
|
|
|
|
} |
1507
|
|
|
|
|
|
|
|
1508
|
16
|
100
|
100
|
|
|
105
|
if (@real_args and !(($#real_args+1) % 2)) { |
1509
|
6
|
50
|
|
|
|
18
|
$debug and print STDERR " [right number of args to recurse, ref=".(ref $ovr->{$name})."]"; |
1510
|
6
|
50
|
33
|
|
|
35
|
if (ref $ovr->{$name} eq 'CODE' or |
|
1
|
|
33
|
|
|
1154
|
|
|
|
|
66
|
|
|
|
|
1511
|
|
|
|
|
|
|
(ref $ovr->{$name} eq 'ARRAY' and |
1512
|
|
|
|
|
|
|
$#{ $ovr->{$name} } == 2 and |
1513
|
|
|
|
|
|
|
ref $ovr->{$name}->[1] eq 'CODE')) { |
1514
|
6
|
|
|
|
|
30
|
%ra = @real_args; |
1515
|
6
|
100
|
|
|
|
20
|
if ($ra{bt_template}) { |
1516
|
1
|
|
|
|
|
5
|
$use_recursive_parse = 1; |
1517
|
|
|
|
|
|
|
} |
1518
|
|
|
|
|
|
|
# $debug and print STDERR " [use recursive_parse]"; |
1519
|
|
|
|
|
|
|
} |
1520
|
|
|
|
|
|
|
} |
1521
|
|
|
|
|
|
|
|
1522
|
|
|
|
|
|
|
# print " [e_d: name=$name, ovr=$ovr ovr->name=$ovr->{$name}]"; |
1523
|
|
|
|
|
|
|
# ref $ovr->{$name} eq 'ARRAY' and $debug and print STDERR " [num=".$#{ $ovr->{$name} }."]"; |
1524
|
16
|
100
|
33
|
|
|
78
|
if (ref $ovr->{$name} eq 'CODE') { |
|
2
|
50
|
|
|
|
12
|
|
1525
|
14
|
|
|
|
|
23
|
$buf = &{ $ovr->{$name} }(@real_args); |
|
14
|
|
|
|
|
78
|
|
1526
|
14
|
50
|
|
|
|
108
|
$debug and print STDERR " [real_args=".join(',',@real_args)." n=$#real_args]"; |
1527
|
14
|
50
|
|
|
|
1010
|
!ref $buf and return $buf; |
1528
|
0
|
0
|
0
|
|
|
0
|
if (ref $buf eq 'HASH' and $use_recursive_parse) { |
1529
|
0
|
0
|
|
|
|
0
|
$debug and print STDERR " [would now recurse to parse subref output]"; |
1530
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
} |
1532
|
|
|
|
|
|
|
} elsif (ref $ovr->{$name} eq 'ARRAY' and |
1533
|
|
|
|
|
|
|
$#{ $ovr->{$name} } == 2) { |
1534
|
2
|
50
|
|
|
|
16
|
if (!ref $ovr->{$name}->[0]) { |
|
|
50
|
|
|
|
|
|
1535
|
0
|
|
|
|
|
0
|
$buf = $ovr->{$name}->[0]; |
1536
|
0
|
0
|
|
|
|
0
|
$debug and print STDERR " [started with scalar $buf]"; |
1537
|
|
|
|
|
|
|
} elsif (ref $ovr->{$name}->[0] eq 'CODE') { |
1538
|
2
|
|
|
|
|
4
|
$seg = &{ $ovr->{$name}->[0] }(@real_args); |
|
2
|
|
|
|
|
15
|
|
1539
|
2
|
50
|
66
|
|
|
19
|
if ($use_recursive_parse and ref $seg eq 'HASH') { |
1540
|
0
|
|
|
|
|
0
|
$sseg = $self->parse($ra{bt_template},$seg,$ovr, |
1541
|
|
|
|
|
|
|
{ _bt_recurse_count => |
1542
|
|
|
|
|
|
|
$ovr->{_bt_recurse_count}+1 }); |
1543
|
0
|
0
|
|
|
|
0
|
if (ref $sseg eq 'SCALAR') { |
|
|
0
|
|
|
|
|
|
1544
|
0
|
|
|
|
|
0
|
$buf = $$sseg; |
1545
|
|
|
|
|
|
|
} elsif (!ref $sseg) { |
1546
|
0
|
|
|
|
|
0
|
$buf = $sseg; |
1547
|
|
|
|
|
|
|
} |
1548
|
|
|
|
|
|
|
} else { |
1549
|
2
|
|
|
|
|
6
|
$buf = $seg; |
1550
|
|
|
|
|
|
|
} |
1551
|
|
|
|
|
|
|
} |
1552
|
2
|
50
|
|
|
|
14
|
if (!ref $ovr->{$name}->[1]) { |
|
|
50
|
|
|
|
|
|
1553
|
0
|
|
|
|
|
0
|
$buf .= $ovr->{$name}->[1]; |
1554
|
|
|
|
|
|
|
} elsif (ref $ovr->{$name}->[1] eq 'CODE') { |
1555
|
2
|
|
|
|
|
6
|
while ($seg = &{ $ovr->{$name}->[1] }(@real_args)) { |
|
7
|
|
|
|
|
35
|
|
1556
|
5
|
100
|
66
|
|
|
87
|
if ($use_recursive_parse and ref $seg eq 'HASH') { |
1557
|
3
|
|
|
|
|
30
|
$sseg = $self->parse($ra{bt_template},$seg,$ovr, |
1558
|
|
|
|
|
|
|
{ _bt_recurse_count => |
1559
|
|
|
|
|
|
|
$ovr->{_bt_recurse_count}+1 }); |
1560
|
3
|
50
|
|
|
|
25
|
if (ref $sseg eq 'SCALAR') { |
|
|
50
|
|
|
|
|
|
1561
|
0
|
|
|
|
|
0
|
$buf .= $$sseg; |
1562
|
|
|
|
|
|
|
} elsif (!ref $sseg) { |
1563
|
3
|
|
|
|
|
10
|
$buf .= $sseg; |
1564
|
|
|
|
|
|
|
} |
1565
|
|
|
|
|
|
|
} else { |
1566
|
2
|
|
|
|
|
5
|
$buf .= $seg; |
1567
|
|
|
|
|
|
|
} |
1568
|
|
|
|
|
|
|
} |
1569
|
|
|
|
|
|
|
} |
1570
|
2
|
50
|
|
|
|
27
|
if (!ref $ovr->{$name}->[2]) { |
|
|
50
|
|
|
|
|
|
1571
|
0
|
|
|
|
|
0
|
$buf .= $ovr->{$name}->[2]; |
1572
|
|
|
|
|
|
|
} elsif (ref $ovr->{$name}->[2] eq 'CODE') { |
1573
|
|
|
|
|
|
|
# $buf .= &{ $ovr->{$name}->[2] }(@real_args); |
1574
|
2
|
|
|
|
|
4
|
$seg = &{ $ovr->{$name}->[2] }(@real_args); |
|
2
|
|
|
|
|
9
|
|
1575
|
2
|
50
|
66
|
|
|
79
|
if ($use_recursive_parse and ref $seg eq 'HASH') { |
1576
|
0
|
|
|
|
|
0
|
$sseg = $self->parse($ra{bt_template},$seg,$ovr, |
1577
|
|
|
|
|
|
|
{ _bt_recurse_count => |
1578
|
|
|
|
|
|
|
$ovr->{_bt_recurse_count}+1 }); |
1579
|
0
|
|
|
|
|
0
|
$buf .= $$sseg; |
1580
|
|
|
|
|
|
|
} else { |
1581
|
2
|
|
|
|
|
4
|
$buf .= $seg; |
1582
|
|
|
|
|
|
|
} |
1583
|
|
|
|
|
|
|
} |
1584
|
2
|
|
|
|
|
15
|
return $buf; |
1585
|
|
|
|
|
|
|
} |
1586
|
|
|
|
|
|
|
} |
1587
|
|
|
|
|
|
|
|
1588
|
|
|
|
|
|
|
=item parse_dynroutine_args $argstr |
1589
|
|
|
|
|
|
|
|
1590
|
|
|
|
|
|
|
Pulls apart the argument string passed to a template-referenced |
1591
|
|
|
|
|
|
|
dynamic routine, and returns a listref for it. |
1592
|
|
|
|
|
|
|
|
1593
|
|
|
|
|
|
|
Format tolerance is only minimally clever. The formats tolerated |
1594
|
|
|
|
|
|
|
are, in any combination: |
1595
|
|
|
|
|
|
|
|
1596
|
|
|
|
|
|
|
word, word, |
1597
|
|
|
|
|
|
|
word => word, word |
1598
|
|
|
|
|
|
|
word => "word \"word\" 'word'" |
1599
|
|
|
|
|
|
|
word => 'word "word"' |
1600
|
|
|
|
|
|
|
word => "word\nword", |
1601
|
|
|
|
|
|
|
|
1602
|
|
|
|
|
|
|
In the first case, each word argument may contain anything but [,=>'"] |
1603
|
|
|
|
|
|
|
(that is, ', ", =, or >; yes, that is not entirely proper). |
1604
|
|
|
|
|
|
|
If you need to use any of those characters, put the arguments in |
1605
|
|
|
|
|
|
|
quotes. Parsing with quotations is more accurate, but depends on |
1606
|
|
|
|
|
|
|
lookbehind assertions and is accordingly slow (the parse |
1607
|
|
|
|
|
|
|
results are cached, so this is mostly an issue in repetitive |
1608
|
|
|
|
|
|
|
executions rather than use of many instances in one template). |
1609
|
|
|
|
|
|
|
|
1610
|
|
|
|
|
|
|
=cut |
1611
|
|
|
|
|
|
|
|
1612
|
|
|
|
|
|
|
sub parse_dynroutine_args { |
1613
|
11
|
|
|
11
|
1
|
19
|
my $self = shift; |
1614
|
11
|
|
50
|
|
|
46
|
my $argstr = shift || return []; |
1615
|
11
|
|
|
|
|
25
|
my @args = (); |
1616
|
11
|
|
|
|
|
15
|
my $x; |
1617
|
|
|
|
|
|
|
|
1618
|
11
|
100
|
|
|
|
37
|
if ($argstr =~ tr/\"\'/\"\'/) { |
1619
|
2
|
|
|
|
|
19
|
while ($argstr =~ m/\s*([^,=>\"\']+?| # word arg (yes, the => in the class is bad |
1620
|
|
|
|
|
|
|
(\"|\')(.*?(?
|
1621
|
|
|
|
|
|
|
)\s*(?:,|=>|$)/sgx) { # space, comma, => |
1622
|
14
|
|
66
|
|
|
45
|
$x = $3 || $1; |
1623
|
14
|
50
|
50
|
|
|
43
|
$x eq "''" or $x eq '""' and $x = '' ; |
1624
|
14
|
|
|
|
|
30
|
$x =~ s/(?
|
1625
|
14
|
|
|
|
|
77
|
push @args, $x; |
1626
|
|
|
|
|
|
|
} |
1627
|
|
|
|
|
|
|
} else { |
1628
|
9
|
|
|
|
|
105
|
@args = split(/\s*(?:=>|,)\s*/,$argstr); |
1629
|
|
|
|
|
|
|
} |
1630
|
|
|
|
|
|
|
# warn "parse_args: [new: $argstr -> ".join('|',@args)."]"; |
1631
|
|
|
|
|
|
|
# warn "parse_args: vs [old: $argstr -> ".join('|',split(/\s*(?:=>|,)\s*/,$argstr))."]"; |
1632
|
|
|
|
|
|
|
# return [ split(/\s*(?:=>|,)\s*/,$argstr) ]; |
1633
|
11
|
|
|
|
|
52
|
\@args; |
1634
|
|
|
|
|
|
|
} |
1635
|
|
|
|
|
|
|
|
1636
|
|
|
|
|
|
|
=item evaluate_pragma $name, $args, \%ovr |
1637
|
|
|
|
|
|
|
|
1638
|
|
|
|
|
|
|
=cut |
1639
|
|
|
|
|
|
|
|
1640
|
|
|
|
|
|
|
sub evaluate_pragma { |
1641
|
6
|
|
|
6
|
1
|
10
|
my $self = shift; |
1642
|
6
|
|
|
|
|
13
|
my ($name,$args,$ovr) = @_; |
1643
|
6
|
|
|
|
|
8
|
my @real_args; |
1644
|
|
|
|
|
|
|
|
1645
|
6
|
|
50
|
|
|
18
|
$args ||= ''; |
1646
|
6
|
50
|
33
|
|
|
38
|
$name && $ovr or return undef; |
1647
|
6
|
50
|
|
|
|
15
|
$debug && print STDERR " [evaluate_dynroutine: name=$name args=$args ovr=$ovr]"; |
1648
|
6
|
50
|
|
|
|
25
|
if ($args) { |
1649
|
6
|
100
|
|
|
|
22
|
if ($self->{dynroutine_arg_cache}{$args}) { |
1650
|
2
|
|
|
|
|
8
|
$args = $self->{dynroutine_arg_cache}{$args}; |
1651
|
|
|
|
|
|
|
} else { |
1652
|
4
|
|
|
|
|
14
|
my $targs = $self->parse_dynroutine_args($args); |
1653
|
4
|
|
|
|
|
13
|
$self->{dynroutine_arg_cache}{$args} = $targs; |
1654
|
4
|
|
|
|
|
9
|
$args = $targs; |
1655
|
|
|
|
|
|
|
} |
1656
|
|
|
|
|
|
|
} |
1657
|
6
|
50
|
|
|
|
28
|
if (ref $args eq 'ARRAY') { |
1658
|
6
|
|
|
|
|
6
|
@real_args = @{ $args }; |
|
6
|
|
|
|
|
21
|
|
1659
|
|
|
|
|
|
|
} else { |
1660
|
0
|
|
|
|
|
0
|
@real_args = (); |
1661
|
|
|
|
|
|
|
} |
1662
|
6
|
100
|
66
|
|
|
51
|
unless ($self->{pragma_enable}->{$name} && |
1663
|
|
|
|
|
|
|
ref $self->{pragma_functions}->{$name} eq 'CODE') { |
1664
|
1
|
50
|
|
|
|
4
|
$debug && print STDERR "pragma $name is disabled or has no function reference (enable=$self->{pragma_enable}->{$name}, ref=$self->{pragma_functions}->{$name}"; |
1665
|
1
|
|
|
|
|
9
|
return $self->{disabled_pragma_identifier}; |
1666
|
|
|
|
|
|
|
} |
1667
|
|
|
|
|
|
|
# print STDERR "pragma_enable->{$name} is true, calling prama"; |
1668
|
5
|
|
|
|
|
10
|
return &{ $self->{pragma_functions}->{$name} }($self,$ovr,@real_args); |
|
5
|
|
|
|
|
23
|
|
1669
|
|
|
|
|
|
|
} |
1670
|
|
|
|
|
|
|
|
1671
|
|
|
|
|
|
|
=item is_identifier \$candidate |
1672
|
|
|
|
|
|
|
|
1673
|
|
|
|
|
|
|
Takes a reference to a scalar containing a potential identifier. |
1674
|
|
|
|
|
|
|
In a scalar context, returns 1 or 0. In a list context, returns |
1675
|
|
|
|
|
|
|
(type,name) where type is one of the identififer type designators |
1676
|
|
|
|
|
|
|
(&, !, $, etc) and name is the remainder of the identifier. |
1677
|
|
|
|
|
|
|
|
1678
|
|
|
|
|
|
|
=cut |
1679
|
|
|
|
|
|
|
|
1680
|
|
|
|
|
|
|
sub is_identifier { |
1681
|
212
|
|
|
212
|
1
|
253
|
my $self = shift; |
1682
|
212
|
|
|
|
|
240
|
my $nr = shift; |
1683
|
|
|
|
|
|
|
|
1684
|
212
|
50
|
|
|
|
404
|
!defined $nr and return undef; |
1685
|
212
|
50
|
|
|
|
408
|
!ref $nr and $nr = \$nr; |
1686
|
|
|
|
|
|
|
|
1687
|
212
|
50
|
|
|
|
435
|
$debug and print STDERR " [ checking nr=$$nr ]"; |
1688
|
212
|
100
|
100
|
|
|
3023
|
if (!$self->{reserved_words}->{$$nr} && |
1689
|
|
|
|
|
|
|
$$nr =~ /^%?([&\$]?)(\w+)%?$/) { |
1690
|
42
|
50
|
|
|
|
84
|
$debug and print STDERR "[ $$nr is an identifier:($1,$2) ]"; |
1691
|
42
|
50
|
|
|
|
276
|
wantarray and return ($1,$2); |
1692
|
0
|
|
|
|
|
0
|
return 1; |
1693
|
|
|
|
|
|
|
# } else { |
1694
|
|
|
|
|
|
|
# $debug and print STDERR " [ not identifier ]"; |
1695
|
|
|
|
|
|
|
} |
1696
|
170
|
50
|
|
|
|
4918
|
wantarray and return (); |
1697
|
0
|
|
|
|
|
0
|
return 0; |
1698
|
|
|
|
|
|
|
} |
1699
|
|
|
|
|
|
|
|
1700
|
|
|
|
|
|
|
|
1701
|
|
|
|
|
|
|
=item lex \$src |
1702
|
|
|
|
|
|
|
|
1703
|
|
|
|
|
|
|
Splits the specified source buffer into a series of tokens, returns |
1704
|
|
|
|
|
|
|
a listref to the resulting lexicon. See B for the details. |
1705
|
|
|
|
|
|
|
|
1706
|
|
|
|
|
|
|
=cut |
1707
|
|
|
|
|
|
|
|
1708
|
|
|
|
|
|
|
sub lex { |
1709
|
145
|
|
|
145
|
1
|
703
|
my $self = shift; |
1710
|
145
|
|
50
|
|
|
324
|
my $src = shift || return; |
1711
|
145
|
|
|
|
|
176
|
my ($inlen,$inblock,$pos); |
1712
|
0
|
|
|
|
|
0
|
my ($prior,$opseq,$opcontent); |
1713
|
0
|
|
|
|
|
0
|
my ($itype,$iname); |
1714
|
145
|
|
|
|
|
210
|
my @lexicon = (); |
1715
|
145
|
|
|
|
|
181
|
my $clevel = 0; |
1716
|
|
|
|
|
|
|
|
1717
|
145
|
50
|
|
|
|
1043
|
!ref $src and $src = \$src; |
1718
|
|
|
|
|
|
|
|
1719
|
7
|
|
|
7
|
|
96
|
use re 'taint'; |
|
7
|
|
|
|
|
21
|
|
|
7
|
|
|
|
|
12837
|
|
1720
|
145
|
50
|
|
|
|
611
|
$self->{compatibility_mode_0x} and |
1721
|
|
|
|
|
|
|
$$src = $self->convert_template_0x_2x($$src); |
1722
|
145
|
50
|
|
|
|
340
|
!$$src and return []; |
1723
|
|
|
|
|
|
|
|
1724
|
145
|
|
50
|
|
|
6013
|
$inlen = length($$src) || 0; |
1725
|
145
|
|
|
|
|
194
|
$pos = 0; |
1726
|
145
|
|
|
|
|
9213
|
LEXEME: while ($pos < $inlen) { |
1727
|
230
|
50
|
|
|
|
1130
|
next LEXEME unless $$src =~ m/([^%]*)(%([^%]*)%)?/mg; |
1728
|
230
|
|
|
|
|
340
|
$pos = pos($$src); |
1729
|
230
|
|
100
|
|
|
1533
|
($prior,$opseq,$opcontent) = ($1,$2 || '',$3 || ''); |
|
|
|
100
|
|
|
|
|
1730
|
230
|
100
|
|
|
|
468
|
if ($opseq eq '%%') { |
1731
|
2
|
|
|
|
|
3
|
$prior .= '%'; |
1732
|
2
|
|
|
|
|
3
|
$opseq = ''; |
1733
|
|
|
|
|
|
|
} |
1734
|
|
|
|
|
|
|
|
1735
|
230
|
|
|
|
|
651
|
push @lexicon, [ $clevel, $prior, 0 ]; |
1736
|
230
|
100
|
|
|
|
971
|
next LEXEME unless $opseq; |
1737
|
|
|
|
|
|
|
# if ($opseq =~ /^%(if |elsif |fi%)/) { |
1738
|
|
|
|
|
|
|
# $debug and print STDERR " [ found std. conditional $opseq ]"; |
1739
|
|
|
|
|
|
|
# push @lexicon, [ ++$clevel, $opseq, 1 ]; |
1740
|
|
|
|
|
|
|
# next LEXEME; |
1741
|
|
|
|
|
|
|
# } els |
1742
|
|
|
|
|
|
|
# print STDERR " [opseq=$opseq]"; |
1743
|
212
|
100
|
66
|
|
|
1093
|
if (($itype,$iname) = $self->is_identifier(\$opseq)) { |
|
|
100
|
66
|
|
|
|
|
1744
|
42
|
50
|
|
|
|
79
|
$debug and |
1745
|
|
|
|
|
|
|
print STDERR " [ found identifier $itype,$iname ]"; |
1746
|
42
|
|
|
|
|
122
|
push @lexicon, [ $clevel, $opseq, 2, $itype, $iname ]; |
1747
|
|
|
|
|
|
|
|
1748
|
42
|
|
|
|
|
147
|
next LEXEME; |
1749
|
|
|
|
|
|
|
} elsif (($opcontent) && |
1750
|
|
|
|
|
|
|
($opcontent !~ /^(if\s|elsif\s|fi$|else$)/) && |
1751
|
|
|
|
|
|
|
($opcontent =~ tr/^A-Za-z0-9_/^A-Za-z0-9_/)) { |
1752
|
84
|
50
|
|
|
|
169
|
$debug and |
1753
|
|
|
|
|
|
|
print STDERR " [ found non-conditional operation $opcontent ]"; |
1754
|
84
|
|
|
|
|
244
|
push @lexicon, [ $clevel, $opseq, 6, $opcontent ]; |
1755
|
84
|
|
|
|
|
276
|
next LEXEME; |
1756
|
|
|
|
|
|
|
} |
1757
|
86
|
100
|
|
|
|
207
|
$clevel++ if $opseq =~ /^%if\s/; |
1758
|
86
|
|
|
|
|
205
|
push @lexicon, [ $clevel, $opseq, 1 ]; |
1759
|
86
|
100
|
|
|
|
1255
|
$clevel-- if $opseq eq '%fi%'; |
1760
|
|
|
|
|
|
|
} |
1761
|
145
|
|
|
|
|
372
|
\@lexicon; |
1762
|
|
|
|
|
|
|
} |
1763
|
|
|
|
|
|
|
|
1764
|
|
|
|
|
|
|
=item load_from_file $filename |
1765
|
|
|
|
|
|
|
|
1766
|
|
|
|
|
|
|
Loads a template from the specified file. If use_file_cache is true, |
1767
|
|
|
|
|
|
|
the file will be stored in the file cache (not necessary if caching |
1768
|
|
|
|
|
|
|
is enabled for lexicons). |
1769
|
|
|
|
|
|
|
|
1770
|
|
|
|
|
|
|
This code is very trusting concerning its filename -- the only check |
1771
|
|
|
|
|
|
|
performed is to strip leading <, >, | and + signs to try to ensure that |
1772
|
|
|
|
|
|
|
the filehandle obtained is read-only. Trailing pipes will be left |
1773
|
|
|
|
|
|
|
alone, so that "/path/to/binary|" may use the output from 'binary'. |
1774
|
|
|
|
|
|
|
|
1775
|
|
|
|
|
|
|
=cut |
1776
|
|
|
|
|
|
|
|
1777
|
|
|
|
|
|
|
sub load_from_file { |
1778
|
48
|
|
|
48
|
1
|
59
|
my $self = shift; |
1779
|
48
|
|
50
|
|
|
305
|
my $fn = shift || return undef; |
1780
|
48
|
|
|
|
|
54
|
my ($b,$buf); |
1781
|
|
|
|
|
|
|
|
1782
|
48
|
50
|
33
|
|
|
177
|
if (!$self->{open_tainted_files} && |
1783
|
|
|
|
|
|
|
$self->is_tainted($fn)) { |
1784
|
0
|
|
|
|
|
0
|
print STDERR "Text::BasicTemplate: load_from_file: '$fn' is tainted, can't open safely\n"; |
1785
|
0
|
|
|
|
|
0
|
return undef; |
1786
|
|
|
|
|
|
|
} |
1787
|
48
|
100
|
|
|
|
182
|
$self->{file_cache}{$fn} and return $self->{file_cache}{$fn}; |
1788
|
43
|
|
|
|
|
149
|
$fn =~ s/^[\+<>|]+//; |
1789
|
43
|
|
|
|
|
52
|
$buf = ''; |
1790
|
43
|
50
|
|
|
|
1730
|
sysopen(TMPL,$fn,0) || do { |
1791
|
0
|
0
|
|
|
|
0
|
$debug and print STDERR "Text::BasicTemplate::load_from_file($fn): $!"; |
1792
|
0
|
|
|
|
|
0
|
return undef; |
1793
|
|
|
|
|
|
|
}; |
1794
|
43
|
50
|
|
|
|
311
|
$self->{use_flock} and flock(TMPL,LOCK_SH); |
1795
|
43
|
|
|
|
|
382
|
while (sysread(TMPL,$b,4096)) { |
1796
|
43
|
|
|
|
|
316
|
$buf .= $b; |
1797
|
|
|
|
|
|
|
} |
1798
|
43
|
50
|
|
|
|
252
|
$self->{use_flock} and flock(TMPL,LOCK_UN); |
1799
|
43
|
|
|
|
|
421
|
close(TMPL); |
1800
|
43
|
|
|
|
|
80
|
$buf .= substr($^X,0,0); # deliberately taint the contents |
1801
|
43
|
50
|
|
|
|
213
|
$self->{use_file_cache} and $self->{file_cache}{$fn} = \$buf; |
1802
|
43
|
|
|
|
|
155
|
\$buf; |
1803
|
|
|
|
|
|
|
} |
1804
|
|
|
|
|
|
|
|
1805
|
|
|
|
|
|
|
|
1806
|
|
|
|
|
|
|
## pragma functions |
1807
|
|
|
|
|
|
|
|
1808
|
|
|
|
|
|
|
sub bt_include { |
1809
|
4
|
|
|
4
|
1
|
7
|
my $self = shift; |
1810
|
4
|
|
50
|
|
|
24
|
my $ovr = shift || {}; |
1811
|
4
|
|
|
|
|
9
|
my ($type,$file,$parse) = @_; |
1812
|
4
|
|
|
|
|
4
|
my $buf; |
1813
|
|
|
|
|
|
|
|
1814
|
4
|
50
|
33
|
|
|
32
|
if ($type && !$file) { |
1815
|
0
|
|
|
|
|
0
|
$file = $type; |
1816
|
0
|
|
|
|
|
0
|
$type = 'file'; |
1817
|
|
|
|
|
|
|
} |
1818
|
4
|
|
33
|
|
|
24
|
$parse = !($parse and $parse eq 'noparse'); |
1819
|
|
|
|
|
|
|
|
1820
|
4
|
50
|
33
|
|
|
47
|
$type && $type =~ /^(file|virtual|semisecure)$/ && $file or |
|
|
|
33
|
|
|
|
|
1821
|
|
|
|
|
|
|
return '[format: bt_include([ file | virtual | semisecure ], fn, [ noparse])]'; |
1822
|
4
|
50
|
|
|
|
23
|
if ($type eq 'semisecure') { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1823
|
7
|
|
|
7
|
|
61
|
no re 'taint'; |
|
7
|
|
|
|
|
22
|
|
|
7
|
|
|
|
|
22455
|
|
1824
|
0
|
0
|
|
|
|
0
|
if ($file =~ /^(\w[\w\-.]{0,254})$/) { |
1825
|
0
|
|
|
|
|
0
|
$file = $1; |
1826
|
|
|
|
|
|
|
} else { |
1827
|
0
|
|
|
|
|
0
|
return "[bt_include: File '$file' does not match valid pattern in semisecure mode]"; |
1828
|
|
|
|
|
|
|
} |
1829
|
0
|
0
|
0
|
|
|
0
|
if ($self->is_tainted($file) && |
1830
|
|
|
|
|
|
|
!$self->{bt_include_allow_tainted}) { |
1831
|
0
|
|
|
|
|
0
|
return "[bt_include: semisecure filename $file is tainted, can't include]"; |
1832
|
|
|
|
|
|
|
} |
1833
|
0
|
0
|
|
|
|
0
|
-e $file or return "[bt_include: semisecure file $file does not exist]"; |
1834
|
0
|
0
|
|
|
|
0
|
-f _ or return "[bt_include: semisecure file $file is not a regular file]"; |
1835
|
0
|
0
|
|
|
|
0
|
-r _ or return "[bt_include: semisecure file $file not readable]"; |
1836
|
0
|
0
|
|
|
|
0
|
$parse and return $self->parse($file,$ovr); |
1837
|
0
|
|
|
|
|
0
|
$buf = $self->load_from_file($file); |
1838
|
0
|
|
|
|
|
0
|
print STDERR "[buf=$buf for file=$file]"; |
1839
|
0
|
0
|
|
|
|
0
|
return ((ref $buf eq 'SCALAR') ? $$buf : "[bt_include: load_from_file returned nothing]"); |
1840
|
|
|
|
|
|
|
} elsif ($type eq 'virtual') { |
1841
|
2
|
50
|
33
|
|
|
19
|
unless ($self->{include_document_root} || $ENV{DOCUMENT_ROOT}) { |
1842
|
0
|
|
|
|
|
0
|
return '[bt_include: No document root supplied in virtual mode]'; |
1843
|
|
|
|
|
|
|
} |
1844
|
2
|
50
|
33
|
|
|
8
|
if ($self->is_tainted($file) && |
1845
|
|
|
|
|
|
|
!$self->{bt_include_allow_tainted}) { |
1846
|
0
|
|
|
|
|
0
|
return "[bt_include: virtual filename $file is tainted, can't include]"; |
1847
|
|
|
|
|
|
|
} |
1848
|
2
|
|
33
|
|
|
11
|
$file = ($self->{include_document_root} || $ENV{DOCUMENT_ROOT}) . |
1849
|
|
|
|
|
|
|
'/' . $file; |
1850
|
2
|
50
|
|
|
|
70
|
-e $file or return "[bt_include: virtual file $file does not exist]"; |
1851
|
2
|
50
|
|
|
|
5
|
-f _ or return "[bt_include: virtual file $file is not a regular file]"; |
1852
|
2
|
50
|
|
|
|
10
|
-r _ or return "[bt_include: virtual file $file not readable]"; |
1853
|
2
|
50
|
|
|
|
16
|
$parse and return $self->parse($file,$ovr); |
1854
|
0
|
|
|
|
|
0
|
$buf = $self->load_from_file($file); |
1855
|
0
|
0
|
|
|
|
0
|
return ((ref $buf eq 'SCALAR') ? $$buf : "[bt_include: load_from_file returned nothing]"); |
1856
|
|
|
|
|
|
|
} elsif ($type eq 'file') { |
1857
|
2
|
50
|
33
|
|
|
8
|
if ($self->is_tainted($file) && |
1858
|
|
|
|
|
|
|
!$self->{bt_include_allow_tainted}) { |
1859
|
0
|
|
|
|
|
0
|
return "[bt_include: filename $file is tainted, can't include]"; |
1860
|
|
|
|
|
|
|
} |
1861
|
2
|
50
|
|
|
|
80
|
-e $file or return "[bt_include: file $file does not exist]"; |
1862
|
2
|
50
|
|
|
|
9
|
-f _ or return "[bt_include: file $file is not a regular file]"; |
1863
|
2
|
50
|
|
|
|
12
|
-r _ or return "[bt_include: file $file not readable]"; |
1864
|
2
|
50
|
|
|
|
29
|
$parse and return $self->parse($file,$ovr); |
1865
|
0
|
|
|
|
|
0
|
$buf = $self->load_from_file($file); |
1866
|
0
|
|
|
|
|
0
|
print STDERR "[buf=$buf for file=$file]"; |
1867
|
0
|
0
|
|
|
|
0
|
return ((ref $buf eq 'SCALAR') ? $$buf : "[bt_include: load_from_file returned nothing]"); |
1868
|
|
|
|
|
|
|
} else { |
1869
|
0
|
|
|
|
|
0
|
return "[bt_include: include type '$type' not known]"; |
1870
|
|
|
|
|
|
|
} |
1871
|
|
|
|
|
|
|
} |
1872
|
|
|
|
|
|
|
|
1873
|
|
|
|
|
|
|
=item bt_exec |
1874
|
|
|
|
|
|
|
|
1875
|
|
|
|
|
|
|
=cut |
1876
|
|
|
|
|
|
|
|
1877
|
|
|
|
|
|
|
|
1878
|
|
|
|
|
|
|
sub bt_exec { |
1879
|
1
|
|
|
1
|
1
|
3
|
my $self = shift; |
1880
|
1
|
|
50
|
|
|
8
|
my $ovr = shift || {}; |
1881
|
1
|
|
|
|
|
3
|
my ($type,$command,$parse) = @_; |
1882
|
1
|
|
|
|
|
2
|
my $buf; |
1883
|
|
|
|
|
|
|
|
1884
|
1
|
50
|
33
|
|
|
50
|
$type && $type =~ /^(cmd|cgi)$/ && $command or |
|
|
|
33
|
|
|
|
|
1885
|
|
|
|
|
|
|
return '[format: bt_exec({ cmd | file }, command [, parse ])]'; |
1886
|
1
|
|
50
|
|
|
4
|
$parse ||= 0; |
1887
|
1
|
50
|
|
|
|
5
|
if ($type eq 'cmd') { |
|
|
0
|
|
|
|
|
|
1888
|
1
|
50
|
|
|
|
15944
|
open(IC,$command.'|') || |
1889
|
|
|
|
|
|
|
return "[bt_exec: Couldn't exec $command: $!]"; |
1890
|
1
|
|
|
|
|
64
|
$buf = join(',',); |
1891
|
1
|
|
|
|
|
36
|
close IC; |
1892
|
1
|
50
|
33
|
|
|
36
|
if ($parse && $buf) { |
1893
|
1
|
|
|
|
|
31
|
$buf = $self->parse(\$buf,$ovr); |
1894
|
|
|
|
|
|
|
} |
1895
|
1
|
|
|
|
|
44
|
return $buf; |
1896
|
|
|
|
|
|
|
} elsif ($type eq 'cgi') { |
1897
|
0
|
0
|
|
|
|
0
|
open(IC,$command.'|') || |
1898
|
|
|
|
|
|
|
return "[bt_exec: Couldn't exec $command: $!]"; |
1899
|
0
|
|
|
|
|
0
|
while () { |
1900
|
0
|
|
|
|
|
0
|
chomp; |
1901
|
0
|
0
|
|
|
|
0
|
last if !$_; |
1902
|
|
|
|
|
|
|
} |
1903
|
0
|
|
|
|
|
0
|
$buf = join(',',); |
1904
|
0
|
|
|
|
|
0
|
close IC; |
1905
|
0
|
0
|
0
|
|
|
0
|
if ($parse && $buf) { |
1906
|
0
|
|
|
|
|
0
|
$buf = $self->parse(\$buf,$ovr); |
1907
|
|
|
|
|
|
|
} |
1908
|
0
|
|
|
|
|
0
|
return $buf; |
1909
|
|
|
|
|
|
|
} |
1910
|
|
|
|
|
|
|
} |
1911
|
|
|
|
|
|
|
|
1912
|
|
|
|
|
|
|
=item dump_lexicon \@lexicon [ $start_pos [ $end_pos ] ] |
1913
|
|
|
|
|
|
|
|
1914
|
|
|
|
|
|
|
Returns a dump of the given lexicon. Principally used for debugging the |
1915
|
|
|
|
|
|
|
module, or if you need to optimize templates to save lexical storage. |
1916
|
|
|
|
|
|
|
If $start_pos/$end_pos are given, only that range of the lexical array |
1917
|
|
|
|
|
|
|
is dumped. |
1918
|
|
|
|
|
|
|
|
1919
|
|
|
|
|
|
|
=cut |
1920
|
|
|
|
|
|
|
|
1921
|
|
|
|
|
|
|
sub dump_lexicon { |
1922
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1923
|
0
|
|
|
|
|
0
|
my $L = shift; |
1924
|
0
|
|
|
|
|
0
|
my $l; |
1925
|
0
|
|
|
|
|
0
|
my ($start_pos,$end_pos) = @_; |
1926
|
0
|
|
|
|
|
0
|
my $x; |
1927
|
0
|
|
|
|
|
0
|
my $b = ''; |
1928
|
|
|
|
|
|
|
|
1929
|
|
|
|
|
|
|
|
1930
|
0
|
0
|
|
|
|
0
|
ref $L eq 'ARRAY' or return undef; |
1931
|
0
|
|
0
|
|
|
0
|
for (my $i=$start_pos || 0; $i<=($end_pos || $#{$L}); $i++) { |
|
|
|
0
|
|
|
|
|
1932
|
0
|
|
|
|
|
0
|
$l = $L->[$i]; |
1933
|
0
|
|
|
|
|
0
|
$b .= "[ $i: L$l->[0] $lexeme_types{$l->[2]}"; |
1934
|
0
|
|
|
|
|
0
|
$x = $l->[1]; |
1935
|
0
|
|
|
|
|
0
|
$x =~ s/\n/\\n/g; |
1936
|
0
|
|
|
|
|
0
|
$x =~ s/\t/\\t/g; |
1937
|
0
|
|
|
|
|
0
|
$x =~ s/\r/\\r/g; |
1938
|
0
|
|
|
|
|
0
|
$b .= " '$x'"; |
1939
|
0
|
0
|
|
|
|
0
|
defined $l->[3] and $b .= " '$l->[3]'"; |
1940
|
0
|
0
|
|
|
|
0
|
defined $l->[4] and $b .= " '$l->[4]'"; |
1941
|
0
|
|
|
|
|
0
|
$b .= " ]\n"; |
1942
|
|
|
|
|
|
|
} |
1943
|
0
|
|
|
|
|
0
|
$b; |
1944
|
|
|
|
|
|
|
} |
1945
|
|
|
|
|
|
|
|
1946
|
|
|
|
|
|
|
=item dump_stack \@stack |
1947
|
|
|
|
|
|
|
|
1948
|
|
|
|
|
|
|
Dumps the contents of a conditional-eval stack, which consists of a list of listrefs |
1949
|
|
|
|
|
|
|
containing [ type, value ], type being one of the lexeme_types, value being either |
1950
|
|
|
|
|
|
|
the identififer or an operator, depending on the type. |
1951
|
|
|
|
|
|
|
|
1952
|
|
|
|
|
|
|
=cut |
1953
|
|
|
|
|
|
|
|
1954
|
|
|
|
|
|
|
sub dump_stack { |
1955
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1956
|
0
|
|
|
|
|
0
|
my $sr = shift; |
1957
|
0
|
|
0
|
|
|
0
|
my $terse = shift || 0; |
1958
|
0
|
|
|
|
|
0
|
my $S; |
1959
|
0
|
|
|
|
|
0
|
my $b = ''; |
1960
|
0
|
|
|
|
|
0
|
my $x = 0; |
1961
|
|
|
|
|
|
|
|
1962
|
0
|
0
|
|
|
|
0
|
ref $sr eq 'ARRAY' or return undef; |
1963
|
0
|
|
|
|
|
0
|
for $S (@{$sr}) { |
|
0
|
|
|
|
|
0
|
|
1964
|
0
|
0
|
|
|
|
0
|
if ($terse) { |
1965
|
0
|
0
|
|
|
|
0
|
$b .= ',' if $x++; |
1966
|
0
|
|
|
|
|
0
|
$b .= "$S->[1]"; |
1967
|
|
|
|
|
|
|
} else { |
1968
|
0
|
|
|
|
|
0
|
$b .= "{ $lexeme_types{$S->[0]}, $S->[1] }"; |
1969
|
|
|
|
|
|
|
} |
1970
|
|
|
|
|
|
|
} |
1971
|
0
|
|
|
|
|
0
|
$b; |
1972
|
|
|
|
|
|
|
} |
1973
|
|
|
|
|
|
|
|
1974
|
|
|
|
|
|
|
=item list_lexicon_cache |
1975
|
|
|
|
|
|
|
|
1976
|
|
|
|
|
|
|
Lists the lexicons cached for files/scalars/etc. |
1977
|
|
|
|
|
|
|
|
1978
|
|
|
|
|
|
|
=cut |
1979
|
|
|
|
|
|
|
|
1980
|
|
|
|
|
|
|
sub list_lexicon_cache { |
1981
|
1
|
|
|
1
|
1
|
20
|
my $self = shift; |
1982
|
|
|
|
|
|
|
|
1983
|
1
|
|
|
|
|
1
|
keys %{$self->{lexicon_cache}}; |
|
1
|
|
|
|
|
4
|
|
1984
|
|
|
|
|
|
|
} |
1985
|
|
|
|
|
|
|
|
1986
|
|
|
|
|
|
|
=item list_file_cache |
1987
|
|
|
|
|
|
|
|
1988
|
|
|
|
|
|
|
Lists the files cached in the file cache. Empty unless use_file_cache is |
1989
|
|
|
|
|
|
|
true. |
1990
|
|
|
|
|
|
|
|
1991
|
|
|
|
|
|
|
=cut |
1992
|
|
|
|
|
|
|
|
1993
|
|
|
|
|
|
|
sub list_file_cache { |
1994
|
0
|
|
|
0
|
1
|
0
|
keys %{$_[0]->{file_cache}}; |
|
0
|
|
|
|
|
0
|
|
1995
|
|
|
|
|
|
|
} |
1996
|
|
|
|
|
|
|
|
1997
|
|
|
|
|
|
|
=item list_cond2rpn_cache |
1998
|
|
|
|
|
|
|
|
1999
|
|
|
|
|
|
|
Lists the conditional-to-RPN conversion cache. Empty if B |
2000
|
|
|
|
|
|
|
is false. |
2001
|
|
|
|
|
|
|
|
2002
|
|
|
|
|
|
|
=cut |
2003
|
|
|
|
|
|
|
|
2004
|
|
|
|
|
|
|
sub list_cond2rpn_cache { |
2005
|
0
|
|
|
0
|
1
|
0
|
keys %{$_[0]->{cond2rpn_cache}}; |
|
0
|
|
|
|
|
0
|
|
2006
|
|
|
|
|
|
|
} |
2007
|
|
|
|
|
|
|
|
2008
|
|
|
|
|
|
|
=item list_fullcond_cache |
2009
|
|
|
|
|
|
|
|
2010
|
|
|
|
|
|
|
Lists the contents of the conditional evaluation cache. Empty unless |
2011
|
|
|
|
|
|
|
B is set true. |
2012
|
|
|
|
|
|
|
|
2013
|
|
|
|
|
|
|
=cut |
2014
|
|
|
|
|
|
|
|
2015
|
|
|
|
|
|
|
sub list_fullcond_cache { |
2016
|
0
|
|
|
0
|
1
|
0
|
keys %{$_[0]->{fullcond_cache}}; |
|
0
|
|
|
|
|
0
|
|
2017
|
|
|
|
|
|
|
} |
2018
|
|
|
|
|
|
|
|
2019
|
|
|
|
|
|
|
=item taint_enabled |
2020
|
|
|
|
|
|
|
|
2021
|
|
|
|
|
|
|
Tries to work out if taint checking is enabled, so that the right things |
2022
|
|
|
|
|
|
|
can be enabled/disabled by new(). |
2023
|
|
|
|
|
|
|
|
2024
|
|
|
|
|
|
|
=cut |
2025
|
|
|
|
|
|
|
|
2026
|
|
|
|
|
|
|
sub taint_enabled { |
2027
|
7
|
|
|
7
|
1
|
16
|
return not eval { my $x = $^X, kill 0; $x }; |
|
7
|
|
|
|
|
84
|
|
|
7
|
|
|
|
|
35
|
|
2028
|
|
|
|
|
|
|
} |
2029
|
|
|
|
|
|
|
|
2030
|
|
|
|
|
|
|
=item is_tainted SCALAR |
2031
|
|
|
|
|
|
|
|
2032
|
|
|
|
|
|
|
Returns true if taint checking is enabled and the specified |
2033
|
|
|
|
|
|
|
variable is tainted. |
2034
|
|
|
|
|
|
|
|
2035
|
|
|
|
|
|
|
=cut |
2036
|
|
|
|
|
|
|
|
2037
|
|
|
|
|
|
|
sub is_tainted { |
2038
|
52
|
50
|
|
52
|
1
|
139
|
return undef unless defined $_[1]; |
2039
|
52
|
|
|
|
|
111
|
return not eval { my $x = $_[1], kill 0; $x }; |
|
52
|
|
|
|
|
167
|
|
|
52
|
|
|
|
|
244
|
|
2040
|
|
|
|
|
|
|
} |
2041
|
|
|
|
|
|
|
|
2042
|
|
|
|
|
|
|
|
2043
|
|
|
|
|
|
|
=item debug DEBUGLEVEL |
2044
|
|
|
|
|
|
|
|
2045
|
|
|
|
|
|
|
Activates debugging output. |
2046
|
|
|
|
|
|
|
|
2047
|
|
|
|
|
|
|
=cut |
2048
|
|
|
|
|
|
|
|
2049
|
|
|
|
|
|
|
sub debug { |
2050
|
0
|
|
|
0
|
1
|
0
|
shift; |
2051
|
0
|
|
|
|
|
0
|
$debug = shift; |
2052
|
|
|
|
|
|
|
} |
2053
|
|
|
|
|
|
|
|
2054
|
|
|
|
|
|
|
=item purge_lexicon_cache |
2055
|
|
|
|
|
|
|
|
2056
|
|
|
|
|
|
|
=item purge_cond2rpn_cache |
2057
|
|
|
|
|
|
|
|
2058
|
|
|
|
|
|
|
=item purge_fullcond_cache |
2059
|
|
|
|
|
|
|
|
2060
|
|
|
|
|
|
|
=item purge_file_cache |
2061
|
|
|
|
|
|
|
|
2062
|
|
|
|
|
|
|
Purges the given cache. |
2063
|
|
|
|
|
|
|
|
2064
|
|
|
|
|
|
|
=cut |
2065
|
|
|
|
|
|
|
|
2066
|
2
|
|
|
2
|
1
|
7
|
sub purge_lexicon_cache { $_[0]->{lexicon_cache} = (); } |
2067
|
2
|
|
|
2
|
1
|
6
|
sub purge_cond2rpn_cache { $_[0]->{cond2rpn_cache} = (); } |
2068
|
147
|
|
|
147
|
1
|
426
|
sub purge_fullcond_cache { $_[0]->{fullcond_cache} = (); } |
2069
|
2
|
|
|
2
|
1
|
6
|
sub purge_file_cache { $_[0]->{file_cache} = (); } |
2070
|
|
|
|
|
|
|
|
2071
|
|
|
|
|
|
|
|
2072
|
|
|
|
|
|
|
## backwards-compatibility functions |
2073
|
|
|
|
|
|
|
|
2074
|
|
|
|
|
|
|
|
2075
|
|
|
|
|
|
|
=item list_cache |
2076
|
|
|
|
|
|
|
|
2077
|
|
|
|
|
|
|
Compatibility function for BasicTemplate 0.x; synonym for B |
2078
|
|
|
|
|
|
|
|
2079
|
|
|
|
|
|
|
=cut |
2080
|
|
|
|
|
|
|
|
2081
|
0
|
|
|
0
|
1
|
0
|
sub list_cache { $_[0]->list_lexicon_cache }; |
2082
|
|
|
|
|
|
|
|
2083
|
|
|
|
|
|
|
|
2084
|
|
|
|
|
|
|
=item push, parse_push |
2085
|
|
|
|
|
|
|
|
2086
|
|
|
|
|
|
|
Compatibility functions for BasicTemplate 0.x; synonym for B. |
2087
|
|
|
|
|
|
|
|
2088
|
|
|
|
|
|
|
=cut |
2089
|
|
|
|
|
|
|
|
2090
|
7
|
|
|
7
|
1
|
652
|
sub push { my $self = shift; $self->parse(@_) }; |
|
7
|
|
|
|
|
21
|
|
2091
|
0
|
|
|
0
|
1
|
0
|
sub parse_push { my $self = shift; $self->parse(@_) }; |
|
0
|
|
|
|
|
0
|
|
2092
|
|
|
|
|
|
|
|
2093
|
|
|
|
|
|
|
=item print, parse_print |
2094
|
|
|
|
|
|
|
|
2095
|
|
|
|
|
|
|
Compatibility functions for BasicTempltae 0.x |
2096
|
|
|
|
|
|
|
|
2097
|
|
|
|
|
|
|
=cut |
2098
|
|
|
|
|
|
|
|
2099
|
0
|
|
|
0
|
1
|
0
|
sub print { my $self = shift; print $self->parse(@_); }; |
|
0
|
|
|
|
|
0
|
|
2100
|
0
|
|
|
0
|
1
|
0
|
sub parse_print { my $self = shift; print $self->parse(@_); }; |
|
0
|
|
|
|
|
0
|
|
2101
|
|
|
|
|
|
|
|
2102
|
|
|
|
|
|
|
=item purge_cache |
2103
|
|
|
|
|
|
|
|
2104
|
|
|
|
|
|
|
Compatibility function for BasicTemplate 0.x; purges all |
2105
|
|
|
|
|
|
|
applicable caches. |
2106
|
|
|
|
|
|
|
|
2107
|
|
|
|
|
|
|
=cut |
2108
|
|
|
|
|
|
|
|
2109
|
|
|
|
|
|
|
sub purge_cache { |
2110
|
2
|
|
|
2
|
1
|
728
|
$_[0]->purge_lexicon_cache; |
2111
|
2
|
|
|
|
|
10
|
$_[0]->purge_cond2rpn_cache; |
2112
|
2
|
|
|
|
|
11
|
$_[0]->purge_fullcond_cache; |
2113
|
2
|
|
|
|
|
42
|
$_[0]->purge_file_cache; |
2114
|
2
|
|
|
|
|
8
|
1; |
2115
|
|
|
|
|
|
|
} |
2116
|
|
|
|
|
|
|
|
2117
|
|
|
|
|
|
|
=item uncache FILE |
2118
|
|
|
|
|
|
|
|
2119
|
|
|
|
|
|
|
Compatibility function for BasicTemplate 0.x; purges the |
2120
|
|
|
|
|
|
|
specified file from the file and lexicon caches. |
2121
|
|
|
|
|
|
|
|
2122
|
|
|
|
|
|
|
=cut |
2123
|
|
|
|
|
|
|
|
2124
|
|
|
|
|
|
|
sub uncache { |
2125
|
0
|
|
|
0
|
1
|
0
|
$_[0]->purge_lexicon_cache($_[1]); |
2126
|
0
|
|
|
|
|
0
|
$_[0]->purge_file_cache($_[1]); |
2127
|
|
|
|
|
|
|
} |
2128
|
|
|
|
|
|
|
|
2129
|
|
|
|
|
|
|
=item convert_template_0x_2x $buffer |
2130
|
|
|
|
|
|
|
|
2131
|
|
|
|
|
|
|
Backwards-compatibility function for BasicTemplate 0.x; converts a |
2132
|
|
|
|
|
|
|
template constructed for v0.x to v2.x. Used internally for conversions |
2133
|
|
|
|
|
|
|
on-the-fly in backwards-compatible mode. |
2134
|
|
|
|
|
|
|
|
2135
|
|
|
|
|
|
|
Note that this method will have no effect unless the 0.x template |
2136
|
|
|
|
|
|
|
contains conditionals -- simple %key% substitutions are the same in |
2137
|
|
|
|
|
|
|
both versions. |
2138
|
|
|
|
|
|
|
|
2139
|
|
|
|
|
|
|
=cut |
2140
|
|
|
|
|
|
|
|
2141
|
|
|
|
|
|
|
sub convert_template_0x_2x { |
2142
|
145
|
|
|
145
|
1
|
182
|
my $self = shift; |
2143
|
145
|
|
50
|
|
|
368
|
my $buf = shift || return undef; |
2144
|
145
|
|
|
|
|
191
|
my ($lvalue,$operator,$operand,$aoperand, |
2145
|
|
|
|
|
|
|
$aoperator,$truesub,$atruesub, |
2146
|
|
|
|
|
|
|
$falsesub,$afalsesub); |
2147
|
|
|
|
|
|
|
|
2148
|
145
|
50
|
|
|
|
311
|
ref $buf eq 'SCALAR' and $buf = $$buf; |
2149
|
145
|
50
|
|
|
|
266
|
!$buf and return ''; |
2150
|
|
|
|
|
|
|
|
2151
|
7
|
|
|
7
|
|
69
|
use re 'taint'; |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
6034
|
|
2152
|
|
|
|
|
|
|
|
2153
|
|
|
|
|
|
|
# print STDERR "Pbuf=$buf\n"; |
2154
|
|
|
|
|
|
|
# $buf =~ s/([^%])%([^%\w\s?!])/$1%%$2/g; |
2155
|
|
|
|
|
|
|
|
2156
|
|
|
|
|
|
|
# |
2157
|
|
|
|
|
|
|
|
2158
|
|
|
|
|
|
|
# does it have anything that looks 2.0-ish in it? |
2159
|
145
|
100
|
|
|
|
929
|
$buf =~ m/(%if\s+[^%]+%|%&\w+\([^\)]*\)%)/gm and do { |
2160
|
|
|
|
|
|
|
# warn "convert_template_0x_2x(): matched $1, assuming new template"; |
2161
|
33
|
|
|
|
|
124
|
return $buf; |
2162
|
|
|
|
|
|
|
}; |
2163
|
|
|
|
|
|
|
|
2164
|
|
|
|
|
|
|
# does it use 0.x-style conditionals? |
2165
|
112
|
100
|
|
|
|
594
|
$buf =~ m/%\?|/i) { |
2170
|
|
|
|
|
|
|
# ($itype,$ifn) = (lc $1,$2); |
2171
|
|
|
|
|
|
|
# # more horrible hack -- parses %key% in the filename (-ian) |
2172
|
|
|
|
|
|
|
# while ($itype =~ /%(.*?)%/g) { |
2173
|
|
|
|
|
|
|
# $self->{compat_0x_ovr} and |
2174
|
|
|
|
|
|
|
# defined $self->{compat_0x_ovr}->{$1} and |
2175
|
|
|
|
|
|
|
# $itype =~ s/\Q$1\E/$self->{compat_0x_ovr}->{$1}; |
2176
|
|
|
|
|
|
|
# } |
2177
|
|
|
|
|
|
|
# } |
2178
|
|
|
|
|
|
|
|
2179
|
|
|
|
|
|
|
# without the horrible hack: |
2180
|
10
|
|
|
|
|
63
|
$buf =~ s//%&bt_include($1,$2)%/g; |
2181
|
|
|
|
|
|
|
|
2182
|
|
|
|
|
|
|
# print STDERR "3buf=[$buf]\n"; |
2183
|
|
|
|
|
|
|
|
2184
|
10
|
|
|
|
|
58
|
while ($buf =~ m/%\?([\w\.\-]+)\s*(==?|!=)\s*([^%]*)%([^%]*)%([^%]*)%/gm) { |
2185
|
8
|
|
|
|
|
30
|
($lvalue,$operator,$operand,$truesub,$falsesub) = |
2186
|
|
|
|
|
|
|
($1,$2,$3,$4,$5); |
2187
|
8
|
|
|
|
|
14
|
($atruesub,$afalsesub) = ($truesub,$falsesub); |
2188
|
8
|
50
|
|
|
|
16
|
if ($operand =~ /^{(\w+)}$/) { |
2189
|
0
|
|
|
|
|
0
|
$aoperand = $1; |
2190
|
|
|
|
|
|
|
} else { |
2191
|
8
|
|
|
|
|
16
|
$aoperand = "\"$operand\""; |
2192
|
|
|
|
|
|
|
} |
2193
|
8
|
50
|
|
|
|
15
|
$aoperator = ($operator eq '!=') ? ' ne ' : ' eq '; |
2194
|
|
|
|
|
|
|
# $operand =~ s/^{(\w+)}$/$1/g; |
2195
|
8
|
|
|
|
|
14
|
$atruesub =~ s/{(\w+)}/%$1%/g; |
2196
|
8
|
|
|
|
|
16
|
$afalsesub =~ s/{(\w+)}/%$1%/g; |
2197
|
|
|
|
|
|
|
|
2198
|
|
|
|
|
|
|
# print STDERR "lvalue=$lvalue operator=$operator operand=$operand truesub=$truesub falsesub=$falsesub\n"; |
2199
|
|
|
|
|
|
|
|
2200
|
|
|
|
|
|
|
# print STDERR "$buf =~ s/%\?\s*$lvalue\s*$operator\s*$operand%$truesub%$falsesub%/%if $lvalue$operator$operand%$truesub%else%$falsesub%fi%/xg;\n"; |
2201
|
|
|
|
|
|
|
|
2202
|
8
|
|
|
|
|
272
|
$buf =~ s/%\?\s*\Q$lvalue\E\s*\Q$operator\E\s*\Q$operand\E\s*%\Q$truesub%$falsesub%\E/%if $lvalue$aoperator$aoperand%$atruesub%else%$afalsesub%fi%/gm; |
2203
|
|
|
|
|
|
|
} |
2204
|
|
|
|
|
|
|
|
2205
|
|
|
|
|
|
|
# $buf =~ s/([^%]|^)%([,.\'\"<>\[\]{}()@\#\$\^&*])(?!bt_)/$1%%$2/g; |
2206
|
|
|
|
|
|
|
# $buf =~ s/([ =\"]\d+)%([,.\'\"<>\[\]{}()@\#\$\^&*])(?!bt_)/$1%%$2/g; |
2207
|
|
|
|
|
|
|
# print STDERR "backconvert[$buf]"; |
2208
|
10
|
|
|
|
|
29
|
$buf; |
2209
|
|
|
|
|
|
|
} |
2210
|
|
|
|
|
|
|
|
2211
|
|
|
|
|
|
|
1; |
2212
|
|
|
|
|
|
|
|
2213
|
|
|
|
|
|
|
__END__ |