File Coverage

Pro.xs
Criterion Covered Total %
statement 294 361 81.4
branch 154 384 40.1
condition n/a
subroutine n/a
pod n/a
total 448 745 60.1


line stmt bran cond sub pod time code
1             #define PERLIO_NOT_STDIO 0 /* For co-existence with stdio only */
2             #define PERL_NO_GET_CONTEXT /* we want efficiency */
3              
4             #ifdef __cplusplus
5             extern "C" {
6             #endif
7             #include "EXTERN.h"
8             #include "perl.h"
9             #include "XSUB.h"
10             #ifdef __cplusplus
11             }
12             #endif
13              
14             #include
15             #include
16              
17             #include "ppport.h"
18              
19             #ifdef USE_SYSTEM_HTP_HEADER
20             #include
21             #else
22             #include "tmplpro.h"
23             #endif
24              
25             typedef PerlIO * OutputStream;
26              
27             struct perl_callback_state {
28             SV* perl_obj_self_ptr;
29             AV* filtered_tmpl_array;
30             AV* pool_for_perl_vars;
31             int force_untaint;
32             };
33              
34             static
35             int debuglevel=0;
36              
37 449           static struct perl_callback_state new_callback_state (SV* self_ptr) {
38             dTHX; /* fetch context */
39             struct perl_callback_state cs;
40 449           cs.perl_obj_self_ptr = self_ptr;
41 449           cs.filtered_tmpl_array = newAV();
42 449           cs.pool_for_perl_vars = newAV();
43 449           cs.force_untaint = 0;
44 449           return cs;
45             }
46              
47             /* endnext points on next character to end of interval as in c++ */
48 1297           static void write_chars_to_file (ABSTRACT_WRITER* OutputFile, const char* begin, const char* endnext) {
49             dTHX; /* fetch context */
50 1297           PerlIO_write((PerlIO*)OutputFile,begin, endnext-begin);
51 1297           }
52              
53             /* endnext points on next to end character of the interval */
54 2759           static void write_chars_to_string (ABSTRACT_WRITER* OutputString, const char* begin, const char* endnext) {
55             dTHX; /* fetch context */
56 2759           sv_catpvn((SV*)OutputString, begin, endnext-begin);
57 2759           }
58              
59             static
60 1476           ABSTRACT_VALUE* get_ABSTRACT_VALUE_impl (ABSTRACT_DATASTATE* none, ABSTRACT_MAP* ptr_HV, PSTRING name) {
61             dTHX; /* fetch context */
62 1476           return hv_fetch((HV*) ptr_HV,name.begin, name.endnext-name.begin, 0);
63             }
64              
65             static
66             SV*
67 209           call_coderef (SV* coderef) {
68             SV* SVretval;
69             I32 count;
70             dTHX; /* fetch context */
71             /* TODO: G_EVAL and error handler */
72 209           dSP;
73              
74             /* let perl clean up mortals after the end of output() call
75             ENTER;
76             SAVETMPS;*/
77              
78 209 50         PUSHMARK(SP);
79 209           PUTBACK; /* in fact, isn't needed -- nothing is pushed and G_NOARGS is used */
80              
81 209           count = call_sv(coderef, G_EVAL|G_SCALAR|G_NOARGS);
82 209           SPAGAIN;
83              
84             /* Check the eval first */
85 209 50         if (SvTRUE(ERRSV))
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
86 0           {
87             STRLEN n_a;
88 0 0         printf ("Pro.xs: param tree code reference exited abnormally - %s\n", SvPV(ERRSV, n_a));
    0          
    0          
    0          
    0          
89 0           SVretval=POPs; /* undef */
90             }
91             else
92             {
93 209 50         if (count != 1)
94 0           croak("Pro.xs: internal context error (got %d) while calling CODE reference\n", (int)count);
95 209           SVretval=POPs;
96             }
97              
98 209           PUTBACK;
99             /* let perl clean up mortals after the end of output() call
100             FREETMPS;
101             LEAVE;*/
102 209           return SVretval;
103             }
104              
105             static
106 731           PSTRING ABSTRACT_VALUE2PSTRING_impl (ABSTRACT_DATASTATE* callback_state, ABSTRACT_VALUE* valptr) {
107 731           STRLEN len=0;
108 731           PSTRING retval={NULL,NULL};
109             SV* SVval;
110             dTHX; /* fetch context */
111 731 50         if (valptr==NULL) return retval;
112 731           SVval = *((SV**) valptr);
113 731 100         SvGETMAGIC(SVval);
    50          
114 731 50         if (SvOK(SVval) && SvROK(SVval)) {
    0          
    0          
    100          
115 12 100         if (SvTYPE(SvRV(SVval))==SVt_PVCV) {
116 7           SVval = call_coderef(SVval);
117 5 50         } else if(SvTYPE(SvRV(SVval))==SVt_PV) {
118 0           SVval = SvRV(SVval);
119             }
120 12 50         SvGETMAGIC(SVval);
    0          
121             }
122 731 50         if (!SvOK(SVval)) return retval;
    0          
    0          
123             /* TODO param resource deallocation */
124 731 50         if (((struct perl_callback_state*) callback_state)->force_untaint && SVval && SvTAINTED(SVval))
    0          
    0          
    0          
125 0           croak("force_untaint: got tainted value %" SVf, SVval);
126              
127 731 100         retval.begin=SvPV(SVval, len);
128 731           retval.endnext=retval.begin+len;
129 731           return retval;
130             }
131              
132             static
133 304           int is_ABSTRACT_VALUE_true_impl (ABSTRACT_DATASTATE* none, ABSTRACT_VALUE* valptr) {
134             SV* SVval;
135             dTHX; /* fetch context */
136 304 50         if (valptr==NULL) return 0;
137 304           SVval = *((SV**) valptr);
138 304 100         if (SvROK(SVval)) {
139 208 100         if ((SvTYPE(SvRV(SVval)) == SVt_PVCV)) {
140 202           SVval = call_coderef(SVval);
141             } else
142             /* arrayptr : in HTML::Template, true if len(array)>0 */
143 6 50         if ((SvTYPE(SvRV(SVval)) == SVt_PVAV)
144 6 50         && (av_len((AV *)SvRV(SVval))<0)) {
145 0           return 0;
146 6           } else return 1;
147             }
148             /* in any place where I receive a value of which I don't know the origin,
149             I should call SvGETMAGIC first. */
150 298 50         SvGETMAGIC(SVval);
    0          
151 298 50         if(SvTRUE(SVval)) return 1;
    50          
    50          
    0          
    0          
    100          
    50          
    50          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
152 106           return 0;
153             }
154              
155             static
156 75           ABSTRACT_ARRAY* ABSTRACT_VALUE2ABSTRACT_ARRAY_impl (ABSTRACT_DATASTATE* none, ABSTRACT_VALUE* abstrvalptr) {
157 75           SV* val = *((SV**) abstrvalptr);
158             dTHX; /* fetch context */
159 75 50         SvGETMAGIC(val);
    0          
160 75 50         if ((!SvROK(val)) || (SvTYPE(SvRV(val)) != SVt_PVAV)) return 0;
    50          
161 75           return (ABSTRACT_ARRAY*) SvRV(val);
162             }
163              
164             static
165 75           int get_ABSTRACT_ARRAY_length_impl (ABSTRACT_DATASTATE* none, ABSTRACT_ARRAY* loops_AV) {
166             dTHX; /* fetch context */
167 75 50         SvGETMAGIC((SV *)loops_AV);
    0          
168 75           return av_len((AV *)loops_AV)+1;
169             }
170              
171             static
172 187           ABSTRACT_MAP* get_ABSTRACT_MAP_impl (ABSTRACT_DATASTATE* none, ABSTRACT_ARRAY* loops_AV, int loop) {
173             dTHX; /* fetch context */
174             SV* val;
175 187           SV** arrayvalptr = av_fetch((AV*)loops_AV, loop, 0);
176 187 50         if (arrayvalptr==NULL) return NULL;
177 187           val = *arrayvalptr;
178 187 100         SvGETMAGIC(val);
    50          
179 187 50         if ((!SvROK(val)) || (SvTYPE(SvRV(val)) != SVt_PVHV)) {
    50          
180 0           return NULL;
181             } else {
182 187           return (ABSTRACT_MAP *)SvRV(*arrayvalptr);
183             }
184             }
185              
186             static
187 0           const char* get_filepath (ABSTRACT_FINDFILE* callback_state, const char* filename, const char* prevfilename) {
188             dTHX; /* fetch context */
189 0           dSP ;
190             int count ;
191             STRLEN len;
192             char* filepath;
193             SV* perlprevfile;
194 0           SV* PerlSelfHTMLTemplatePro = ((struct perl_callback_state*)callback_state)->perl_obj_self_ptr;
195 0           SV* perlretval = sv_2mortal(newSVpv(filename,0));
196 0 0         if (prevfilename) {
197 0           perlprevfile=sv_2mortal(newSVpv(prevfilename,0));
198             } else {
199 0           perlprevfile=sv_2mortal(newSV(0));
200             }
201 0           ENTER ;
202 0           SAVETMPS;
203 0 0         PUSHMARK(SP) ;
204 0 0         XPUSHs((SV*)PerlSelfHTMLTemplatePro);
205 0 0         XPUSHs(perlretval);
206 0 0         XPUSHs(perlprevfile);
207 0           PUTBACK ;
208 0           count = call_pv("_get_filepath", G_SCALAR);
209 0           SPAGAIN ;
210 0 0         if (count != 1) croak("Big troublen") ;
211 0           perlretval=POPs;
212             /* any memory leaks??? */
213 0 0         if (SvOK(perlretval)) {
    0          
    0          
214 0 0         filepath = SvPV(perlretval, len);
215 0           av_push(((struct perl_callback_state*)callback_state)->pool_for_perl_vars,perlretval);
216 0           SvREFCNT_inc(perlretval);
217             } else {
218 0           filepath = NULL;
219             }
220 0           PUTBACK ;
221 0 0         FREETMPS ;
222 0           LEAVE ;
223 0           return filepath;
224             }
225              
226             static
227 9           PSTRING load_file (ABSTRACT_FILTER* callback_state, const char* filepath) {
228             dTHX; /* fetch context */
229 9           dSP ;
230             int count ;
231             STRLEN len;
232             PSTRING tmpl;
233             SV* templateptr;
234 9           SV* perlretval = sv_2mortal(newSVpv(filepath,0));
235 9           ENTER ;
236 9           SAVETMPS;
237 9 50         PUSHMARK(SP) ;
238 9 50         XPUSHs(((struct perl_callback_state*)callback_state)->perl_obj_self_ptr);
239 9 50         XPUSHs(perlretval);
240 9           PUTBACK ;
241 9           count = call_pv("_load_template", G_SCALAR);
242 9           SPAGAIN ;
243 9 50         if (count != 1) croak("Big troublen") ;
244 9           templateptr=POPs;
245             /* any memory leaks??? */
246 9 50         if (SvOK(templateptr) && SvROK(templateptr)) {
    0          
    0          
    50          
247 9 50         tmpl.begin = SvPV(SvRV(templateptr), len);
248 9           tmpl.endnext=tmpl.begin+len;
249 9           av_push(((struct perl_callback_state*)callback_state)->filtered_tmpl_array,templateptr);
250 9           SvREFCNT_inc(templateptr);
251             } else {
252 0           croak("Big trouble! _load_template internal fatal error\n") ;
253             }
254 9           PUTBACK ;
255 9 50         FREETMPS ;
256 9           LEAVE ;
257 9           return tmpl;
258             }
259              
260             static
261 9           int unload_file(ABSTRACT_FILTER* callback_state, PSTRING memarea) {
262             dTHX; /* fetch context */
263 9           SvREFCNT_dec(av_pop(((struct perl_callback_state*)callback_state)->filtered_tmpl_array));
264 9           return 0;
265             }
266              
267             static
268 135           ABSTRACT_USERFUNC* is_expr_userfnc (ABSTRACT_FUNCMAP* FuncHash, PSTRING name) {
269             dTHX; /* fetch context */
270 135           SV** hashvalptr=hv_fetch((HV *) FuncHash, name.begin, name.endnext-name.begin, 0);
271 135           return hashvalptr;
272             }
273              
274             static
275 70           void free_expr_arglist(ABSTRACT_ARGLIST* arglist)
276             {
277             dTHX; /* fetch context */
278 70 50         if (NULL!=arglist) {
279 70           av_undef((AV*) arglist);
280 70           SvREFCNT_dec(arglist);
281             }
282 70           }
283              
284             static
285 70           ABSTRACT_ARGLIST* init_expr_arglist(ABSTRACT_CALLER* none)
286             {
287             dTHX; /* fetch context */
288 70           return newAV();
289             }
290              
291             static
292 88           void push_expr_arglist(ABSTRACT_ARGLIST* arglist, ABSTRACT_EXPRVAL* exprval)
293             {
294             dTHX; /* fetch context */
295 88           SV* val=NULL;
296 88           int exprval_type=tmplpro_get_expr_type(exprval);
297             PSTRING parg;
298 88           switch (exprval_type) {
299 0           case EXPR_TYPE_NULL: val=newSV(0);break;
300 8           case EXPR_TYPE_INT: val=newSViv(tmplpro_get_expr_as_int64(exprval));break;
301 1           case EXPR_TYPE_DBL: val=newSVnv(tmplpro_get_expr_as_double(exprval));break;
302 79           case EXPR_TYPE_PSTR: parg=tmplpro_get_expr_as_pstring(exprval);
303 79           val=newSVpvn(parg.begin, parg.endnext-parg.begin);break;
304 0           default: die ("Perl wrapper: FATAL INTERNAL ERROR:Unsupported type %d in exprval", exprval_type);
305             }
306 88           av_push ((AV*) arglist, val);
307 88           }
308              
309             static
310 70           void call_expr_userfnc (ABSTRACT_CALLER* callback_state, ABSTRACT_ARGLIST* arglist, ABSTRACT_USERFUNC* hashvalptr, ABSTRACT_EXPRVAL* exprval) {
311             dTHX; /* fetch context */
312 70           dSP ;
313 70           char* empty="";
314             char* strval;
315             SV ** arrval;
316             SV * svretval;
317             I32 i;
318             I32 numretval;
319 70           I32 arrlen=av_len((AV *) arglist);
320 70           PSTRING retvalpstr = { empty, empty };
321 70           retvalpstr.begin=empty;
322 70           retvalpstr.endnext=empty;
323 70 50         if (hashvalptr==NULL) {
324 0           die ("FATAL INTERNAL ERROR:Call_EXPR:function called but not exists");
325             tmplpro_set_expr_as_pstring(exprval,retvalpstr);
326             return;
327 70 50         } else if (! SvROK(*((SV**) hashvalptr)) || (SvTYPE(SvRV(*((SV**) hashvalptr))) != SVt_PVCV)) {
    50          
328 0           die ("FATAL INTERNAL ERROR:Call_EXPR:not a function reference");
329             tmplpro_set_expr_as_pstring(exprval,retvalpstr);
330             return;
331             }
332              
333 70           ENTER ;
334 70           SAVETMPS ;
335              
336 70 50         PUSHMARK(SP) ;
337 158 100         for (i=0;i<=arrlen;i++) {
338 88           arrval=av_fetch((AV *) arglist,i,0);
339 88 50         if (arrval) XPUSHs(*arrval);
    50          
340 0           else warn("INTERNAL: call: strange arrval");
341             }
342 70           PUTBACK ;
343 70           numretval=call_sv(*((SV**) hashvalptr), G_SCALAR);
344 70           SPAGAIN ;
345 70 50         if (numretval) {
346 70           svretval=POPs;
347 70 50         SvGETMAGIC(svretval);
    0          
348 70 100         if (SvOK(svretval)) {
    50          
    50          
349 132 100         if (SvIOK(svretval)) {
350 1 50         tmplpro_set_expr_as_int64(exprval,SvIV(svretval));
351 65 50         } else if (SvNOK(svretval)) {
352 0 0         tmplpro_set_expr_as_double(exprval,SvNV(svretval));
353             } else {
354 65           STRLEN len=0;
355 65 50         strval =SvPV(svretval, len);
356             /* hack !!! */
357 65           av_push(((struct perl_callback_state*)callback_state)->pool_for_perl_vars,svretval);
358 65           SvREFCNT_inc(svretval);
359 65           retvalpstr.begin=strval;
360 65           retvalpstr.endnext=strval +len;
361 65           tmplpro_set_expr_as_pstring(exprval,retvalpstr);
362             }
363             } else {
364 70 50         if (debuglevel>1) warn ("user defined function returned undef\n");
365             }
366             } else {
367 0 0         if (debuglevel) warn ("user defined function returned nothing\n");
368             }
369              
370 70 50         FREETMPS ;
371 70           LEAVE ;
372              
373 70           return;
374             }
375              
376             typedef void (*set_int_option_functype) (struct tmplpro_param*, int);
377              
378             static
379 4041           void set_integer_from_hash(pTHX_ HV* TheHash, char* key, struct tmplpro_param* param, set_int_option_functype setfunc) {
380 4041           SV** hashvalptr=hv_fetch(TheHash, key, strlen(key), 0);
381 4041 100         if (hashvalptr==NULL) return;
382 3214 50         setfunc(param,SvIV(*hashvalptr));
383             }
384              
385             static
386 1347           int get_integer_from_hash(pTHX_ HV* TheHash, char* key) {
387 1347           SV** hashvalptr=hv_fetch(TheHash, key, strlen(key), 0);
388 1347 100         if (hashvalptr==NULL) return 0;
389 898 50         return SvIV(*hashvalptr);
390             }
391              
392             static
393 1347           PSTRING get_string_from_hash(pTHX_ HV* TheHash, char* key) {
394 1347           SV** hashvalptr=hv_fetch(TheHash, key, strlen(key), 0);
395 1347           STRLEN len=0;
396             char * begin;
397 1347           PSTRING retval={NULL,NULL};
398 1347 100         if (hashvalptr==NULL) return retval;
399 451 100         if (SvROK(*hashvalptr)) {
400             /* if (SvTYPE(SvRV(*hashvalptr))!=SVt_PV) return (PSTRING) {NULL,NULL}; */
401 216 50         begin=SvPV(SvRV(*hashvalptr),len);
402             } else {
403 235 50         if (! SvPOK(*hashvalptr)) return retval;
404 235 50         begin=SvPV(*hashvalptr,len);
405             }
406 451           retval.begin=begin;
407 451           retval.endnext=begin+len;
408 1347           return retval;
409             }
410              
411              
412             static
413 449           char** get_array_of_strings_from_hash(pTHX_ HV* TheHash, char* key, struct perl_callback_state* callback_state) {
414 449           SV** valptr=hv_fetch(TheHash, key, strlen(key), 0);
415             int amax;
416 449           char** path=NULL;
417             AV* pathAV;
418 449           int i =0;
419             char** j;
420             SV* store;
421 449 50         if (valptr!=NULL && SvROK(*valptr) && (SvTYPE(SvRV(*valptr)) == SVt_PVAV) ) {
    50          
    50          
422 449           pathAV=(AV *)SvRV(*valptr);
423 449           amax=av_len(pathAV);
424 508 100         if (amax<0) {
425 390           return NULL;
426             } else {
427 59           store = newSV(sizeof(char*)*(amax+2));
428 59 50         path = (char**) SvGROW(store, sizeof(char*)*(amax+2));
    50          
429 59           av_push(((struct perl_callback_state*)callback_state)->pool_for_perl_vars,store);
430 59           SvREFCNT_inc(store);
431             //path=(char**) malloc(sizeof(char*)*(amax+2));
432 59           j=path;
433 127 100         for (i=0; i<=amax;i++) {
434 68           valptr = av_fetch(pathAV,i,0);
435 68 50         if (valptr!=NULL) {
436 68 50         *j=SvPV_nolen(*valptr);
437 68           j++;
438             }
439 68           *j=NULL;
440             }
441             }
442             } else {
443 0           warn ("get_array_of_strings:option %s not found :(\n", key);
444             }
445 59           return path;
446             }
447              
448             static
449 449           struct tmplpro_param* process_tmplpro_options (struct perl_callback_state* callback_state) {
450             dTHX; /* fetch context */
451             HV* SelfHash;
452             SV** hashvalptr;
453             const char* tmpstring;
454 449           SV* PerlSelfPtr=callback_state->perl_obj_self_ptr;
455 449           int default_escape=HTML_TEMPLATE_OPT_ESCAPE_NO;
456              
457             /* main arguments */
458             PSTRING filename;
459             PSTRING scalarref;
460              
461             /* internal initialization */
462 449           struct tmplpro_param* param=tmplpro_param_init();
463              
464             /* setting initial hooks */
465 449           tmplpro_set_option_WriterFuncPtr(param, &write_chars_to_string);
466 449           tmplpro_set_option_GetAbstractValFuncPtr(param, &get_ABSTRACT_VALUE_impl);
467 449           tmplpro_set_option_AbstractVal2pstringFuncPtr(param, &ABSTRACT_VALUE2PSTRING_impl);
468 449           tmplpro_set_option_AbstractVal2abstractArrayFuncPtr(param, &ABSTRACT_VALUE2ABSTRACT_ARRAY_impl);
469 449           tmplpro_set_option_GetAbstractArrayLengthFuncPtr(param, &get_ABSTRACT_ARRAY_length_impl);
470 449           tmplpro_set_option_IsAbstractValTrueFuncPtr(param, &is_ABSTRACT_VALUE_true_impl);
471 449           tmplpro_set_option_GetAbstractMapFuncPtr(param, &get_ABSTRACT_MAP_impl);
472 449           tmplpro_set_option_LoadFileFuncPtr(param, &load_file);
473 449           tmplpro_set_option_UnloadFileFuncPtr(param, &unload_file);
474              
475             /* setting initial Expr hooks */
476 449           tmplpro_set_option_InitExprArglistFuncPtr(param, &init_expr_arglist);
477 449           tmplpro_set_option_FreeExprArglistFuncPtr(param, &free_expr_arglist);
478 449           tmplpro_set_option_PushExprArglistFuncPtr(param, &push_expr_arglist);
479 449           tmplpro_set_option_CallExprUserfncFuncPtr(param, &call_expr_userfnc);
480 449           tmplpro_set_option_IsExprUserfncFuncPtr(param, &is_expr_userfnc);
481             /* end setting initial hooks */
482              
483             /* setting perl globals */
484 449           tmplpro_set_option_ext_findfile_state(param,callback_state);
485 449           tmplpro_set_option_ext_filter_state(param,callback_state);
486 449           tmplpro_set_option_ext_calluserfunc_state(param,callback_state);
487 449           tmplpro_set_option_ext_data_state(param,callback_state);
488             /* end setting perl globals */
489              
490 449 50         if ((!SvROK(PerlSelfPtr)) || (SvTYPE(SvRV(PerlSelfPtr)) != SVt_PVHV))
    50          
491             {
492 0           die("FATAL:SELF:hash pointer was expected but not found");
493             }
494 449           SelfHash=(HV *)SvRV(PerlSelfPtr);
495              
496             /* checking main arguments */
497 449           filename=get_string_from_hash(aTHX_ SelfHash,"filename");
498 449           scalarref=get_string_from_hash(aTHX_ SelfHash,"scalarref");
499 449           tmplpro_set_option_filename(param, filename.begin);
500 449           tmplpro_set_option_scalarref(param, scalarref);
501 449 100         if (filename.begin==NULL && scalarref.begin==NULL) {
    50          
502 0           die ("bad arguments: expected filename or scalarref");
503             }
504              
505             /* setting expr_func */
506 449           hashvalptr=hv_fetch(SelfHash, "expr_func", 9, 0); /* 9=strlen("expr_func") */
507 449 50         if (!hashvalptr || !SvROK(*hashvalptr) || (SvTYPE(SvRV(*hashvalptr)) != SVt_PVHV))
    50          
    50          
508 0           die("FATAL:output:EXPR user functions not found");
509 449           tmplpro_set_option_expr_func_map(param, (HV *) SvRV(*hashvalptr));
510             /* end setting expr_func */
511              
512             /* setting param_map */
513 449           tmplpro_clear_option_param_map(param);
514 449           hashvalptr=hv_fetch(SelfHash, "associate", 9, 0); /* 9=strlen("associate") */
515 449 50         if (hashvalptr!=NULL && SvROK(*hashvalptr) && (SvTYPE(SvRV(*hashvalptr)) == SVt_PVAV)) {
    50          
    50          
516 449           AV* associate = (AV*) SvRV(*hashvalptr);
517 449           I32 i = av_len(associate);
518             SV** arrayvalptr;
519 451 100         while (i>=0) {
520 2           arrayvalptr = av_fetch(associate, i, 0);
521 2 50         if (arrayvalptr!=NULL && SvROK(*arrayvalptr))
    50          
522 2           tmplpro_push_option_param_map(param, (ABSTRACT_MAP *)SvRV(*arrayvalptr), 0);
523 2           i--;
524             }
525             }
526 449           hashvalptr=hv_fetch(SelfHash, "param_map", 9, 0); /* 9=strlen("param_map") */
527             /* TODO param deallocation on warn/die */
528 449 50         if (!hashvalptr || !SvROK(*hashvalptr) || (SvTYPE(SvRV(*hashvalptr)) != SVt_PVHV))
    50          
    50          
529 0           die("FATAL:output:param_map not found");
530 449           tmplpro_push_option_param_map(param, (ABSTRACT_MAP *)SvRV(*hashvalptr), 0);
531             /* end setting param_map */
532              
533             /* setting filter */
534 449           hashvalptr=hv_fetch(SelfHash, "filter", 6, 0); /* 6=strlen("filter") */
535 449 50         if (!hashvalptr || !SvROK(*hashvalptr) || (SvTYPE(SvRV(*hashvalptr)) != SVt_PVAV))
    50          
    50          
536 0           die("FATAL:output:filter not found");
537 449 100         if (av_len((AV*)SvRV(*hashvalptr))>=0) tmplpro_set_option_filters(param, 1);
538             /* end setting param_map */
539              
540 449 100         if (!get_integer_from_hash(aTHX_ SelfHash,"case_sensitive")) {
541 375           tmplpro_set_option_tmpl_var_case(param, ASK_NAME_LOWERCASE);
542             }
543              
544 449           set_integer_from_hash(aTHX_ SelfHash,"tmpl_var_case",param,tmplpro_set_option_tmpl_var_case);
545 449           set_integer_from_hash(aTHX_ SelfHash,"max_includes",param,tmplpro_set_option_max_includes);
546 449           set_integer_from_hash(aTHX_ SelfHash,"no_includes",param,tmplpro_set_option_no_includes);
547 449           set_integer_from_hash(aTHX_ SelfHash,"search_path_on_include",param,tmplpro_set_option_search_path_on_include);
548 449           set_integer_from_hash(aTHX_ SelfHash,"global_vars",param,tmplpro_set_option_global_vars);
549 449           set_integer_from_hash(aTHX_ SelfHash,"debug",param,tmplpro_set_option_debug);
550 449           debuglevel = tmplpro_get_option_debug(param);
551 449           set_integer_from_hash(aTHX_ SelfHash,"loop_context_vars",param,tmplpro_set_option_loop_context_vars);
552 449           set_integer_from_hash(aTHX_ SelfHash,"path_like_variable_scope",param,tmplpro_set_option_path_like_variable_scope);
553             /* still unsupported */
554 449           set_integer_from_hash(aTHX_ SelfHash,"strict",param,tmplpro_set_option_strict);
555              
556 449           tmpstring=get_string_from_hash(aTHX_ SelfHash,"default_escape").begin;
557 449 100         if (tmpstring && *tmpstring) {
    50          
558 2           switch (*tmpstring) {
559             case '1': case 'H': case 'h': /* HTML*/
560 1           default_escape = HTML_TEMPLATE_OPT_ESCAPE_HTML;
561 1           break;
562             case 'U': case 'u': /* URL */
563 1           default_escape = HTML_TEMPLATE_OPT_ESCAPE_URL;
564 1           break;
565             case 'J': case 'j': /* JS */
566 0           default_escape = HTML_TEMPLATE_OPT_ESCAPE_JS;
567 0           break;
568             case '0': case 'N': case 'n': /* 0 or NONE */
569 0           default_escape = HTML_TEMPLATE_OPT_ESCAPE_NO;
570 0           break;
571             default:
572 0           warn("unsupported value of default_escape=%s. Valid values are HTML, URL or JS.\n",tmpstring);
573             }
574 2           tmplpro_set_option_default_escape(param, default_escape);
575              
576             }
577              
578             /* setting callback_state */
579 449           callback_state->force_untaint=get_integer_from_hash(aTHX_ SelfHash,"force_untaint");
580             /* end setting callback_state */
581              
582 449 50         if (get_integer_from_hash(aTHX_ SelfHash,"__use_perl_find_file")) {
583 0           tmplpro_set_option_FindFileFuncPtr(param, &get_filepath);
584             } else {
585 449           tmplpro_set_option_path(param, get_array_of_strings_from_hash(aTHX_ SelfHash, "path", callback_state));
586 449           tmplpro_set_option_FindFileFuncPtr(param, NULL);
587             }
588              
589             #if defined _WIN32
590             /* hack; see https://rt.cpan.org/Public/Bug/Display.html?id=51218 */
591             tmplpro_set_option_template_root(param, getenv("HTML_TEMPLATE_ROOT"));
592             #endif
593 449           return param;
594             }
595              
596             static void
597 449           release_tmplpro_options(struct tmplpro_param* param, struct perl_callback_state callback_state)
598             {
599             dTHX; /* fetch context */
600 449           av_undef(callback_state.filtered_tmpl_array);
601 449           av_undef(callback_state.pool_for_perl_vars);
602 449           SvREFCNT_dec(callback_state.filtered_tmpl_array);
603 449           SvREFCNT_dec(callback_state.pool_for_perl_vars);
604 449           tmplpro_param_free(param);
605 449           }
606              
607              
608              
609             MODULE = HTML::Template::Pro PACKAGE = HTML::Template::Pro
610              
611             void
612             _init()
613             CODE:
614 14           tmplpro_procore_init();
615              
616             void
617             _done()
618             CODE:
619 0           tmplpro_procore_done();
620              
621              
622             int
623             exec_tmpl(self_ptr,possible_output)
624             SV* self_ptr;
625             SV* possible_output;
626             PREINIT:
627 71           struct perl_callback_state callback_state = new_callback_state(self_ptr);
628 71           struct tmplpro_param* proparam=process_tmplpro_options(&callback_state);
629             CODE:
630 71 50         if (debuglevel>0) warn ("Pro.xs: entered exec_tmpl self=%p",self_ptr);
631             OutputStream output_stream;
632 71 50         SvGETMAGIC(possible_output);
    0          
