html-template-pro 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.autotest +9 -0
- data/ARTISTIC +131 -0
- data/History.txt +4 -0
- data/LGPL +504 -0
- data/Manifest.txt +221 -0
- data/README.rdoc +52 -0
- data/Rakefile +18 -0
- data/benchmark.rb +136 -0
- data/config/website.yml +2 -0
- data/ext/html/template/internal/Pro.xs +679 -0
- data/ext/html/template/internal/builtin_findfile.inc +361 -0
- data/ext/html/template/internal/calc.h +26 -0
- data/ext/html/template/internal/calc.inc +120 -0
- data/ext/html/template/internal/callback_stubs.inc +63 -0
- data/ext/html/template/internal/expr.c +2267 -0
- data/ext/html/template/internal/expr.y +476 -0
- data/ext/html/template/internal/expr_iface.c +94 -0
- data/ext/html/template/internal/exprpstr.h +36 -0
- data/ext/html/template/internal/exprpstr.inc +144 -0
- data/ext/html/template/internal/exprtool.h +99 -0
- data/ext/html/template/internal/exprtool.inc +289 -0
- data/ext/html/template/internal/exprtype.h +62 -0
- data/ext/html/template/internal/exprval.h +30 -0
- data/ext/html/template/internal/extconf.rb +6 -0
- data/ext/html/template/internal/internal.c +449 -0
- data/ext/html/template/internal/loadfile.h +11 -0
- data/ext/html/template/internal/loadfile.inc +171 -0
- data/ext/html/template/internal/pabidecl.h +54 -0
- data/ext/html/template/internal/pabstract.h +426 -0
- data/ext/html/template/internal/parse_expr.h +15 -0
- data/ext/html/template/internal/pbuffer.c +76 -0
- data/ext/html/template/internal/pbuffer.h +31 -0
- data/ext/html/template/internal/pmiscdef.h +54 -0
- data/ext/html/template/internal/pparam.h +101 -0
- data/ext/html/template/internal/ppport.h +1098 -0
- data/ext/html/template/internal/procore.c +1189 -0
- data/ext/html/template/internal/procore.h +18 -0
- data/ext/html/template/internal/proparam.c +443 -0
- data/ext/html/template/internal/proparam.h +571 -0
- data/ext/html/template/internal/proscope.h +32 -0
- data/ext/html/template/internal/proscope.inc +107 -0
- data/ext/html/template/internal/prostate.h +49 -0
- data/ext/html/template/internal/prostate.inc +24 -0
- data/ext/html/template/internal/provalue.h +14 -0
- data/ext/html/template/internal/pstring.h +60 -0
- data/ext/html/template/internal/pstrutils.h +25 -0
- data/ext/html/template/internal/pstrutils.inc +150 -0
- data/ext/html/template/internal/tagstack.h +30 -0
- data/ext/html/template/internal/tagstack.inc +65 -0
- data/ext/html/template/internal/tmpllog.c +62 -0
- data/ext/html/template/internal/tmpllog.h +27 -0
- data/ext/html/template/internal/tmplpro.h +218 -0
- data/ext/html/template/internal/tmplpro_version.c +35 -0
- data/lib/html/template/pro.rb +225 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +71 -0
- data/tasks/extconf.rake +13 -0
- data/tasks/extconf/tmplpro.rake +43 -0
- data/templates-Pro/a.incl +1 -0
- data/templates-Pro/empty.incl +0 -0
- data/templates-Pro/include/1/a.incl +1 -0
- data/templates-Pro/include/2.out +3 -0
- data/templates-Pro/include/2.tmpl +1 -0
- data/templates-Pro/include/2/a.incl +1 -0
- data/templates-Pro/include/3.tmpl +1 -0
- data/templates-Pro/include/4.tmpl +1 -0
- data/templates-Pro/include/a.incl +1 -0
- data/templates-Pro/test_broken.tmpl +25 -0
- data/templates-Pro/test_broken1.out +1 -0
- data/templates-Pro/test_broken1.tmpl +1 -0
- data/templates-Pro/test_esc1.out +4 -0
- data/templates-Pro/test_esc1.tmpl +4 -0
- data/templates-Pro/test_esc2.out +5 -0
- data/templates-Pro/test_esc2.tmpl +6 -0
- data/templates-Pro/test_esc3.out +4 -0
- data/templates-Pro/test_esc3.tmpl +4 -0
- data/templates-Pro/test_esc4.out +3 -0
- data/templates-Pro/test_esc4.tmpl +4 -0
- data/templates-Pro/test_expr1.out +26 -0
- data/templates-Pro/test_expr1.tmpl +26 -0
- data/templates-Pro/test_expr2.out +34 -0
- data/templates-Pro/test_expr2.tmpl +34 -0
- data/templates-Pro/test_expr3.out +6 -0
- data/templates-Pro/test_expr3.tmpl +6 -0
- data/templates-Pro/test_expr4.out +4 -0
- data/templates-Pro/test_expr4.tmpl +4 -0
- data/templates-Pro/test_expr5.out +18 -0
- data/templates-Pro/test_expr5.tmpl +18 -0
- data/templates-Pro/test_expr6.out +18 -0
- data/templates-Pro/test_expr6.tmpl +18 -0
- data/templates-Pro/test_expr7.out +44 -0
- data/templates-Pro/test_expr7.tmpl +20 -0
- data/templates-Pro/test_expr8.out +15 -0
- data/templates-Pro/test_expr8.tmpl +15 -0
- data/templates-Pro/test_if1.out +25 -0
- data/templates-Pro/test_if1.tmpl +28 -0
- data/templates-Pro/test_if2.out +17 -0
- data/templates-Pro/test_if2.tmpl +25 -0
- data/templates-Pro/test_if3.out +12 -0
- data/templates-Pro/test_if3.tmpl +14 -0
- data/templates-Pro/test_if4.out +15 -0
- data/templates-Pro/test_if4.tmpl +31 -0
- data/templates-Pro/test_if5.out +16 -0
- data/templates-Pro/test_if5.tmpl +16 -0
- data/templates-Pro/test_if6.out +15 -0
- data/templates-Pro/test_if6.tmpl +31 -0
- data/templates-Pro/test_if7.out +14 -0
- data/templates-Pro/test_if7.tmpl +18 -0
- data/templates-Pro/test_include1.out +23 -0
- data/templates-Pro/test_include1.tmpl +7 -0
- data/templates-Pro/test_include2.out +120 -0
- data/templates-Pro/test_include2.tmpl +10 -0
- data/templates-Pro/test_include3.out +8 -0
- data/templates-Pro/test_include3.tmpl +8 -0
- data/templates-Pro/test_include4.out +7 -0
- data/templates-Pro/test_include4.tmpl +6 -0
- data/templates-Pro/test_include5.out +7 -0
- data/templates-Pro/test_include5.tmpl +6 -0
- data/templates-Pro/test_loop1.erb +17 -0
- data/templates-Pro/test_loop1.out +12 -0
- data/templates-Pro/test_loop1.tmpl +16 -0
- data/templates-Pro/test_loop2.erb +19 -0
- data/templates-Pro/test_loop2.out +40 -0
- data/templates-Pro/test_loop2.tmpl +19 -0
- data/templates-Pro/test_loop3.out +38 -0
- data/templates-Pro/test_loop3.tmpl +40 -0
- data/templates-Pro/test_loop4.out +44 -0
- data/templates-Pro/test_loop4.tmpl +20 -0
- data/templates-Pro/test_loop5.out +9 -0
- data/templates-Pro/test_loop5.tmpl +11 -0
- data/templates-Pro/test_loop6.out +33 -0
- data/templates-Pro/test_loop6.tmpl +15 -0
- data/templates-Pro/test_malloc.tmpl +1 -0
- data/templates-Pro/test_userfunc1.out +14 -0
- data/templates-Pro/test_userfunc1.tmpl +14 -0
- data/templates-Pro/test_userfunc2.out +35 -0
- data/templates-Pro/test_userfunc2.tmpl +5 -0
- data/templates-Pro/test_userfunc3.out +5 -0
- data/templates-Pro/test_userfunc3.tmpl +5 -0
- data/templates-Pro/test_userfunc4.out +10 -0
- data/templates-Pro/test_userfunc4.tmpl +10 -0
- data/templates-Pro/test_userfunc5.out +4 -0
- data/templates-Pro/test_userfunc5.tmpl +4 -0
- data/templates-Pro/test_userfunc6.out +4 -0
- data/templates-Pro/test_userfunc6.tmpl +4 -0
- data/templates-Pro/test_var1.erb +23 -0
- data/templates-Pro/test_var1.out +20 -0
- data/templates-Pro/test_var1.tmpl +23 -0
- data/templates-Pro/test_var2.erb +7 -0
- data/templates-Pro/test_var2.out +6 -0
- data/templates-Pro/test_var2.tmpl +7 -0
- data/templates-Pro/test_var3.out +14 -0
- data/templates-Pro/test_var3.tmpl +16 -0
- data/templates/case_loop.tmpl +3 -0
- data/templates/context.tmpl +3 -0
- data/templates/counter.tmpl +2 -0
- data/templates/default.tmpl +1 -0
- data/templates/default_escape.tmpl +4 -0
- data/templates/double_loop.tmpl +7 -0
- data/templates/escape.tmpl +5 -0
- data/templates/global-loops.tmpl +9 -0
- data/templates/globals.tmpl +11 -0
- data/templates/if.tmpl +7 -0
- data/templates/ifelse.tmpl +6 -0
- data/templates/include.tmpl +14 -0
- data/templates/include_path/a.tmpl +2 -0
- data/templates/include_path/b.tmpl +1 -0
- data/templates/include_path/inner.tmpl +1 -0
- data/templates/include_path/one.tmpl +2 -0
- data/templates/include_path2/inner.tmpl +1 -0
- data/templates/included.tmpl +4 -0
- data/templates/included2.tmpl +3 -0
- data/templates/js.tmpl +1 -0
- data/templates/long_loops.tmpl +307 -0
- data/templates/loop-context.tmpl +2 -0
- data/templates/loop-if.tmpl +9 -0
- data/templates/medium.tmpl +217 -0
- data/templates/multiline_tags.tmpl +7 -0
- data/templates/newline_test1.tmpl +1 -0
- data/templates/newline_test2.tmpl +1 -0
- data/templates/other-loop.tmpl +7 -0
- data/templates/outer.tmpl +3 -0
- data/templates/query-test.tmpl +21 -0
- data/templates/query-test2.tmpl +12 -0
- data/templates/recursive.tmpl +2 -0
- data/templates/searchpath/included.tmpl +4 -0
- data/templates/searchpath/three.tmpl +1 -0
- data/templates/searchpath/two.tmpl +2 -0
- data/templates/simple-loop-nonames.tmpl +13 -0
- data/templates/simple-loop.tmpl +12 -0
- data/templates/simple.tmpl +9 -0
- data/templates/unless.tmpl +5 -0
- data/templates/urlescape.tmpl +3 -0
- data/templates/vanguard1.tmpl +2 -0
- data/templates/vanguard2.tmpl +3 -0
- data/test/templates/complex.tmpl +24 -0
- data/test/templates/foo.tmpl +6 -0
- data/test/templates/func.tmpl +2 -0
- data/test/templates/loop.tmpl +14 -0
- data/test/templates/negative.tmpl +1 -0
- data/test/templates/numerics.tmpl +6 -0
- data/test/templates/register.tmpl +2 -0
- data/test/test_basic.rb +23 -0
- data/test/test_coderefs.rb +16 -0
- data/test/test_complex.rb +106 -0
- data/test/test_helper.rb +3 -0
- data/test/test_html_template.rb +583 -0
- data/test/test_html_template_internal_extn.rb +10 -0
- data/test/test_html_template_pro.rb +177 -0
- data/test/test_path_like_variable_scope.rb +59 -0
- data/test/test_random.rb +21 -0
- data/test/test_realloc.rb +16 -0
- data/test/test_register.rb +25 -0
- data/test/test_tmplpro.rb +9 -0
- data/test/tests.rb +9 -0
- data/website/index.txt +57 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +159 -0
- data/website/template.html.erb +50 -0
- metadata +303 -0
|
@@ -0,0 +1,1189 @@
|
|
|
1
|
+
#include <stdio.h>
|
|
2
|
+
#include <stdlib.h>
|
|
3
|
+
#include <string.h>
|
|
4
|
+
#include <ctype.h>
|
|
5
|
+
|
|
6
|
+
#include "tmplpro.h"
|
|
7
|
+
#include "procore.h"
|
|
8
|
+
#include "prostate.h"
|
|
9
|
+
#include "provalue.h"
|
|
10
|
+
#include "tagstack.h"
|
|
11
|
+
#include "pbuffer.h"
|
|
12
|
+
#include "parse_expr.h"
|
|
13
|
+
#include "pparam.h"
|
|
14
|
+
#include "proscope.h"
|
|
15
|
+
#include "proscope.inc"
|
|
16
|
+
#include "pstrutils.inc"
|
|
17
|
+
#include "pmiscdef.h" /*for snprintf */
|
|
18
|
+
/* for mmap_load_file & mmap_unload_file */
|
|
19
|
+
#include "loadfile.inc"
|
|
20
|
+
|
|
21
|
+
#define HTML_TEMPLATE_NO_TAG -1
|
|
22
|
+
#define HTML_TEMPLATE_BAD_TAG 0
|
|
23
|
+
#define HTML_TEMPLATE_FIRST_TAG_USED 1
|
|
24
|
+
#define HTML_TEMPLATE_TAG_VAR 1
|
|
25
|
+
#define HTML_TEMPLATE_TAG_INCLUDE 2
|
|
26
|
+
#define HTML_TEMPLATE_TAG_LOOP 3
|
|
27
|
+
#define HTML_TEMPLATE_TAG_IF 4
|
|
28
|
+
#define HTML_TEMPLATE_TAG_ELSE 5
|
|
29
|
+
#define HTML_TEMPLATE_TAG_UNLESS 6
|
|
30
|
+
#define HTML_TEMPLATE_TAG_ELSIF 7
|
|
31
|
+
#define HTML_TEMPLATE_LAST_TAG_USED 7
|
|
32
|
+
|
|
33
|
+
static
|
|
34
|
+
const char* const tagname[]={
|
|
35
|
+
"Bad or unsupported tag", /* 0 */
|
|
36
|
+
"var", "include", "loop", "if", "else", "unless", "elsif"
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
static
|
|
40
|
+
const char* const TAGNAME[]={
|
|
41
|
+
"Bad or unsupported tag", /* 0 */
|
|
42
|
+
"VAR", "INCLUDE", "LOOP", "IF", "ELSE", "UNLESS", "ELSIF"
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/* max offset to ensure we are not out of file when try <!--/ */
|
|
46
|
+
#define TAG_WIDTH_OFFSET 4
|
|
47
|
+
|
|
48
|
+
static int debuglevel=0;
|
|
49
|
+
|
|
50
|
+
#include "prostate.inc"
|
|
51
|
+
|
|
52
|
+
static
|
|
53
|
+
const char* const innerloopname[]={
|
|
54
|
+
"", "first__", "last__", "inner__", "odd__", "counter__"
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
static
|
|
58
|
+
const char* const INNERLOOPNAME[]={
|
|
59
|
+
"", "FIRST__", "LAST__", "INNER__", "ODD__", "COUNTER__"
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
#define HTML_TEMPLATE_INNER_LOOP_VAR_FIRST 1
|
|
63
|
+
#define HTML_TEMPLATE_INNER_LOOP_VAR_LAST 2
|
|
64
|
+
#define HTML_TEMPLATE_INNER_LOOP_VAR_INNER 3
|
|
65
|
+
#define HTML_TEMPLATE_INNER_LOOP_VAR_ODD 4
|
|
66
|
+
#define HTML_TEMPLATE_INNER_LOOP_VAR_COUNTER 5
|
|
67
|
+
|
|
68
|
+
#define HTML_TEMPLATE_FIRST_INNER_LOOP 1
|
|
69
|
+
#define HTML_TEMPLATE_LAST_INNER_LOOP 5
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
static
|
|
73
|
+
int
|
|
74
|
+
try_inner_loop_variable (PSTRING name)
|
|
75
|
+
{
|
|
76
|
+
int i;
|
|
77
|
+
const char* cur_pos;
|
|
78
|
+
const char* pattern;
|
|
79
|
+
const char* PATTERN;
|
|
80
|
+
for (i=HTML_TEMPLATE_FIRST_INNER_LOOP; i<=HTML_TEMPLATE_LAST_INNER_LOOP; i++) {
|
|
81
|
+
cur_pos=name.begin;
|
|
82
|
+
pattern=innerloopname[i];
|
|
83
|
+
PATTERN=INNERLOOPNAME[i];
|
|
84
|
+
while (*pattern && cur_pos<name.endnext) {
|
|
85
|
+
if (*pattern == *cur_pos || *PATTERN == *cur_pos) {
|
|
86
|
+
pattern++;
|
|
87
|
+
PATTERN++;
|
|
88
|
+
cur_pos++;
|
|
89
|
+
} else {
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (cur_pos==name.endnext) {
|
|
94
|
+
return i;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static
|
|
101
|
+
PSTRING
|
|
102
|
+
get_loop_context_vars_value (struct tmplpro_param *param, PSTRING name) {
|
|
103
|
+
static char* FalseString="0";
|
|
104
|
+
static char* TrueString ="1";
|
|
105
|
+
static char buffer[20]; /* for snprintf %d */
|
|
106
|
+
int loop;
|
|
107
|
+
PSTRING retval={NULL,NULL};
|
|
108
|
+
struct ProScopeEntry* currentScope = getCurrentScope(¶m->var_scope_stack);
|
|
109
|
+
if (isScopeLoop(currentScope)
|
|
110
|
+
&& name.endnext-name.begin>4
|
|
111
|
+
&& '_'==*(name.begin)
|
|
112
|
+
&& '_'==*(name.begin+1)
|
|
113
|
+
) {
|
|
114
|
+
/* we can meet loop variables here -- try it first */
|
|
115
|
+
/* length of its name >4 */
|
|
116
|
+
/* __first__ __last__ __inner__ __odd__ __counter__ */
|
|
117
|
+
PSTRING shiftedname; /* (PSTRING) {name.begin+2,name.endnext} */
|
|
118
|
+
shiftedname.begin=name.begin+2;
|
|
119
|
+
shiftedname.endnext=name.endnext;
|
|
120
|
+
switch (try_inner_loop_variable(shiftedname)) {
|
|
121
|
+
case 0: break;
|
|
122
|
+
case HTML_TEMPLATE_INNER_LOOP_VAR_FIRST:
|
|
123
|
+
if (currentScope->loop==0) { /* first__ */
|
|
124
|
+
retval.begin=TrueString; retval.endnext=TrueString+1;
|
|
125
|
+
} else {
|
|
126
|
+
retval.begin=FalseString; retval.endnext=FalseString+1;
|
|
127
|
+
}; break;
|
|
128
|
+
case HTML_TEMPLATE_INNER_LOOP_VAR_LAST:
|
|
129
|
+
if (currentScope->loop==(currentScope->loop_count-1)) {
|
|
130
|
+
retval.begin=TrueString; retval.endnext=TrueString+1;
|
|
131
|
+
} else {
|
|
132
|
+
retval.begin=FalseString; retval.endnext=FalseString+1;
|
|
133
|
+
}; break;
|
|
134
|
+
case HTML_TEMPLATE_INNER_LOOP_VAR_ODD:
|
|
135
|
+
if ((currentScope->loop%2)==0) {
|
|
136
|
+
retval.begin=TrueString; retval.endnext=TrueString+1;
|
|
137
|
+
} else {
|
|
138
|
+
retval.begin=FalseString; retval.endnext=FalseString+1;
|
|
139
|
+
}; break;
|
|
140
|
+
case HTML_TEMPLATE_INNER_LOOP_VAR_INNER:
|
|
141
|
+
if (currentScope->loop>0 &&
|
|
142
|
+
(currentScope->loop_count<0 /* loop_count < 0 if number of loops is unknown/undefined */
|
|
143
|
+
|| currentScope->loop < (currentScope->loop_count-1))) {
|
|
144
|
+
retval.begin=TrueString; retval.endnext=TrueString+1;
|
|
145
|
+
} else {
|
|
146
|
+
retval.begin=FalseString; retval.endnext=FalseString+1;
|
|
147
|
+
}; break;
|
|
148
|
+
case HTML_TEMPLATE_INNER_LOOP_VAR_COUNTER:
|
|
149
|
+
loop=currentScope->loop+1;
|
|
150
|
+
snprintf(buffer,sizeof(buffer),"%d",loop);
|
|
151
|
+
retval.begin=buffer; retval.endnext=buffer+strlen(buffer);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return retval;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
static
|
|
159
|
+
void init_tmpl_var_case_buffers (struct tmplpro_param *param) {
|
|
160
|
+
param->lowercase_varname.begin = NULL;
|
|
161
|
+
param->lowercase_varname.endnext = NULL;
|
|
162
|
+
param->uppercase_varname.begin = NULL;
|
|
163
|
+
param->uppercase_varname.endnext = NULL;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
static
|
|
167
|
+
ABSTRACT_VALUE* get_abstract_value (struct tmplpro_param *param, int scope_level, PSTRING name) {
|
|
168
|
+
ABSTRACT_VALUE* retval = NULL;
|
|
169
|
+
ABSTRACT_MAP* param_HV = getScope(¶m->var_scope_stack, scope_level)->param_HV;
|
|
170
|
+
ABSTRACT_DATASTATE* data_state = param->ext_data_state;
|
|
171
|
+
get_ABSTRACT_VALUE_functype getval_func = param->GetAbstractValFuncPtr;
|
|
172
|
+
int tmpl_var_case = param->tmpl_var_case;
|
|
173
|
+
if ((tmpl_var_case & ASK_NAME_MASK) == ASK_NAME_DEFAULT
|
|
174
|
+
|| tmpl_var_case & ASK_NAME_AS_IS) {
|
|
175
|
+
retval = getval_func(data_state, param_HV, name);
|
|
176
|
+
if (retval != NULL) return retval;
|
|
177
|
+
}
|
|
178
|
+
if (tmpl_var_case & ASK_NAME_LOWERCASE) {
|
|
179
|
+
if (param->lowercase_varname.begin == NULL) {
|
|
180
|
+
param->lowercase_varname=lowercase_pstring(¶m->lowercase_varname_buffer, name);
|
|
181
|
+
}
|
|
182
|
+
retval = getval_func(data_state, param_HV, param->lowercase_varname);
|
|
183
|
+
if (retval != NULL) return retval;
|
|
184
|
+
}
|
|
185
|
+
if (tmpl_var_case & ASK_NAME_UPPERCASE) {
|
|
186
|
+
if (param->uppercase_varname.begin == NULL) {
|
|
187
|
+
param->uppercase_varname=uppercase_pstring(¶m->uppercase_varname_buffer, name);
|
|
188
|
+
}
|
|
189
|
+
retval = getval_func(data_state, param_HV, param->uppercase_varname);
|
|
190
|
+
if (retval != NULL) return retval;
|
|
191
|
+
}
|
|
192
|
+
return retval;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
static
|
|
196
|
+
ABSTRACT_VALUE* walk_through_nested_loops (struct tmplpro_param *param, PSTRING name) {
|
|
197
|
+
int CurLevel;
|
|
198
|
+
ABSTRACT_VALUE* valptr;
|
|
199
|
+
init_tmpl_var_case_buffers (param);
|
|
200
|
+
/* Shigeki Morimoto path_like_variable_scope extension */
|
|
201
|
+
if (param->path_like_variable_scope) {
|
|
202
|
+
if(*(name.begin) == '/' || strncmp(name.begin, "../", 3) == 0){
|
|
203
|
+
PSTRING tmp_name;
|
|
204
|
+
int GoalHash;
|
|
205
|
+
if(*(name.begin) == '/'){
|
|
206
|
+
tmp_name.begin = name.begin+1; // skip '/'
|
|
207
|
+
tmp_name.endnext = name.endnext;
|
|
208
|
+
GoalHash = 0;
|
|
209
|
+
}else{
|
|
210
|
+
tmp_name.begin = name.begin;
|
|
211
|
+
tmp_name.endnext = name.endnext;
|
|
212
|
+
GoalHash = curScopeLevel(¶m->var_scope_stack);
|
|
213
|
+
while(strncmp(tmp_name.begin, "../", 3) == 0){
|
|
214
|
+
tmp_name.begin = tmp_name.begin + 3; // skip '../'
|
|
215
|
+
GoalHash --;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return get_abstract_value(param, GoalHash, tmp_name);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/* end Shigeki Morimoto path_like_variable_scope extension */
|
|
222
|
+
|
|
223
|
+
CurLevel = curScopeLevel(¶m->var_scope_stack);
|
|
224
|
+
valptr = get_abstract_value(param, CurLevel, name);
|
|
225
|
+
if (valptr) return valptr;
|
|
226
|
+
/* optional strict scoping; does it have much sence?
|
|
227
|
+
if ((STRICT_SCOPING==param->global_vars)) return NULL;
|
|
228
|
+
*/
|
|
229
|
+
|
|
230
|
+
/* loop-bounded scoping; */
|
|
231
|
+
if (0==param->global_vars) {
|
|
232
|
+
while (isScopeMap(getScope(¶m->var_scope_stack,CurLevel)) && --CurLevel>=0) {
|
|
233
|
+
valptr = get_abstract_value(param, CurLevel, name);
|
|
234
|
+
if (valptr!=NULL) return valptr;
|
|
235
|
+
}
|
|
236
|
+
return NULL;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
while (--CurLevel>=0) {
|
|
240
|
+
valptr = get_abstract_value(param, CurLevel, name);
|
|
241
|
+
if (valptr!=NULL) return valptr;
|
|
242
|
+
}
|
|
243
|
+
return NULL;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
static
|
|
247
|
+
int
|
|
248
|
+
is_string(struct tmplpro_state *state, const char* pattern,const char* PATTERN)
|
|
249
|
+
{
|
|
250
|
+
const char* cur_pos=state->cur_pos;
|
|
251
|
+
while (*pattern && cur_pos<state->next_to_end) {
|
|
252
|
+
if (*pattern == *cur_pos || *PATTERN == *cur_pos) {
|
|
253
|
+
pattern++;
|
|
254
|
+
PATTERN++;
|
|
255
|
+
cur_pos++;
|
|
256
|
+
} else {
|
|
257
|
+
return 0;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (cur_pos>=state->next_to_end) return 0;
|
|
261
|
+
state->cur_pos=cur_pos;
|
|
262
|
+
return 1;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
static
|
|
267
|
+
INLINE
|
|
268
|
+
void
|
|
269
|
+
jump_over_space(struct tmplpro_state *state)
|
|
270
|
+
{
|
|
271
|
+
while (isspace(*(state->cur_pos)) && state->cur_pos<state->next_to_end) {state->cur_pos++;};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
static
|
|
275
|
+
INLINE
|
|
276
|
+
void
|
|
277
|
+
jump_to_char(struct tmplpro_state *state, char c)
|
|
278
|
+
{
|
|
279
|
+
while (c!=*(state->cur_pos) && state->cur_pos<state->next_to_end) {state->cur_pos++;};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
TMPLPRO_LOCAL
|
|
283
|
+
PSTRING _get_variable_value (struct tmplpro_param *param, PSTRING name) {
|
|
284
|
+
PSTRING varvalue ={NULL, NULL};
|
|
285
|
+
ABSTRACT_VALUE* abstrval;
|
|
286
|
+
if (param->loop_context_vars) {
|
|
287
|
+
varvalue=get_loop_context_vars_value(param, name);
|
|
288
|
+
}
|
|
289
|
+
if (varvalue.begin==NULL) {
|
|
290
|
+
abstrval=walk_through_nested_loops(param, name);
|
|
291
|
+
if (abstrval!=NULL) varvalue=(param->AbstractVal2pstringFuncPtr)(param->ext_data_state, abstrval);
|
|
292
|
+
}
|
|
293
|
+
if (debuglevel>=TMPL_LOG_DEBUG2) {
|
|
294
|
+
if (name.begin!=NULL) {
|
|
295
|
+
tmpl_log(TMPL_LOG_DEBUG2,"_get_variable_value: name = %.*s ",(int)(name.endnext-name.begin),name.begin);
|
|
296
|
+
} else {
|
|
297
|
+
tmpl_log(TMPL_LOG_DEBUG2,"_get_variable_value: name = NULL ");
|
|
298
|
+
}
|
|
299
|
+
if (varvalue.begin!=NULL) {
|
|
300
|
+
tmpl_log(TMPL_LOG_DEBUG2,"value = %.*s\n",(int)(varvalue.endnext-varvalue.begin),varvalue.begin);
|
|
301
|
+
} else {
|
|
302
|
+
tmpl_log(TMPL_LOG_DEBUG2,"value = UNDEF\n");
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return varvalue;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
static
|
|
309
|
+
void
|
|
310
|
+
tag_handler_var (struct tmplpro_state *state, PSTRING name, PSTRING defvalue, int escapeopt)
|
|
311
|
+
{
|
|
312
|
+
PSTRING varvalue ={NULL, NULL};
|
|
313
|
+
/*
|
|
314
|
+
if (debuglevel>=TMPL_LOG_DEBUG2) {
|
|
315
|
+
log_state(state,TMPL_LOG_DEBUG2,"Entered tag_handler_var\n");
|
|
316
|
+
}*/
|
|
317
|
+
if (! state->is_visible) return;
|
|
318
|
+
if (state->is_expr) {
|
|
319
|
+
varvalue=parse_expr(name, state);
|
|
320
|
+
} else {
|
|
321
|
+
varvalue=_get_variable_value(state->param, name);
|
|
322
|
+
}
|
|
323
|
+
if (debuglevel>=TMPL_LOG_DEBUG) {
|
|
324
|
+
if (name.begin!=NULL) {
|
|
325
|
+
log_state(state,TMPL_LOG_DEBUG,"variable name = %.*s ",(int)(name.endnext-name.begin),name.begin);
|
|
326
|
+
} else {
|
|
327
|
+
log_state(state,TMPL_LOG_DEBUG,"variable name = NULL ");
|
|
328
|
+
}
|
|
329
|
+
if (varvalue.begin!=NULL) {
|
|
330
|
+
tmpl_log(TMPL_LOG_DEBUG,"value = %.*s\n",(int)(varvalue.endnext-varvalue.begin),varvalue.begin);
|
|
331
|
+
} else {
|
|
332
|
+
tmpl_log(TMPL_LOG_DEBUG,"value = UNDEF\n");
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (varvalue.begin==NULL) {
|
|
336
|
+
if (defvalue.begin!=defvalue.endnext) {
|
|
337
|
+
varvalue=defvalue;
|
|
338
|
+
} else return;
|
|
339
|
+
}
|
|
340
|
+
if (escapeopt!=HTML_TEMPLATE_OPT_ESCAPE_NO) {
|
|
341
|
+
varvalue=escape_pstring(&(state->str_buffer), varvalue, escapeopt);
|
|
342
|
+
}
|
|
343
|
+
(state->param->WriterFuncPtr)(state->param->ext_writer_state,varvalue.begin,varvalue.endnext);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
static
|
|
347
|
+
void
|
|
348
|
+
tag_handler_include (struct tmplpro_state *state, PSTRING name, PSTRING defvalue)
|
|
349
|
+
{
|
|
350
|
+
struct tmplpro_param* param;
|
|
351
|
+
char* filename;
|
|
352
|
+
const char* masterpath;
|
|
353
|
+
int x;
|
|
354
|
+
PSTRING varvalue=name;
|
|
355
|
+
if (! state->is_visible) return;
|
|
356
|
+
param=state->param;
|
|
357
|
+
if (param->no_includes) {
|
|
358
|
+
log_state(state,TMPL_LOG_ERROR, "HTML::Template::Pro : Illegal attempt to use TMPL_INCLUDE in template file : (no_includes => 1)\n");
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
if (param->max_includes && param->max_includes < param->cur_includes) return;
|
|
362
|
+
param->cur_includes++;
|
|
363
|
+
|
|
364
|
+
if (state->is_expr) {
|
|
365
|
+
varvalue=parse_expr(name, state);
|
|
366
|
+
} else
|
|
367
|
+
if (varvalue.begin==varvalue.endnext && defvalue.begin!=defvalue.endnext)
|
|
368
|
+
varvalue=defvalue;
|
|
369
|
+
/* pstrdup */
|
|
370
|
+
filename =(char*) malloc(varvalue.endnext-varvalue.begin+1);
|
|
371
|
+
for (x=0;x<varvalue.endnext-varvalue.begin;x++) {
|
|
372
|
+
*(filename+x)=*(varvalue.begin+x);
|
|
373
|
+
}
|
|
374
|
+
*(filename+(varvalue.endnext-varvalue.begin))=0;
|
|
375
|
+
/* end pstrdup */
|
|
376
|
+
masterpath=param->masterpath; /* saving current file name */
|
|
377
|
+
tmplpro_exec_tmpl_filename (param,filename);
|
|
378
|
+
free (filename);
|
|
379
|
+
param->masterpath=masterpath;
|
|
380
|
+
param->cur_includes--;
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
static
|
|
385
|
+
int
|
|
386
|
+
is_var_true(struct tmplpro_state *state, PSTRING name)
|
|
387
|
+
{
|
|
388
|
+
register int ifval=-1; /*not yet defined*/
|
|
389
|
+
if (state->is_expr) {
|
|
390
|
+
ifval=is_pstring_true(parse_expr(name, state));
|
|
391
|
+
} else
|
|
392
|
+
if (state->param->loop_context_vars) {
|
|
393
|
+
PSTRING loop_var=get_loop_context_vars_value(state->param, name);
|
|
394
|
+
if (loop_var.begin!=NULL) {
|
|
395
|
+
ifval=is_pstring_true(loop_var);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (ifval==-1) {
|
|
399
|
+
is_ABSTRACT_VALUE_true_functype userSuppliedIsTrueFunc;
|
|
400
|
+
ABSTRACT_VALUE* abstrval=walk_through_nested_loops(state->param, name);
|
|
401
|
+
if (abstrval==NULL) return 0;
|
|
402
|
+
userSuppliedIsTrueFunc = state->param->IsAbstractValTrueFuncPtr;
|
|
403
|
+
if (userSuppliedIsTrueFunc!=NULL) {
|
|
404
|
+
ifval=(userSuppliedIsTrueFunc)(state->param->ext_data_state, abstrval);
|
|
405
|
+
} else {
|
|
406
|
+
ifval=is_pstring_true((state->param->AbstractVal2pstringFuncPtr)(state->param->ext_data_state, abstrval));
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return ifval;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
static
|
|
413
|
+
void
|
|
414
|
+
tag_handler_if (struct tmplpro_state *state, PSTRING name)
|
|
415
|
+
{
|
|
416
|
+
struct tagstack_entry iftag;
|
|
417
|
+
iftag.tag=HTML_TEMPLATE_TAG_IF;
|
|
418
|
+
iftag.vcontext=state->is_visible;
|
|
419
|
+
iftag.position=state->cur_pos; /* unused */
|
|
420
|
+
/* state->is_visible && means that we do not evaluate variable in shadow */
|
|
421
|
+
if (state->is_visible && is_var_true(state,name)) {
|
|
422
|
+
iftag.value=1;
|
|
423
|
+
/* state->is_visible is not touched */
|
|
424
|
+
} else {
|
|
425
|
+
iftag.value=0;
|
|
426
|
+
state->is_visible=0;
|
|
427
|
+
}
|
|
428
|
+
tagstack_push(&(state->tag_stack), iftag);
|
|
429
|
+
if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"tag_handler_if:visible context =%d value=%d ",iftag.vcontext,iftag.value);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
static
|
|
433
|
+
void
|
|
434
|
+
tag_handler_unless (struct tmplpro_state *state, PSTRING name)
|
|
435
|
+
{
|
|
436
|
+
struct tagstack_entry iftag;
|
|
437
|
+
iftag.tag=HTML_TEMPLATE_TAG_UNLESS;
|
|
438
|
+
iftag.vcontext=state->is_visible;
|
|
439
|
+
iftag.position=state->cur_pos; /* unused */
|
|
440
|
+
/* state->is_visible && means that we do not evaluate variable in shadow */
|
|
441
|
+
if (state->is_visible && !is_var_true(state,name)) {
|
|
442
|
+
iftag.value=1;
|
|
443
|
+
/* state->is_visible is not touched */
|
|
444
|
+
} else {
|
|
445
|
+
iftag.value=0;
|
|
446
|
+
state->is_visible=0;
|
|
447
|
+
}
|
|
448
|
+
tagstack_push(&(state->tag_stack), iftag);
|
|
449
|
+
if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"tag_handler_unless:visible context =%d value=%d ",iftag.vcontext,iftag.value);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
static
|
|
453
|
+
INLINE
|
|
454
|
+
int
|
|
455
|
+
test_stack (int tag)
|
|
456
|
+
{
|
|
457
|
+
// return (tagstack_notempty(&(state->tag_stack)) && (tagstack_top(&(state->tag_stack))->tag==tag));
|
|
458
|
+
return 1;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
static
|
|
462
|
+
void
|
|
463
|
+
tag_stack_debug (struct tmplpro_state *state, int stack_tag_type)
|
|
464
|
+
{
|
|
465
|
+
if (stack_tag_type) {
|
|
466
|
+
if (tagstack_notempty(&(state->tag_stack))) {
|
|
467
|
+
struct tagstack_entry* iftag=tagstack_top(&(state->tag_stack));
|
|
468
|
+
if (iftag->tag!=stack_tag_type) {
|
|
469
|
+
log_state(state,TMPL_LOG_ERROR, "ERROR: tag mismatch with %s\n",TAGNAME[iftag->tag]);
|
|
470
|
+
}
|
|
471
|
+
} else {
|
|
472
|
+
log_state(state,TMPL_LOG_ERROR, "ERROR: opening tag %s not found\n",TAGNAME[stack_tag_type]);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
static
|
|
478
|
+
void
|
|
479
|
+
tag_handler_closeif (struct tmplpro_state *state)
|
|
480
|
+
{
|
|
481
|
+
struct tagstack_entry iftag;
|
|
482
|
+
if (! test_stack(HTML_TEMPLATE_TAG_IF)) {
|
|
483
|
+
tag_stack_debug(state,HTML_TEMPLATE_TAG_IF);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
iftag=tagstack_pop(&(state->tag_stack));
|
|
487
|
+
if (0==state->is_visible) state->last_processed_pos=state->cur_pos;
|
|
488
|
+
state->is_visible=iftag.vcontext;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
static
|
|
492
|
+
void
|
|
493
|
+
tag_handler_closeunless (struct tmplpro_state *state)
|
|
494
|
+
{
|
|
495
|
+
struct tagstack_entry iftag;
|
|
496
|
+
if (! test_stack(HTML_TEMPLATE_TAG_UNLESS)) {
|
|
497
|
+
tag_stack_debug(state,HTML_TEMPLATE_TAG_UNLESS);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
iftag=tagstack_pop(&(state->tag_stack));
|
|
501
|
+
if (0==state->is_visible) state->last_processed_pos=state->cur_pos;
|
|
502
|
+
state->is_visible=iftag.vcontext;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
static
|
|
506
|
+
void
|
|
507
|
+
tag_handler_else (struct tmplpro_state *state)
|
|
508
|
+
{
|
|
509
|
+
struct tagstack_entry* iftag;
|
|
510
|
+
if (! test_stack(HTML_TEMPLATE_TAG_IF) &&
|
|
511
|
+
! test_stack(HTML_TEMPLATE_TAG_UNLESS)) {
|
|
512
|
+
tag_stack_debug(state,HTML_TEMPLATE_TAG_ELSE);
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
iftag=tagstack_top(&(state->tag_stack));
|
|
516
|
+
if (0==state->is_visible) state->last_processed_pos=state->cur_pos;
|
|
517
|
+
if (iftag->value) {
|
|
518
|
+
state->is_visible=0;
|
|
519
|
+
} else if (1==iftag->vcontext) {
|
|
520
|
+
state->is_visible=1;
|
|
521
|
+
}
|
|
522
|
+
if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"else:(pos " MOD_TD ") visible:context =%d, set to %d ",
|
|
523
|
+
TO_PTRDIFF_T(iftag->position - state->top),iftag->vcontext,state->is_visible);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
static
|
|
527
|
+
void
|
|
528
|
+
tag_handler_elsif (struct tmplpro_state *state, PSTRING name)
|
|
529
|
+
{
|
|
530
|
+
struct tagstack_entry *iftag;
|
|
531
|
+
if (! test_stack(HTML_TEMPLATE_TAG_IF) &&
|
|
532
|
+
! test_stack(HTML_TEMPLATE_TAG_UNLESS)) {
|
|
533
|
+
tag_stack_debug(state,HTML_TEMPLATE_TAG_ELSIF);
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
iftag=tagstack_top(&(state->tag_stack));
|
|
537
|
+
if (0==state->is_visible) state->last_processed_pos=state->cur_pos;
|
|
538
|
+
if (iftag->value) {
|
|
539
|
+
state->is_visible=0;
|
|
540
|
+
} else if (1==iftag->vcontext) {
|
|
541
|
+
/* test only if vcontext==true; if the whole tag if..endif itself is invisible, skip the is_var_true test */
|
|
542
|
+
/*TODO: it is reasonable to skip is_var_true test in if/unless too */
|
|
543
|
+
if (is_var_true(state,name)) {
|
|
544
|
+
iftag->value=1;
|
|
545
|
+
state->is_visible=1;
|
|
546
|
+
} else {
|
|
547
|
+
iftag->value=0;
|
|
548
|
+
state->is_visible=0;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"elsif:(pos " MOD_TD ") visible:context =%d, set to %d ",
|
|
552
|
+
TO_PTRDIFF_T(iftag->position - state->top), iftag->vcontext, state->is_visible);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
static
|
|
556
|
+
int
|
|
557
|
+
next_loop (struct tmplpro_state* state) {
|
|
558
|
+
#ifdef DEBUG
|
|
559
|
+
log_state(state,TMPL_LOG_DEBUG2,"next_loop:before NextLoopFuncPtr\n");
|
|
560
|
+
#endif
|
|
561
|
+
struct ProScopeEntry* currentScope = getCurrentScope(&state->param->var_scope_stack);
|
|
562
|
+
if (!isScopeLoop(currentScope)) {
|
|
563
|
+
log_state(state,TMPL_LOG_ERROR, "next_loop:at scope level %d: internal error - loop is null\n", curScopeLevel(&state->param->var_scope_stack));
|
|
564
|
+
return 0;
|
|
565
|
+
}
|
|
566
|
+
if (++currentScope->loop < currentScope->loop_count || currentScope->loop_count< 0) {
|
|
567
|
+
ABSTRACT_MAP* arrayvalptr=(state->param->GetAbstractMapFuncPtr)(state->param->ext_data_state, currentScope->loops_AV,currentScope->loop);
|
|
568
|
+
if ((arrayvalptr!=NULL)) {
|
|
569
|
+
currentScope->param_HV=arrayvalptr;
|
|
570
|
+
return 1;
|
|
571
|
+
} else {
|
|
572
|
+
/* either undefined loop ended normally or defined loop ended ubnormally */
|
|
573
|
+
if (currentScope->loop_count>0) log_state(state,TMPL_LOG_ERROR, "PARAM:LOOP:next_loop(%d): callback returned null scope\n", currentScope->loop);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (state->param->ExitLoopScopeFuncPtr) state->param->ExitLoopScopeFuncPtr(state->param->ext_data_state, currentScope->loops_AV);
|
|
577
|
+
popScope(&state->param->var_scope_stack);
|
|
578
|
+
return 0;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
static
|
|
582
|
+
int init_loop (struct tmplpro_state *state, PSTRING name) {
|
|
583
|
+
int loop_count;
|
|
584
|
+
ABSTRACT_ARRAY* loopptr=(ABSTRACT_ARRAY*) walk_through_nested_loops(state->param,name);
|
|
585
|
+
if (loopptr==NULL) {
|
|
586
|
+
return 0;
|
|
587
|
+
} else {
|
|
588
|
+
/* set loop array */
|
|
589
|
+
loopptr = (*state->param->AbstractVal2abstractArrayFuncPtr)(state->param->ext_data_state, loopptr);
|
|
590
|
+
if (loopptr == NULL)
|
|
591
|
+
{
|
|
592
|
+
log_state(state,TMPL_LOG_ERROR, "PARAM:LOOP:loop argument:loop was expected but not found.\n");
|
|
593
|
+
return 0;
|
|
594
|
+
}
|
|
595
|
+
loop_count = (*state->param->GetAbstractArrayLengthFuncPtr)(state->param->ext_data_state, loopptr);
|
|
596
|
+
/* 0 is an empty array; <0 is an undefined array (iterated until next_loop==NULL */
|
|
597
|
+
if (0==loop_count) return 0;
|
|
598
|
+
pushScopeLoop(&state->param->var_scope_stack, loop_count, loopptr);
|
|
599
|
+
return 1;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
static
|
|
604
|
+
void
|
|
605
|
+
tag_handler_loop (struct tmplpro_state *state, PSTRING name)
|
|
606
|
+
{
|
|
607
|
+
struct tagstack_entry iftag;
|
|
608
|
+
iftag.tag=HTML_TEMPLATE_TAG_LOOP;
|
|
609
|
+
iftag.vcontext=state->is_visible;
|
|
610
|
+
iftag.value=0;
|
|
611
|
+
iftag.position=state->cur_pos; /* loop start - to restore in </tmpl_loop> */
|
|
612
|
+
#ifdef DEBUG
|
|
613
|
+
log_state(state,TMPL_LOG_DEBUG2,"tag_handler_loop:before InitLoopFuncPtr\n");
|
|
614
|
+
#endif
|
|
615
|
+
if (state->is_visible && init_loop(state,name) && next_loop(state)) {
|
|
616
|
+
iftag.value=1; /* the loop is non - empty */
|
|
617
|
+
} else {
|
|
618
|
+
/* empty loop is equal to <if false> ... </if> */
|
|
619
|
+
state->is_visible=0;
|
|
620
|
+
}
|
|
621
|
+
#ifdef DEBUG
|
|
622
|
+
log_state(state,TMPL_LOG_DEBUG2,"tag_handler_loop:after InitLoopFuncPtr\n");
|
|
623
|
+
#endif
|
|
624
|
+
tagstack_push(&(state->tag_stack), iftag);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
static
|
|
628
|
+
void
|
|
629
|
+
tag_handler_closeloop (struct tmplpro_state *state)
|
|
630
|
+
{
|
|
631
|
+
struct tagstack_entry* iftag_ptr;
|
|
632
|
+
if (! test_stack(HTML_TEMPLATE_TAG_LOOP)) {
|
|
633
|
+
tag_stack_debug(state,HTML_TEMPLATE_TAG_LOOP);
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
iftag_ptr=tagstack_top(&(state->tag_stack));
|
|
637
|
+
if (iftag_ptr->value==1 && next_loop(state)) {
|
|
638
|
+
/* continue loop */
|
|
639
|
+
state->cur_pos=iftag_ptr->position;
|
|
640
|
+
state->last_processed_pos=iftag_ptr->position;
|
|
641
|
+
return;
|
|
642
|
+
} else {
|
|
643
|
+
/* finish loop */
|
|
644
|
+
struct tagstack_entry iftag;
|
|
645
|
+
iftag=tagstack_pop(&(state->tag_stack));
|
|
646
|
+
state->is_visible=iftag.vcontext;
|
|
647
|
+
state->last_processed_pos=state->cur_pos;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
static
|
|
652
|
+
void
|
|
653
|
+
tag_handler_unknown (struct tmplpro_state *state)
|
|
654
|
+
{
|
|
655
|
+
log_state(state,TMPL_LOG_ERROR,"tag_handler_unknown: unknown tag\n");
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
static
|
|
659
|
+
PSTRING
|
|
660
|
+
read_tag_parameter_value (struct tmplpro_state *state)
|
|
661
|
+
{
|
|
662
|
+
PSTRING modifier_value;
|
|
663
|
+
char cur_char;
|
|
664
|
+
char quote_char=0;
|
|
665
|
+
register const char* cur_pos;
|
|
666
|
+
register const char* next_to_end=state->next_to_end;
|
|
667
|
+
jump_over_space(state);
|
|
668
|
+
cur_pos=state->cur_pos;
|
|
669
|
+
cur_char=*(cur_pos);
|
|
670
|
+
if (('"'==cur_char) || ('\''==cur_char)) {
|
|
671
|
+
quote_char=*(cur_pos);
|
|
672
|
+
cur_pos++;
|
|
673
|
+
}
|
|
674
|
+
modifier_value.begin=cur_pos;
|
|
675
|
+
cur_char=*(cur_pos);
|
|
676
|
+
if (quote_char) {
|
|
677
|
+
while (quote_char!=cur_char
|
|
678
|
+
#ifdef COMPAT_ON_BROKEN_QUOTE
|
|
679
|
+
/* compatibility mode; HTML::Template doesn't allow '>' inside quotes */
|
|
680
|
+
&& ('>' != quote_char)
|
|
681
|
+
#endif
|
|
682
|
+
&& cur_pos<next_to_end) {
|
|
683
|
+
cur_pos++;
|
|
684
|
+
cur_char=*(cur_pos);
|
|
685
|
+
}
|
|
686
|
+
} else {
|
|
687
|
+
while ('>'!=cur_char && ! isspace(cur_char) && cur_pos<next_to_end) {
|
|
688
|
+
cur_pos++;
|
|
689
|
+
cur_char=*(cur_pos);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
if (cur_pos>=next_to_end) {
|
|
693
|
+
log_state(state,TMPL_LOG_ERROR,"quote char %c at pos " MOD_TD " is not terminated\n",
|
|
694
|
+
quote_char,TO_PTRDIFF_T(state->cur_pos-state->top));
|
|
695
|
+
modifier_value.endnext=modifier_value.begin;
|
|
696
|
+
jump_over_space(state);
|
|
697
|
+
return modifier_value;
|
|
698
|
+
}
|
|
699
|
+
modifier_value.endnext=cur_pos;
|
|
700
|
+
if (quote_char) {
|
|
701
|
+
if (quote_char==*cur_pos) {
|
|
702
|
+
cur_pos++;
|
|
703
|
+
} else {
|
|
704
|
+
log_state(state,TMPL_LOG_ERROR,"found %c instead of end quote %c at pos " MOD_TD "\n",
|
|
705
|
+
*cur_pos,quote_char,TO_PTRDIFF_T(cur_pos - state->top));
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
state->cur_pos=cur_pos;
|
|
709
|
+
/* log_state(state,TMPL_LOG_DEBUG2," at pos " MOD_TD "",TO_PTRDIFF_T(state->cur_pos-state->top)); */
|
|
710
|
+
jump_over_space(state);
|
|
711
|
+
return modifier_value;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
static
|
|
715
|
+
int
|
|
716
|
+
try_tag_parameter (struct tmplpro_state *state,const char *modifier,const char *MODIFIER)
|
|
717
|
+
{
|
|
718
|
+
const char* initial_pos=state->cur_pos;
|
|
719
|
+
jump_over_space(state);
|
|
720
|
+
if (is_string(state, modifier, MODIFIER)) {
|
|
721
|
+
jump_over_space(state);
|
|
722
|
+
if ('='==*(state->cur_pos)) {
|
|
723
|
+
state->cur_pos++;
|
|
724
|
+
jump_over_space(state);
|
|
725
|
+
return 1;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
state->cur_pos=initial_pos;
|
|
729
|
+
return 0;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
static
|
|
733
|
+
void
|
|
734
|
+
try_tmpl_var_options (struct tmplpro_state *state, PSTRING* OptEscape, PSTRING* OptDefault)
|
|
735
|
+
{
|
|
736
|
+
static const char* escapeopt="escape";
|
|
737
|
+
static const char* ESCAPEOPT="ESCAPE";
|
|
738
|
+
static const char* defaultopt="default";
|
|
739
|
+
static const char* DEFAULTOPT="DEFAULT";
|
|
740
|
+
if (try_tag_parameter(state, escapeopt, ESCAPEOPT)) {
|
|
741
|
+
*OptEscape=read_tag_parameter_value(state);
|
|
742
|
+
log_state(state,TMPL_LOG_DEBUG, "found option ESCAPE at pos " MOD_TD "\n",TO_PTRDIFF_T(state->cur_pos-state->top));
|
|
743
|
+
}
|
|
744
|
+
if (try_tag_parameter(state, defaultopt, DEFAULTOPT)) {
|
|
745
|
+
*OptDefault=read_tag_parameter_value(state);
|
|
746
|
+
log_state(state,TMPL_LOG_DEBUG, "found option DEFAULT at pos " MOD_TD "\n",TO_PTRDIFF_T(state->cur_pos-state->top));
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
static
|
|
752
|
+
void
|
|
753
|
+
process_tmpl_tag(struct tmplpro_state *state)
|
|
754
|
+
{
|
|
755
|
+
const char* tag_start=state->tag_start;
|
|
756
|
+
int is_tag_closed=state->is_tag_closed;
|
|
757
|
+
|
|
758
|
+
int tag_type=HTML_TEMPLATE_BAD_TAG;
|
|
759
|
+
static const char* nameopt="name";
|
|
760
|
+
static const char* NAMEOPT="NAME";
|
|
761
|
+
static const char* expropt="expr";
|
|
762
|
+
static const char* EXPROPT="EXPR";
|
|
763
|
+
|
|
764
|
+
PSTRING OptName = {NULL,NULL};
|
|
765
|
+
PSTRING OptDefault={NULL,NULL};
|
|
766
|
+
PSTRING OptEscape= {NULL,NULL};
|
|
767
|
+
|
|
768
|
+
int i;
|
|
769
|
+
for (i=HTML_TEMPLATE_FIRST_TAG_USED; i<=HTML_TEMPLATE_LAST_TAG_USED; i++) {
|
|
770
|
+
if (is_string(state, tagname[i], TAGNAME[i])) {
|
|
771
|
+
tag_type=i;
|
|
772
|
+
state->tag=tag_type;
|
|
773
|
+
if (debuglevel) {
|
|
774
|
+
if (is_tag_closed) {
|
|
775
|
+
tmpl_log(TMPL_LOG_DEBUG, "found </TMPL_%s> at pos " MOD_TD "\n",TAGNAME[i], TO_PTRDIFF_T(state->cur_pos-state->top));
|
|
776
|
+
} else {
|
|
777
|
+
tmpl_log(TMPL_LOG_DEBUG, "found <TMPL_%s> at pos " MOD_TD "\n",TAGNAME[i], TO_PTRDIFF_T(state->cur_pos-state->top));
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
break;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
if (HTML_TEMPLATE_BAD_TAG==tag_type) {
|
|
784
|
+
log_state(state,TMPL_LOG_ERROR, "found bad tag at pos " MOD_TD "\n", TO_PTRDIFF_T(state->cur_pos-state->top));
|
|
785
|
+
/* TODO: flush its data --- */
|
|
786
|
+
state->cur_pos++;
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
if (is_tag_closed && (
|
|
791
|
+
tag_type==HTML_TEMPLATE_TAG_ELSE
|
|
792
|
+
|| tag_type==HTML_TEMPLATE_TAG_INCLUDE
|
|
793
|
+
|| tag_type==HTML_TEMPLATE_TAG_VAR
|
|
794
|
+
)) {
|
|
795
|
+
log_state(state,TMPL_LOG_ERROR, "incorrect tag </TMPL_%s> at pos " MOD_TD "\n",
|
|
796
|
+
TAGNAME[tag_type], TO_PTRDIFF_T(state->cur_pos-state->top));
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
if (is_tag_closed || tag_type==HTML_TEMPLATE_TAG_ELSE) {
|
|
800
|
+
/* tag has no parameter */
|
|
801
|
+
|
|
802
|
+
/* requested compatibility mode
|
|
803
|
+
to try reading NAME inside </closing tags NAME=" ">
|
|
804
|
+
(useful for comments?) */
|
|
805
|
+
#ifdef COMPAT_ALLOW_NAME_IN_CLOSING_TAG
|
|
806
|
+
try_tag_parameter(state, nameopt, NAMEOPT);
|
|
807
|
+
read_tag_parameter_value(state);
|
|
808
|
+
#endif
|
|
809
|
+
} else {
|
|
810
|
+
/* reading parameter */
|
|
811
|
+
state->is_expr=0;
|
|
812
|
+
if (tag_type==HTML_TEMPLATE_TAG_VAR
|
|
813
|
+
|| tag_type==HTML_TEMPLATE_TAG_INCLUDE
|
|
814
|
+
) {
|
|
815
|
+
try_tmpl_var_options(state,&OptEscape,&OptDefault);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
if (try_tag_parameter(state, expropt, EXPROPT)) {
|
|
819
|
+
state->is_expr=1;
|
|
820
|
+
} else {
|
|
821
|
+
try_tag_parameter(state, nameopt, NAMEOPT);
|
|
822
|
+
}
|
|
823
|
+
OptName=read_tag_parameter_value(state);
|
|
824
|
+
|
|
825
|
+
if (tag_type==HTML_TEMPLATE_TAG_VAR
|
|
826
|
+
|| tag_type==HTML_TEMPLATE_TAG_INCLUDE
|
|
827
|
+
) {
|
|
828
|
+
try_tmpl_var_options(state,&OptEscape,&OptDefault);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
if (state->is_tag_commented) {
|
|
833
|
+
/* try read comment end */
|
|
834
|
+
/* jump_over_space(state); it should be already done :( */
|
|
835
|
+
jump_over_space(state);
|
|
836
|
+
if (state->cur_pos<state->next_to_end-2 && '-'==*(state->cur_pos) && '-'==*(state->cur_pos+1)) {
|
|
837
|
+
state->cur_pos+=2;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
/* template tags could also be decorated as xml <tmpl_TAG /> */
|
|
841
|
+
if (!state->is_tag_closed && '/'==*(state->cur_pos)) state->cur_pos++;
|
|
842
|
+
|
|
843
|
+
if ('>'==*(state->cur_pos)) {
|
|
844
|
+
state->cur_pos++;
|
|
845
|
+
} else {
|
|
846
|
+
log_state(state,TMPL_LOG_ERROR,"end tag:found %c instead of > at pos " MOD_TD "\n",
|
|
847
|
+
*state->cur_pos, TO_PTRDIFF_T(state->cur_pos-state->top));
|
|
848
|
+
}
|
|
849
|
+
/* flush run chars (if in SHOW mode) */
|
|
850
|
+
if (state->is_visible) {
|
|
851
|
+
(state->param->WriterFuncPtr)(state->param->ext_writer_state,state->last_processed_pos,tag_start);
|
|
852
|
+
state->last_processed_pos=state->cur_pos;
|
|
853
|
+
}
|
|
854
|
+
/* TODO: call tag_specific handler by array of handlers
|
|
855
|
+
var_tag_handler(..) */
|
|
856
|
+
if (is_tag_closed) {
|
|
857
|
+
switch (tag_type) {
|
|
858
|
+
case HTML_TEMPLATE_TAG_IF: tag_handler_closeif(state);break;
|
|
859
|
+
case HTML_TEMPLATE_TAG_UNLESS: tag_handler_closeunless(state);break;
|
|
860
|
+
case HTML_TEMPLATE_TAG_LOOP: tag_handler_closeloop(state);break;
|
|
861
|
+
default: tag_handler_unknown(state);break;
|
|
862
|
+
|
|
863
|
+
}
|
|
864
|
+
} else {
|
|
865
|
+
/* int escape = HTML_TEMPLATE_OPT_ESCAPE_NO; */
|
|
866
|
+
int escape = state->param->default_escape;
|
|
867
|
+
switch (tag_type) {
|
|
868
|
+
case HTML_TEMPLATE_TAG_VAR:
|
|
869
|
+
if (OptEscape.begin!=OptEscape.endnext) {
|
|
870
|
+
switch (*OptEscape.begin) {
|
|
871
|
+
case '1': case 'H': case 'h': /* HTML*/
|
|
872
|
+
escape = HTML_TEMPLATE_OPT_ESCAPE_HTML;
|
|
873
|
+
break;
|
|
874
|
+
case 'U': case 'u': /* URL */
|
|
875
|
+
escape = HTML_TEMPLATE_OPT_ESCAPE_URL;
|
|
876
|
+
break;
|
|
877
|
+
case 'J': case 'j': /* JS */
|
|
878
|
+
escape = HTML_TEMPLATE_OPT_ESCAPE_JS;
|
|
879
|
+
break;
|
|
880
|
+
case '0': case 'N': case 'n': /* 0 or NONE */
|
|
881
|
+
escape = HTML_TEMPLATE_OPT_ESCAPE_NO;
|
|
882
|
+
break;
|
|
883
|
+
default:
|
|
884
|
+
log_state(state,TMPL_LOG_ERROR, " unsupported value of ESCAPE=%.*s\n",(int)(OptEscape.endnext-OptEscape.begin),OptEscape.begin);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
tag_handler_var(state,OptName,OptDefault,escape);
|
|
888
|
+
break;
|
|
889
|
+
case HTML_TEMPLATE_TAG_IF: tag_handler_if(state,OptName); break;
|
|
890
|
+
case HTML_TEMPLATE_TAG_UNLESS: tag_handler_unless(state,OptName);break;
|
|
891
|
+
case HTML_TEMPLATE_TAG_ELSE: tag_handler_else(state); break;
|
|
892
|
+
case HTML_TEMPLATE_TAG_ELSIF: tag_handler_elsif(state,OptName);break;
|
|
893
|
+
case HTML_TEMPLATE_TAG_LOOP: tag_handler_loop(state,OptName);break;
|
|
894
|
+
case HTML_TEMPLATE_TAG_INCLUDE: tag_handler_include(state,OptName,OptDefault);break;
|
|
895
|
+
default: tag_handler_unknown(state);break;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
static
|
|
902
|
+
void
|
|
903
|
+
process_state (struct tmplpro_state * state)
|
|
904
|
+
{
|
|
905
|
+
static const char* metatag="tmpl_";
|
|
906
|
+
static const char* METATAG="TMPL_";
|
|
907
|
+
flag is_tag_closed;
|
|
908
|
+
flag is_tag_commented;
|
|
909
|
+
const char* last_safe_pos=state->next_to_end-TAG_WIDTH_OFFSET;
|
|
910
|
+
if (debuglevel) tmpl_log(TMPL_LOG_DEBUG,"process_state:initiated at scope stack depth = %d\n",
|
|
911
|
+
curScopeLevel(&state->param->var_scope_stack));
|
|
912
|
+
tagstack_init(&(state->tag_stack));
|
|
913
|
+
pbuffer_init(&(state->str_buffer));
|
|
914
|
+
/* magic; 256 > 50 (50 is min.required for double to string conversion */
|
|
915
|
+
pbuffer_init_as(&(state->expr_left_pbuffer), 256);
|
|
916
|
+
pbuffer_init_as(&(state->expr_right_pbuffer), 256);
|
|
917
|
+
|
|
918
|
+
while (state->cur_pos < last_safe_pos) {
|
|
919
|
+
register const char* cur_pos=state->cur_pos;
|
|
920
|
+
while (cur_pos < last_safe_pos && '<'!=*(cur_pos++)) {};
|
|
921
|
+
if (cur_pos >= last_safe_pos) break;
|
|
922
|
+
state->tag_start=cur_pos-1;
|
|
923
|
+
is_tag_closed=0;
|
|
924
|
+
is_tag_commented=0;
|
|
925
|
+
state->cur_pos=cur_pos;
|
|
926
|
+
if (('!'==*(cur_pos)) && ('-'==*(cur_pos+1)) && ('-'==*(cur_pos+2))) {
|
|
927
|
+
state->cur_pos+=3;
|
|
928
|
+
jump_over_space(state);
|
|
929
|
+
is_tag_commented=1;
|
|
930
|
+
}
|
|
931
|
+
if ('/'==*(state->cur_pos)) {
|
|
932
|
+
state->cur_pos++;
|
|
933
|
+
is_tag_closed=1;
|
|
934
|
+
}
|
|
935
|
+
if (is_string(state,metatag,METATAG)) {
|
|
936
|
+
state->is_tag_commented=is_tag_commented;
|
|
937
|
+
state->is_tag_closed=is_tag_closed;
|
|
938
|
+
process_tmpl_tag(state);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
(state->param->WriterFuncPtr)(state->param->ext_writer_state,state->last_processed_pos,state->next_to_end);
|
|
942
|
+
|
|
943
|
+
pbuffer_free(&(state->expr_right_pbuffer));
|
|
944
|
+
pbuffer_free(&(state->expr_left_pbuffer));
|
|
945
|
+
pbuffer_free(&(state->str_buffer));
|
|
946
|
+
tagstack_free(&(state->tag_stack));
|
|
947
|
+
if (debuglevel) tmpl_log(TMPL_LOG_DEBUG,"process_state:finished\n");
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
static
|
|
951
|
+
void
|
|
952
|
+
init_state (struct tmplpro_state *state, struct tmplpro_param *param)
|
|
953
|
+
{
|
|
954
|
+
debuglevel=param->debug;
|
|
955
|
+
tmpl_log_set_level(debuglevel);
|
|
956
|
+
/* initializing state */
|
|
957
|
+
state->param=param;
|
|
958
|
+
state->last_processed_pos=state->top;
|
|
959
|
+
state->cur_pos=state->top;
|
|
960
|
+
state->tag=HTML_TEMPLATE_NO_TAG;
|
|
961
|
+
state->is_visible=1;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
static
|
|
965
|
+
int
|
|
966
|
+
tmplpro_exec_tmpl_filename (struct tmplpro_param *param, const char* filename)
|
|
967
|
+
{
|
|
968
|
+
struct tmplpro_state state;
|
|
969
|
+
int mmapstatus;
|
|
970
|
+
PSTRING memarea;
|
|
971
|
+
int retval = 0;
|
|
972
|
+
/*
|
|
973
|
+
* param->masterpath is path to upper level template
|
|
974
|
+
* (or NULL in toplevel) which called <include filename>.
|
|
975
|
+
* we use it to calculate filepath for filename.
|
|
976
|
+
* Then filename becames upper level template for its <include>.
|
|
977
|
+
*/
|
|
978
|
+
const char* filepath=(param->FindFileFuncPtr)(param->ext_findfile_state,filename, param->masterpath);
|
|
979
|
+
if (NULL==filepath) return ERR_PRO_FILE_NOT_FOUND;
|
|
980
|
+
/* filepath should be alive for every nested template */
|
|
981
|
+
filepath = strdup(filepath);
|
|
982
|
+
|
|
983
|
+
param->masterpath=filepath;
|
|
984
|
+
if (param->filters) memarea=(param->LoadFileFuncPtr)(param->ext_filter_state,filepath);
|
|
985
|
+
else memarea=mmap_load_file(filepath);
|
|
986
|
+
if (memarea.begin == NULL) {
|
|
987
|
+
retval = ERR_PRO_CANT_OPEN_FILE;
|
|
988
|
+
goto cleanup_filepath;
|
|
989
|
+
}
|
|
990
|
+
state.top =memarea.begin;
|
|
991
|
+
state.next_to_end=memarea.endnext;
|
|
992
|
+
if (memarea.begin < memarea.endnext) {
|
|
993
|
+
/* to avoid crash with empty file */
|
|
994
|
+
init_state(&state,param);
|
|
995
|
+
log_state(&state,TMPL_LOG_DEBUG, "exec_tmpl: loading %s\n",filename);
|
|
996
|
+
process_state(&state);
|
|
997
|
+
}
|
|
998
|
+
/* destroying */
|
|
999
|
+
if (param->filters) mmapstatus=(param->UnloadFileFuncPtr)(param->ext_filter_state,memarea);
|
|
1000
|
+
else mmapstatus=mmap_unload_file(memarea);
|
|
1001
|
+
cleanup_filepath:
|
|
1002
|
+
if (filepath!=NULL) free((void*) filepath);
|
|
1003
|
+
return retval;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
static
|
|
1007
|
+
int
|
|
1008
|
+
tmplpro_exec_tmpl_scalarref (struct tmplpro_param *param, PSTRING memarea)
|
|
1009
|
+
{
|
|
1010
|
+
struct tmplpro_state state;
|
|
1011
|
+
param->masterpath=NULL; /* no upper file */
|
|
1012
|
+
state.top = memarea.begin;
|
|
1013
|
+
state.next_to_end=memarea.endnext;
|
|
1014
|
+
if (memarea.begin == memarea.endnext) return 0;
|
|
1015
|
+
init_state(&state,param);
|
|
1016
|
+
process_state(&state);
|
|
1017
|
+
return 0;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
#include "builtin_findfile.inc"
|
|
1021
|
+
#include "callback_stubs.inc"
|
|
1022
|
+
|
|
1023
|
+
API_IMPL
|
|
1024
|
+
int
|
|
1025
|
+
APICALL
|
|
1026
|
+
tmplpro_exec_tmpl (struct tmplpro_param *param)
|
|
1027
|
+
{
|
|
1028
|
+
int exitcode=0;
|
|
1029
|
+
if (param->GetAbstractValFuncPtr==NULL ||
|
|
1030
|
+
param->AbstractVal2pstringFuncPtr==NULL ||
|
|
1031
|
+
param->AbstractVal2abstractArrayFuncPtr==NULL ||
|
|
1032
|
+
/*param->GetAbstractArrayLengthFuncPtr==NULL ||*/
|
|
1033
|
+
param->GetAbstractMapFuncPtr==NULL ||
|
|
1034
|
+
(param->IsExprUserfncFuncPtr!=NULL &&
|
|
1035
|
+
(param->InitExprArglistFuncPtr==NULL ||
|
|
1036
|
+
param->PushExprArglistFuncPtr==NULL ||
|
|
1037
|
+
param->FreeExprArglistFuncPtr==NULL ||
|
|
1038
|
+
param->CallExprUserfncFuncPtr==NULL))
|
|
1039
|
+
)
|
|
1040
|
+
{
|
|
1041
|
+
tmpl_log(TMPL_LOG_ERROR,"tmplpro_exec_tmpl: a required callback is missing.");
|
|
1042
|
+
return ERR_PRO_INVALID_ARGUMENT;
|
|
1043
|
+
}
|
|
1044
|
+
if (param->filters &&
|
|
1045
|
+
(param->LoadFileFuncPtr==NULL ||
|
|
1046
|
+
param->UnloadFileFuncPtr==NULL)) {
|
|
1047
|
+
tmpl_log(TMPL_LOG_ERROR,"tmplpro_exec_tmpl: filters is set but filter callbacks are missing.");
|
|
1048
|
+
}
|
|
1049
|
+
/* set up stabs */
|
|
1050
|
+
if (NULL==param->WriterFuncPtr) param->WriterFuncPtr = stub_write_chars_to_stdout;
|
|
1051
|
+
if (NULL==param->ext_findfile_state) param->ext_findfile_state = param;
|
|
1052
|
+
if (NULL==param->FindFileFuncPtr) {
|
|
1053
|
+
param->FindFileFuncPtr = stub_find_file_func;
|
|
1054
|
+
param->ext_findfile_state = param;
|
|
1055
|
+
/*pbuffer_init(¶m->builtin_findfile_buffer);*/
|
|
1056
|
+
}
|
|
1057
|
+
if (NULL==param->IsExprUserfncFuncPtr) param->IsExprUserfncFuncPtr = stub_is_expr_userfnc_func;
|
|
1058
|
+
if (NULL==param->LoadFileFuncPtr) param->LoadFileFuncPtr = stub_load_file_func;
|
|
1059
|
+
if (NULL==param->UnloadFileFuncPtr) param->UnloadFileFuncPtr = stub_unload_file_func;
|
|
1060
|
+
if (NULL==param->GetAbstractArrayLengthFuncPtr) param->GetAbstractArrayLengthFuncPtr = stub_get_ABSTRACT_ARRAY_length_func;
|
|
1061
|
+
|
|
1062
|
+
Scope_reset(¶m->var_scope_stack, param->param_map_count);
|
|
1063
|
+
/* reset other internals */
|
|
1064
|
+
param->cur_includes=0; /* internal counter of include depth */
|
|
1065
|
+
/*masterpath=NULL;*/
|
|
1066
|
+
|
|
1067
|
+
if (param->scalarref.begin) exitcode = tmplpro_exec_tmpl_scalarref(param, param->scalarref);
|
|
1068
|
+
else if (param->filename) exitcode = tmplpro_exec_tmpl_filename(param, param->filename);
|
|
1069
|
+
else {
|
|
1070
|
+
tmpl_log(TMPL_LOG_ERROR,"tmplpro_exec_tmpl: neither scalarref nor filename was specified.");
|
|
1071
|
+
exitcode = ERR_PRO_INVALID_ARGUMENT;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
return exitcode;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
API_IMPL
|
|
1078
|
+
MPSTRING
|
|
1079
|
+
APICALL
|
|
1080
|
+
tmplpro_tmpl2pstring (struct tmplpro_param *param, int *retvalptr)
|
|
1081
|
+
{
|
|
1082
|
+
int exitcode;
|
|
1083
|
+
MPSTRING retval;
|
|
1084
|
+
struct builtin_writer_state state;
|
|
1085
|
+
writer_functype save_writer_func = param->WriterFuncPtr;
|
|
1086
|
+
ABSTRACT_WRITER* save_writer_state = param->ext_writer_state;
|
|
1087
|
+
param->WriterFuncPtr = stub_write_chars_to_pbuffer;
|
|
1088
|
+
param->ext_writer_state = &state;
|
|
1089
|
+
pbuffer_init_as(&state.buffer, 4000);
|
|
1090
|
+
state.size = 0;
|
|
1091
|
+
exitcode = tmplpro_exec_tmpl (param);
|
|
1092
|
+
param->WriterFuncPtr = save_writer_func;
|
|
1093
|
+
param->ext_writer_state = save_writer_state;
|
|
1094
|
+
if (retvalptr) *retvalptr=exitcode;
|
|
1095
|
+
retval.begin = pbuffer_string(&state.buffer);
|
|
1096
|
+
retval.endnext = retval.begin+state.size;
|
|
1097
|
+
*retval.endnext='\0';
|
|
1098
|
+
return retval;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
API_IMPL
|
|
1102
|
+
void
|
|
1103
|
+
APICALL
|
|
1104
|
+
tmplpro_clear_option_param_map(struct tmplpro_param *param)
|
|
1105
|
+
{
|
|
1106
|
+
param->param_map_count=0;
|
|
1107
|
+
Scope_reset(¶m->var_scope_stack,param->param_map_count);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
API_IMPL
|
|
1111
|
+
int
|
|
1112
|
+
APICALL
|
|
1113
|
+
tmplpro_push_option_param_map(struct tmplpro_param *param, ABSTRACT_MAP* map, EXPR_int64 flags)
|
|
1114
|
+
{
|
|
1115
|
+
pushScopeMap(¶m->var_scope_stack, map, (int) flags);
|
|
1116
|
+
return ++(param->param_map_count);
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
API_IMPL
|
|
1120
|
+
int
|
|
1121
|
+
APICALL
|
|
1122
|
+
tmplpro_count_option_param_map(struct tmplpro_param *param)
|
|
1123
|
+
{
|
|
1124
|
+
return param->param_map_count;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
API_IMPL
|
|
1129
|
+
void
|
|
1130
|
+
APICALL
|
|
1131
|
+
tmplpro_procore_init(void)
|
|
1132
|
+
{
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
API_IMPL
|
|
1136
|
+
void
|
|
1137
|
+
APICALL
|
|
1138
|
+
tmplpro_procore_done(void)
|
|
1139
|
+
{
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/* internal initialization of struct tmplpro_param */
|
|
1143
|
+
API_IMPL
|
|
1144
|
+
struct tmplpro_param*
|
|
1145
|
+
APICALL
|
|
1146
|
+
tmplpro_param_init(void)
|
|
1147
|
+
{
|
|
1148
|
+
struct tmplpro_param* param=(struct tmplpro_param*) malloc (sizeof(struct tmplpro_param));
|
|
1149
|
+
if (param==NULL) return param;
|
|
1150
|
+
/* filling initial struct tmplpro_param with 0 */
|
|
1151
|
+
memset (param, 0, sizeof(struct tmplpro_param));
|
|
1152
|
+
/* current level of inclusion */
|
|
1153
|
+
/* param->cur_includes=0; */
|
|
1154
|
+
/* not to use external file loader */
|
|
1155
|
+
/* param->filters=0;
|
|
1156
|
+
param->default_escape=HTML_TEMPLATE_OPT_ESCAPE_NO;
|
|
1157
|
+
param->masterpath=NULL; *//* we are not included by something *//*
|
|
1158
|
+
param->expr_func_map=NULL;
|
|
1159
|
+
param->expr_func_arglist=NULL;
|
|
1160
|
+
*/
|
|
1161
|
+
param->max_includes=256;
|
|
1162
|
+
Scope_init(¶m->var_scope_stack);
|
|
1163
|
+
/* no need for them due to memset 0
|
|
1164
|
+
pbuffer_preinit(¶m->builtin_findfile_buffer);
|
|
1165
|
+
pbuffer_preinit(¶m->lowercase_varname_buffer);
|
|
1166
|
+
pbuffer_preinit(¶m->uppercase_varname_buffer);
|
|
1167
|
+
*/
|
|
1168
|
+
return param;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
API_IMPL
|
|
1172
|
+
void
|
|
1173
|
+
APICALL
|
|
1174
|
+
tmplpro_param_free(struct tmplpro_param* param)
|
|
1175
|
+
{
|
|
1176
|
+
pbuffer_free(¶m->builtin_findfile_buffer);
|
|
1177
|
+
pbuffer_free(¶m->lowercase_varname_buffer);
|
|
1178
|
+
pbuffer_free(¶m->uppercase_varname_buffer);
|
|
1179
|
+
Scope_free(¶m->var_scope_stack);
|
|
1180
|
+
free(param);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
#include "tagstack.inc"
|
|
1184
|
+
|
|
1185
|
+
/*
|
|
1186
|
+
* Local Variables:
|
|
1187
|
+
* mode: c
|
|
1188
|
+
* End:
|
|
1189
|
+
*/
|