File Coverage

tags.inc
Criterion Covered Total %
statement 231 275 84.0
branch 135 172 78.4
condition n/a
subroutine n/a
pod n/a
total 366 447 81.8


line stmt bran cond sub pod time code
1             static
2 1141           int get_escape_option(struct tmplpro_state *state, PSTRING OptEscape)
3             {
4             /* int escape = HTML_TEMPLATE_OPT_ESCAPE_NO; */
5 1141           int escape = state->param->default_escape;
6 1141 100         if (OptEscape.begin
7 90           switch (*OptEscape.begin) {
8             case '1': case 'H': case 'h': /* HTML*/
9 60           escape = HTML_TEMPLATE_OPT_ESCAPE_HTML;
10 60           break;
11             case 'U': case 'u': /* URL */
12 13           escape = HTML_TEMPLATE_OPT_ESCAPE_URL;
13 13           break;
14             case 'J': case 'j': /* JS */
15 9           escape = HTML_TEMPLATE_OPT_ESCAPE_JS;
16 9           break;
17             case '0': case 'N': case 'n': /* 0 or NONE */
18 8           escape = HTML_TEMPLATE_OPT_ESCAPE_NO;
19 8           break;
20             default:
21 0           state->param->found_syntax_error=1;
22 0           log_state(state,TMPL_LOG_ERROR, " unsupported value of ESCAPE=%.*s\n",(int)(OptEscape.endnext-OptEscape.begin),OptEscape.begin);
23             }
24             }
25 1141           return escape;
26             }
27              
28             static
29 1394           void init_tmpl_var_case_buffers (struct tmplpro_param *param) {
30 1394           param->lowercase_varname.begin = NULL;
31 1394           param->lowercase_varname.endnext = NULL;
32 1394           param->uppercase_varname.begin = NULL;
33 1394           param->uppercase_varname.endnext = NULL;
34 1394           }
35              
36             static
37 1446           ABSTRACT_VALUE* get_abstract_value (struct tmplpro_param *param, int scope_level, PSTRING name) {
38 1446           ABSTRACT_VALUE* retval = NULL;
39 1446           ABSTRACT_MAP* param_HV = getScope(¶m->var_scope_stack, scope_level)->param_HV;
40 1446           ABSTRACT_DATASTATE* data_state = param->ext_data_state;
41 1446           get_ABSTRACT_VALUE_functype getval_func = param->GetAbstractValFuncPtr;
42 1446           int tmpl_var_case = param->tmpl_var_case;
43 1446 100         if ((tmpl_var_case & ASK_NAME_MASK) == ASK_NAME_DEFAULT
44 1427 100         || tmpl_var_case & ASK_NAME_AS_IS) {
45 63           retval = getval_func(data_state, param_HV, name);
46 63 100         if (retval != NULL) return retval;
47             }
48 1413 100         if (tmpl_var_case & ASK_NAME_LOWERCASE) {
49 987 100         if (param->lowercase_varname.begin == NULL) {
50 935           param->lowercase_varname=lowercase_pstring(¶m->lowercase_varname_buffer, name);
51             }
52 987           retval = getval_func(data_state, param_HV, param->lowercase_varname);
53 987 100         if (retval != NULL) return retval;
54             }
55 624 100         if (tmpl_var_case & ASK_NAME_UPPERCASE) {
56 426 50         if (param->uppercase_varname.begin == NULL) {
57 426           param->uppercase_varname=uppercase_pstring(¶m->uppercase_varname_buffer, name);
58             }
59 426           retval = getval_func(data_state, param_HV, param->uppercase_varname);
60 426 100         if (retval != NULL) return retval;
61             }
62 336           return retval;
63             }
64              
65             static
66 1394           ABSTRACT_VALUE* walk_through_nested_loops (struct tmplpro_param *param, PSTRING name) {
67             int CurLevel;
68             ABSTRACT_VALUE* valptr;
69 1394           init_tmpl_var_case_buffers (param);
70             /* Shigeki Morimoto path_like_variable_scope extension */
71 1394 100         if (param->path_like_variable_scope) {
72 13 100         if(*(name.begin) == '/' || strncmp(name.begin, "../", 3) == 0){
    100          
73             PSTRING tmp_name;
74             int GoalHash;
75 6 100         if(*(name.begin) == '/'){
76 4           tmp_name.begin = name.begin+1; // skip '/'
77 4           tmp_name.endnext = name.endnext;
78 4           GoalHash = 0;
79             }else{
80 2           tmp_name.begin = name.begin;
81 2           tmp_name.endnext = name.endnext;
82 2           GoalHash = curScopeLevel(¶m->var_scope_stack);
83 4 100         while(strncmp(tmp_name.begin, "../", 3) == 0){
84 2           tmp_name.begin = tmp_name.begin + 3; // skip '../'
85 2           GoalHash --;
86             }
87             }
88 6           return get_abstract_value(param, GoalHash, tmp_name);
89             }
90             }
91             /* end Shigeki Morimoto path_like_variable_scope extension */
92              
93 1388           CurLevel = curScopeLevel(¶m->var_scope_stack);
94 1388           valptr = get_abstract_value(param, CurLevel, name);
95 1388 100         if (valptr) return valptr;
96             /* optional strict scoping; does it have much sence?
97             if ((STRICT_SCOPING==param->global_vars)) return NULL;
98             */
99              
100             /* loop-bounded scoping; */
101 322 100         if (0==param->global_vars) {
102 286 100         while (isScopeMap(getScope(¶m->var_scope_stack,CurLevel)) && --CurLevel>=0) {
    100          
103 2           valptr = get_abstract_value(param, CurLevel, name);
104 2 50         if (valptr!=NULL) return valptr;
105             }
106 284           return NULL;
107             }
108              
109 50 50         while (--CurLevel>=0) {
110 50           valptr = get_abstract_value(param, CurLevel, name);
111 50 100         if (valptr!=NULL) return valptr;
112             }
113 0           return NULL;
114             }
115              
116             TMPLPRO_LOCAL
117 1028           PSTRING _get_variable_value (struct tmplpro_param *param, PSTRING name) {
118 1028           PSTRING varvalue ={NULL, NULL};
119             ABSTRACT_VALUE* abstrval;
120 1028 100         if (param->loop_context_vars) {
121 768           varvalue=get_loop_context_vars_value(param, name);
122             }
123 1028 100         if (varvalue.begin==NULL) {
124 857           abstrval=walk_through_nested_loops(param, name);
125 857 100         if (abstrval!=NULL) varvalue=(param->AbstractVal2pstringFuncPtr)(param->ext_data_state, abstrval);
126             }
127 1028 50         if (debuglevel>=TMPL_LOG_DEBUG2) {
128 0 0         if (name.begin!=NULL) {
129 0           tmpl_log(TMPL_LOG_DEBUG2,"_get_variable_value: name = %.*s ",(int)(name.endnext-name.begin),name.begin);
130             } else {
131 0           tmpl_log(TMPL_LOG_DEBUG2,"_get_variable_value: name = NULL ");
132             }
133 0 0         if (varvalue.begin!=NULL) {
134 0           tmpl_log(TMPL_LOG_DEBUG2,"value = %.*s\n",(int)(varvalue.endnext-varvalue.begin),varvalue.begin);
135             } else {
136 0           tmpl_log(TMPL_LOG_DEBUG2,"value = UNDEF\n");
137             }
138             }
139 1028           return varvalue;
140             }
141              
142             static
143 1141           PSTRING get_variable_option (struct tmplpro_state *state, const PSTRING* const TagOptVal) {
144 1141           PSTRING varvalue ={NULL, NULL};
145 1141           PSTRING defvalue = TagOptVal[TAG_OPT_DEFAULT];
146 1141 100         if (TagOptVal[TAG_OPT_EXPR].begin!=NULL) {
147 477           varvalue=parse_expr(TagOptVal[TAG_OPT_EXPR], state);
148             } else {
149 664           varvalue=_get_variable_value(state->param, TagOptVal[TAG_OPT_NAME]);
150             }
151 1141 100         if (varvalue.begin==NULL) {
152 120 100         if (defvalue.begin!=defvalue.endnext) {
153 27           varvalue=defvalue;
154             }
155             }
156 1141           return varvalue;
157             }
158              
159              
160             static
161             void
162 1422           tag_handler_var (struct tmplpro_state *state, const PSTRING* const TagOptVal)
163             {
164             PSTRING varvalue;
165             int escapeopt;
166             /*
167             if (debuglevel>=TMPL_LOG_DEBUG2) {
168             log_state(state,TMPL_LOG_DEBUG2,"Entered tag_handler_var\n");
169             }*/
170 1515 100         if (! state->is_visible) return;
171 1141           varvalue = get_variable_option(state, TagOptVal);
172 1141           escapeopt = get_escape_option(state,TagOptVal[TAG_OPT_ESCAPE]);
173 1141 100         if (varvalue.begin==NULL) return;
174              
175 1048 100         if (escapeopt!=HTML_TEMPLATE_OPT_ESCAPE_NO) {
176 94           varvalue=escape_pstring(&state->param->escape_pstring_buffer, varvalue, escapeopt);
177             }
178 1048           (state->param->WriterFuncPtr)(state->param->ext_writer_state,varvalue.begin,varvalue.endnext);
179             }
180              
181             static
182             void
183 83           tag_handler_include (struct tmplpro_state *state, const PSTRING* const TagOptVal)
184             {
185             struct tmplpro_param* param;
186             char* filename;
187             int x;
188             PSTRING varvalue;
189             PSTRING defvalue;
190              
191 83 100         if (! state->is_visible) return;
192 79           param=state->param;
193 79 50         if (param->no_includes) {
194 0           log_state(state,TMPL_LOG_ERROR, "HTML::Template::Pro : Illegal attempt to use TMPL_INCLUDE in template file : (no_includes => 1)\n");
195 0           return;
196             }
197 79 50         if (param->max_includes && param->max_includes < param->cur_includes) {
    100          
198 2           log_state(state,TMPL_LOG_INFO, "HTML::Template::Pro : TMPL_INCLUDE: max_includes exceeded.\n");
199 2           return;
200             }
201 77           param->cur_includes++;
202              
203 77           varvalue=TagOptVal[TAG_OPT_NAME];
204 77           defvalue = TagOptVal[TAG_OPT_DEFAULT];
205              
206 77 100         if (TagOptVal[TAG_OPT_EXPR].begin!=NULL) {
207 4           varvalue=parse_expr(TagOptVal[TAG_OPT_EXPR], state);
208             };
209 77 50         if (varvalue.begin==varvalue.endnext && defvalue.begin!=defvalue.endnext) varvalue=defvalue;
    0          
210             /* pstrdup */
211             {
212 77           const long len = varvalue.endnext-varvalue.begin;
213 77           filename =(char*) malloc(len+1);
214 1138 100         for (x=0;x
215 1061           *(filename+x)=*(varvalue.begin+x);
216             }
217 77           *(filename+len)=0;
218             }
219             /* end pstrdup */
220 77           tmplpro_exec_tmpl_filename (param,filename);
221 77           free (filename);
222 77           param->cur_includes--;
223 83           return;
224             }
225              
226             static
227             int
228 506           is_var_true(struct tmplpro_state *state, const PSTRING* const TagOptVal)
229             {
230 506           register int ifval=-1; /*not yet defined*/
231 506 100         if (TagOptVal[TAG_OPT_EXPR].begin!=NULL) {
232             /*
233             if (debuglevel>=TMPL_LOG_DEBUG2) {
234             tmpl_log(TMPL_LOG_DEBUG2,"is_var_true: expr = %.*s\n",(int)(TagOptVal[TAG_OPT_EXPR].endnext-TagOptVal[TAG_OPT_EXPR].begin),TagOptVal[TAG_OPT_EXPR].begin);
235             }*/
236 70           ifval=is_pstring_true(parse_expr(TagOptVal[TAG_OPT_EXPR], state));
237             } else
238 436 100         if (state->param->loop_context_vars) {
239 220           PSTRING loop_var=get_loop_context_vars_value(state->param, TagOptVal[TAG_OPT_NAME]);
240 220 100         if (loop_var.begin!=NULL) {
241 220           ifval=is_pstring_true(loop_var);
242             }
243             }
244 506 100         if (ifval==-1) {
245             is_ABSTRACT_VALUE_true_functype userSuppliedIsTrueFunc;
246 416           ABSTRACT_VALUE* abstrval=walk_through_nested_loops(state->param, TagOptVal[TAG_OPT_NAME]);
247 416 100         if (abstrval==NULL) return 0;
248 304           userSuppliedIsTrueFunc = state->param->IsAbstractValTrueFuncPtr;
249 304 50         if (userSuppliedIsTrueFunc!=NULL) {
250 304           ifval=(userSuppliedIsTrueFunc)(state->param->ext_data_state, abstrval);
251             } else {
252 0           ifval=is_pstring_true((state->param->AbstractVal2pstringFuncPtr)(state->param->ext_data_state, abstrval));
253             }
254             }
255 394           return ifval;
256             }
257              
258             static
259             void
260 502           tag_handler_if (struct tmplpro_state *state, const PSTRING* const TagOptVal)
261             {
262             struct tagstack_entry iftag;
263 502           iftag.tag=HTML_TEMPLATE_TAG_IF;
264 502           iftag.vcontext=state->is_visible;
265 502           iftag.position=state->cur_pos; /* unused */
266             /* state->is_visible && means that we do not evaluate variable in shadow */
267 502 100         if (state->is_visible && is_var_true(state,TagOptVal)) {
    100          
268 230           iftag.value=1;
269             /* state->is_visible is not touched */
270             } else {
271 272           iftag.value=0;
272 272           state->is_visible=0;
273             }
274 502           tagstack_push(&(state->tag_stack), iftag);
275 502 50         if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"tag_handler_if:visible context =%d value=%d ",iftag.vcontext,iftag.value);
276 502           }
277              
278             static
279             void
280 50           tag_handler_unless (struct tmplpro_state *state, const PSTRING* const TagOptVal)
281             {
282             struct tagstack_entry iftag;
283 50           iftag.tag=HTML_TEMPLATE_TAG_UNLESS;
284 50           iftag.vcontext=state->is_visible;
285 50           iftag.position=state->cur_pos; /* unused */
286             /* state->is_visible && means that we do not evaluate variable in shadow */
287 50 100         if (state->is_visible && !is_var_true(state,TagOptVal)) {
    100          
288 29           iftag.value=1;
289             /* state->is_visible is not touched */
290             } else {
291 21           iftag.value=0;
292 21           state->is_visible=0;
293             }
294 50           tagstack_push(&(state->tag_stack), iftag);
295 50 50         if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"tag_handler_unless:visible context =%d value=%d ",iftag.vcontext,iftag.value);
296 50           }
297              
298             static
299             INLINE
300             int
301 1212           test_stack (int tag)
302             {
303             // return (tagstack_notempty(&(state->tag_stack)) && (tagstack_top(&(state->tag_stack))->tag==tag));
304 1212           return 1;
305             }
306              
307             static
308             void
309 0           tag_stack_debug (struct tmplpro_state *state, int stack_tag_type)
310             {
311 0 0         if (stack_tag_type) {
312 0 0         if (tagstack_notempty(&(state->tag_stack))) {
313 0           struct tagstack_entry* iftag=tagstack_top(&(state->tag_stack));
314 0 0         if (iftag->tag!=stack_tag_type) {
315 0           log_state(state,TMPL_LOG_ERROR, "ERROR: tag mismatch with %s\n",TAGNAME[iftag->tag]);
316             }
317             } else {
318 0           log_state(state,TMPL_LOG_ERROR, "ERROR: opening tag %s not found\n",TAGNAME[stack_tag_type]);
319             }
320             }
321 0           }
322              
323             static
324 678           struct tagstack_entry tagstack_smart_pop(struct tmplpro_state *state)
325             {
326 678           int is_underflow=0;
327 678           struct tagstack_entry curtag=tagstack_pop(&(state->tag_stack), &is_underflow);
328 678 100         if (is_underflow) {
329 1           log_state(state,TMPL_LOG_ERROR,"stack underflow:tag stack is empty. Cased by closing tag w/o matching opening tag.\n");
330             }
331 678           return curtag;
332             }
333              
334             static
335             void
336 506           tag_handler_closeif (struct tmplpro_state *state, const PSTRING* const TagOptVal)
337             {
338             struct tagstack_entry iftag;
339 506 50         if (! test_stack(HTML_TEMPLATE_TAG_IF)) {
340 0           tag_stack_debug(state,HTML_TEMPLATE_TAG_IF);
341 0           return;
342             }
343 506           iftag=tagstack_smart_pop(state);
344 506 100         if (0==state->is_visible) state->last_processed_pos=state->cur_pos;
345 506           state->is_visible=iftag.vcontext;
346             }
347              
348             static
349             void
350 46           tag_handler_closeunless (struct tmplpro_state *state, const PSTRING* const TagOptVal)
351             {
352             struct tagstack_entry iftag;
353 46 50         if (! test_stack(HTML_TEMPLATE_TAG_UNLESS)) {
354 0           tag_stack_debug(state,HTML_TEMPLATE_TAG_UNLESS);
355 0           return;
356             }
357 46           iftag=tagstack_smart_pop(state);
358 46 100         if (0==state->is_visible) state->last_processed_pos=state->cur_pos;
359 46           state->is_visible=iftag.vcontext;
360             }
361              
362             static
363             void
364 406           tag_handler_else (struct tmplpro_state *state, const PSTRING* const TagOptVal)
365             {
366             struct tagstack_entry* iftag;
367 406           if (! test_stack(HTML_TEMPLATE_TAG_IF) &&
368 0           ! test_stack(HTML_TEMPLATE_TAG_UNLESS)) {
369 0           tag_stack_debug(state,HTML_TEMPLATE_TAG_ELSE);
370 0           return;
371             }
372 406           iftag=tagstack_top(&(state->tag_stack));
373 406 100         if (0==state->is_visible) state->last_processed_pos=state->cur_pos;
374 406 100         if (iftag->value) {
375 188           state->is_visible=0;
376 218 100         } else if (1==iftag->vcontext) {
377 192           state->is_visible=1;
378             }
379 406 50         if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"else:(pos " MOD_TD ") visible:context =%d, set to %d ",
380 0           TO_PTRDIFF_T(iftag->position - state->top),iftag->vcontext,state->is_visible);
381             }
382              
383             static
384             void
385 8           tag_handler_elsif (struct tmplpro_state *state, const PSTRING* const TagOptVal)
386             {
387             struct tagstack_entry *iftag;
388 8           if (! test_stack(HTML_TEMPLATE_TAG_IF) &&
389 0           ! test_stack(HTML_TEMPLATE_TAG_UNLESS)) {
390 0           tag_stack_debug(state,HTML_TEMPLATE_TAG_ELSIF);
391 0           return;
392             }
393 8           iftag=tagstack_top(&(state->tag_stack));
394 8 100         if (0==state->is_visible) state->last_processed_pos=state->cur_pos;
395 8 100         if (iftag->value) {
396 4           state->is_visible=0;
397 4 50         } else if (1==iftag->vcontext) {
398             /* test only if vcontext==true; if the whole tag if..endif itself is invisible, skip the is_var_true test */
399             /*TODO: it is reasonable to skip is_var_true test in if/unless too */
400 4 50         if (is_var_true(state,TagOptVal)) {
401 4           iftag->value=1;
402 4           state->is_visible=1;
403             } else {
404 0           iftag->value=0;
405 0           state->is_visible=0;
406             }
407             }
408 8 50         if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"elsif:(pos " MOD_TD ") visible:context =%d, set to %d ",
409 0           TO_PTRDIFF_T(iftag->position - state->top), iftag->vcontext, state->is_visible);
410             }
411              
412             static
413             int
414 254           next_loop (struct tmplpro_state* state) {
415             #ifdef DEBUG
416             log_state(state,TMPL_LOG_DEBUG2,"next_loop:before NextLoopFuncPtr\n");
417             #endif
418 254           struct ProScopeEntry* currentScope = getCurrentScope(&state->param->var_scope_stack);
419 254 50         if (!isScopeLoop(currentScope)) {
420 0           log_state(state,TMPL_LOG_ERROR, "next_loop:at scope level %d: internal error - loop is null\n", curScopeLevel(&state->param->var_scope_stack));
421 0           return 0;
422             }
423 254 100         if (++currentScope->loop < currentScope->loop_count || currentScope->loop_count< 0) {
    50          
424 187           ABSTRACT_MAP* arrayvalptr=(state->param->GetAbstractMapFuncPtr)(state->param->ext_data_state, currentScope->loops_AV,currentScope->loop);
425 187 50         if ((arrayvalptr!=NULL)) {
426 187           currentScope->param_HV=arrayvalptr;
427 187           return 1;
428             } else {
429             /* either undefined loop ended normally or defined loop ended ubnormally */
430 0 0         if (currentScope->loop_count>0) log_state(state,TMPL_LOG_ERROR, "PARAM:LOOP:next_loop(%d): callback returned null scope\n", currentScope->loop);
431             }
432             }
433 67 50         if (state->param->ExitLoopScopeFuncPtr) state->param->ExitLoopScopeFuncPtr(state->param->ext_data_state, currentScope->loops_AV);
434 67           popScope(&state->param->var_scope_stack);
435 67           return 0;
436             }
437              
438             static
439 121           int init_loop (struct tmplpro_state *state, const PSTRING* const TagOptVal) {
440             int loop_count;
441 121           ABSTRACT_ARRAY* loopptr=(ABSTRACT_ARRAY*) walk_through_nested_loops(state->param,TagOptVal[TAG_OPT_NAME]);
442 121 100         if (loopptr==NULL) {
443 46           return 0;
444             } else {
445             /* set loop array */
446 75           loopptr = (*state->param->AbstractVal2abstractArrayFuncPtr)(state->param->ext_data_state, loopptr);
447 75 50         if (loopptr == NULL)
448             {
449 0           log_state(state,TMPL_LOG_ERROR, "PARAM:LOOP:loop argument:loop was expected but not found.\n");
450 0           return 0;
451             }
452 75           loop_count = (*state->param->GetAbstractArrayLengthFuncPtr)(state->param->ext_data_state, loopptr);
453             /* 0 is an empty array; <0 is an undefined array (iterated until next_loop==NULL */
454 75 100         if (0==loop_count) return 0;
455 67           pushScopeLoop(&state->param->var_scope_stack, loop_count, loopptr);
456 67           return 1;
457             }
458             }
459              
460             static
461             void
462 126           tag_handler_loop (struct tmplpro_state *state, const PSTRING* const TagOptVal)
463             {
464             struct tagstack_entry iftag;
465 126           iftag.tag=HTML_TEMPLATE_TAG_LOOP;
466 126           iftag.vcontext=state->is_visible;
467 126           iftag.value=0;
468 126           iftag.position=state->cur_pos; /* loop start - to restore in */
469             #ifdef DEBUG
470             log_state(state,TMPL_LOG_DEBUG2,"tag_handler_loop:before InitLoopFuncPtr\n");
471             #endif
472 126 100         if (state->is_visible && init_loop(state,TagOptVal) && next_loop(state)) {
    100          
    50          
473 67           iftag.value=1; /* the loop is non - empty */
474             } else {
475             /* empty loop is equal to ... */
476 59           state->is_visible=0;
477             }
478             #ifdef DEBUG
479             log_state(state,TMPL_LOG_DEBUG2,"tag_handler_loop:after InitLoopFuncPtr\n");
480             #endif
481 126           tagstack_push(&(state->tag_stack), iftag);
482 126           }
483              
484             static
485             void
486 246           tag_handler_closeloop (struct tmplpro_state *state, const PSTRING* const TagOptVal)
487             {
488             struct tagstack_entry* iftag_ptr;
489 246 50         if (! test_stack(HTML_TEMPLATE_TAG_LOOP)) {
490 0           tag_stack_debug(state,HTML_TEMPLATE_TAG_LOOP);
491 0           return;
492             }
493 246           iftag_ptr=tagstack_top(&(state->tag_stack));
494 246 100         if (iftag_ptr->value==1 && next_loop(state)) {
    100          
495             /* continue loop */
496 120           state->cur_pos=iftag_ptr->position;
497 120           state->last_processed_pos=iftag_ptr->position;
498 120           return;
499             } else {
500             /* finish loop */
501             struct tagstack_entry iftag;
502 126           iftag=tagstack_smart_pop(state);
503 126           state->is_visible=iftag.vcontext;
504 126           state->last_processed_pos=state->cur_pos;
505             }
506             }
507              
508             static
509             void
510 0           tag_handler_unknown (struct tmplpro_state *state, const PSTRING* const TagOptVal)
511             {
512 0           log_state(state,TMPL_LOG_ERROR,"tag_handler_unknown: unknown tag\n");
513 0           }
514              
515             /*
516             * Local Variables:
517             * mode: c
518             * End:
519             */