| 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__ |