633 71 50         if (!SvOK(possible_output)) {
    0          
    0          
634 0           tmplpro_set_option_WriterFuncPtr(proparam,NULL);
635             } else {
636 71           output_stream = IoOFP(sv_2io(possible_output));
637 71 50         if (output_stream == NULL){
638 0           warn("Pro.xs:output: bad file descriptor in print_to option. Use stdout\n");
639 0           tmplpro_set_option_WriterFuncPtr(proparam,NULL);
640             } else {
641 71           tmplpro_set_option_ext_writer_state(proparam,output_stream);
642 71           tmplpro_set_option_WriterFuncPtr(proparam,&write_chars_to_file);
643             }
644             }
645 71           RETVAL = tmplpro_exec_tmpl(proparam);
646 71           release_tmplpro_options(proparam,callback_state);
647 71 50         if (RETVAL!=0) warn ("Pro.xs: non-zero exit code %d",RETVAL);
648             OUTPUT:
649             RETVAL
650              
651              
652             SV*
653             exec_tmpl_string(self_ptr)
654             SV* self_ptr;
655             PREINIT:
656             int retstate;
657             /* made mortal automatically */
658             SV* outputString;
659 378           struct perl_callback_state callback_state = new_callback_state(self_ptr);
660 378           struct tmplpro_param* proparam=process_tmplpro_options(&callback_state);
661             CODE:
662 378 50         if (debuglevel>0) warn ("Pro.xs: entered exec_tmpl_string self=%p",self_ptr);
663 378           outputString=newSV(4000); /* 4000 allocated bytes -- should be approx. filesize*/
664 378           sv_setpvn(outputString, "", 0);
665 378           tmplpro_set_option_WriterFuncPtr(proparam,&write_chars_to_string);
666 378           tmplpro_set_option_ext_writer_state(proparam,outputString);
667 378           retstate = tmplpro_exec_tmpl(proparam);
668 378           release_tmplpro_options(proparam,callback_state);
669 378 50         if (retstate!=0) warn ("Pro.xs: non-zero exit code %d",retstate);
670 378           RETVAL = outputString;
671             OUTPUT:
672             RETVAL
673              
674              
675             SV*
676             exec_tmpl_string_builtin(self_ptr)
677             SV* self_ptr;
678             PREINIT:
679             int retstate;
680             SV* outputString;
681             PSTRING inString;
682 0           struct perl_callback_state callback_state = new_callback_state(self_ptr);
683 0           struct tmplpro_param* proparam=process_tmplpro_options(&callback_state);
684             CODE:
685 0           inString = tmplpro_tmpl2pstring(proparam, &retstate);
686 0           outputString=newSV(inString.endnext-inString.begin+2);
687 0           sv_setpvn(outputString, inString.begin, inString.endnext-inString.begin);
688 0           release_tmplpro_options(proparam,callback_state);
689 0 0         if (retstate!=0) warn ("Pro.xs: non-zero exit code %d",retstate);
690 0           RETVAL = outputString;
691             OUTPUT:
692             RETVAL
693