static int get_escape_option(struct tmplpro_state *state, PSTRING OptEscape) { /* int escape = HTML_TEMPLATE_OPT_ESCAPE_NO; */ int escape = state->param->default_escape; if (OptEscape.beginparam->found_syntax_error=1; log_state(state,TMPL_LOG_ERROR, " unsupported value of ESCAPE=%.*s\n",(int)(OptEscape.endnext-OptEscape.begin),OptEscape.begin); } } return escape; } static void init_tmpl_var_case_buffers (struct tmplpro_param *param) { param->lowercase_varname.begin = NULL; param->lowercase_varname.endnext = NULL; param->uppercase_varname.begin = NULL; param->uppercase_varname.endnext = NULL; } static ABSTRACT_VALUE* get_abstract_value (struct tmplpro_param *param, int scope_level, PSTRING name) { ABSTRACT_VALUE* retval = NULL; ABSTRACT_MAP* param_HV = getScope(¶m->var_scope_stack, scope_level)->param_HV; ABSTRACT_DATASTATE* data_state = param->ext_data_state; get_ABSTRACT_VALUE_functype getval_func = param->GetAbstractValFuncPtr; int tmpl_var_case = param->tmpl_var_case; if ((tmpl_var_case & ASK_NAME_MASK) == ASK_NAME_DEFAULT || tmpl_var_case & ASK_NAME_AS_IS) { retval = getval_func(data_state, param_HV, name); if (retval != NULL) return retval; } if (tmpl_var_case & ASK_NAME_LOWERCASE) { if (param->lowercase_varname.begin == NULL) { param->lowercase_varname=lowercase_pstring(¶m->lowercase_varname_buffer, name); } retval = getval_func(data_state, param_HV, param->lowercase_varname); if (retval != NULL) return retval; } if (tmpl_var_case & ASK_NAME_UPPERCASE) { if (param->uppercase_varname.begin == NULL) { param->uppercase_varname=uppercase_pstring(¶m->uppercase_varname_buffer, name); } retval = getval_func(data_state, param_HV, param->uppercase_varname); if (retval != NULL) return retval; } return retval; } static ABSTRACT_VALUE* walk_through_nested_loops (struct tmplpro_param *param, PSTRING name) { int CurLevel; ABSTRACT_VALUE* valptr; init_tmpl_var_case_buffers (param); /* Shigeki Morimoto path_like_variable_scope extension */ if (param->path_like_variable_scope) { if(*(name.begin) == '/' || strncmp(name.begin, "../", 3) == 0){ PSTRING tmp_name; int GoalHash; if(*(name.begin) == '/'){ tmp_name.begin = name.begin+1; // skip '/' tmp_name.endnext = name.endnext; GoalHash = 0; }else{ tmp_name.begin = name.begin; tmp_name.endnext = name.endnext; GoalHash = curScopeLevel(¶m->var_scope_stack); while(strncmp(tmp_name.begin, "../", 3) == 0){ tmp_name.begin = tmp_name.begin + 3; // skip '../' GoalHash --; } } return get_abstract_value(param, GoalHash, tmp_name); } } /* end Shigeki Morimoto path_like_variable_scope extension */ CurLevel = curScopeLevel(¶m->var_scope_stack); valptr = get_abstract_value(param, CurLevel, name); if (valptr) return valptr; /* optional strict scoping; does it have much sence? if ((STRICT_SCOPING==param->global_vars)) return NULL; */ /* loop-bounded scoping; */ if (0==param->global_vars) { while (isScopeMap(getScope(¶m->var_scope_stack,CurLevel)) && --CurLevel>=0) { valptr = get_abstract_value(param, CurLevel, name); if (valptr!=NULL) return valptr; } return NULL; } while (--CurLevel>=0) { valptr = get_abstract_value(param, CurLevel, name); if (valptr!=NULL) return valptr; } return NULL; } TMPLPRO_LOCAL PSTRING _get_variable_value (struct tmplpro_param *param, PSTRING name) { PSTRING varvalue ={NULL, NULL}; ABSTRACT_VALUE* abstrval; if (param->loop_context_vars) { varvalue=get_loop_context_vars_value(param, name); } if (varvalue.begin==NULL) { abstrval=walk_through_nested_loops(param, name); if (abstrval!=NULL) varvalue=(param->AbstractVal2pstringFuncPtr)(param->ext_data_state, abstrval); } if (debuglevel>=TMPL_LOG_DEBUG2) { if (name.begin!=NULL) { tmpl_log(TMPL_LOG_DEBUG2,"_get_variable_value: name = %.*s ",(int)(name.endnext-name.begin),name.begin); } else { tmpl_log(TMPL_LOG_DEBUG2,"_get_variable_value: name = NULL "); } if (varvalue.begin!=NULL) { tmpl_log(TMPL_LOG_DEBUG2,"value = %.*s\n",(int)(varvalue.endnext-varvalue.begin),varvalue.begin); } else { tmpl_log(TMPL_LOG_DEBUG2,"value = UNDEF\n"); } } return varvalue; } static PSTRING get_variable_option (struct tmplpro_state *state, const PSTRING* const TagOptVal) { PSTRING varvalue ={NULL, NULL}; PSTRING defvalue = TagOptVal[TAG_OPT_DEFAULT]; if (TagOptVal[TAG_OPT_EXPR].begin!=NULL) { varvalue=parse_expr(TagOptVal[TAG_OPT_EXPR], state); } else { varvalue=_get_variable_value(state->param, TagOptVal[TAG_OPT_NAME]); } if (varvalue.begin==NULL) { if (defvalue.begin!=defvalue.endnext) { varvalue=defvalue; } } return varvalue; } static void tag_handler_var (struct tmplpro_state *state, const PSTRING* const TagOptVal) { PSTRING varvalue; int escapeopt; /* if (debuglevel>=TMPL_LOG_DEBUG2) { log_state(state,TMPL_LOG_DEBUG2,"Entered tag_handler_var\n"); }*/ if (! state->is_visible) return; varvalue = get_variable_option(state, TagOptVal); escapeopt = get_escape_option(state,TagOptVal[TAG_OPT_ESCAPE]); if (varvalue.begin==NULL) return; if (escapeopt!=HTML_TEMPLATE_OPT_ESCAPE_NO) { varvalue=escape_pstring(&state->param->escape_pstring_buffer, varvalue, escapeopt); } (state->param->WriterFuncPtr)(state->param->ext_writer_state,varvalue.begin,varvalue.endnext); } static void tag_handler_include (struct tmplpro_state *state, const PSTRING* const TagOptVal) { struct tmplpro_param* param; char* filename; int x; PSTRING varvalue; PSTRING defvalue; if (! state->is_visible) return; param=state->param; if (param->no_includes) { log_state(state,TMPL_LOG_ERROR, "HTML::Template::Pro : Illegal attempt to use TMPL_INCLUDE in template file : (no_includes => 1)\n"); return; } if (param->max_includes && param->max_includes < param->cur_includes) { log_state(state,TMPL_LOG_INFO, "HTML::Template::Pro : TMPL_INCLUDE: max_includes exceeded.\n"); return; } param->cur_includes++; varvalue=TagOptVal[TAG_OPT_NAME]; defvalue = TagOptVal[TAG_OPT_DEFAULT]; if (TagOptVal[TAG_OPT_EXPR].begin!=NULL) { varvalue=parse_expr(TagOptVal[TAG_OPT_EXPR], state); }; if (varvalue.begin==varvalue.endnext && defvalue.begin!=defvalue.endnext) varvalue=defvalue; /* pstrdup */ { const long len = varvalue.endnext-varvalue.begin; filename =(char*) malloc(len+1); for (x=0;xcur_includes--; return; } static int is_var_true(struct tmplpro_state *state, const PSTRING* const TagOptVal) { register int ifval=-1; /*not yet defined*/ if (TagOptVal[TAG_OPT_EXPR].begin!=NULL) { /* if (debuglevel>=TMPL_LOG_DEBUG2) { 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); }*/ ifval=is_pstring_true(parse_expr(TagOptVal[TAG_OPT_EXPR], state)); } else if (state->param->loop_context_vars) { PSTRING loop_var=get_loop_context_vars_value(state->param, TagOptVal[TAG_OPT_NAME]); if (loop_var.begin!=NULL) { ifval=is_pstring_true(loop_var); } } if (ifval==-1) { is_ABSTRACT_VALUE_true_functype userSuppliedIsTrueFunc; ABSTRACT_VALUE* abstrval=walk_through_nested_loops(state->param, TagOptVal[TAG_OPT_NAME]); if (abstrval==NULL) return 0; userSuppliedIsTrueFunc = state->param->IsAbstractValTrueFuncPtr; if (userSuppliedIsTrueFunc!=NULL) { ifval=(userSuppliedIsTrueFunc)(state->param->ext_data_state, abstrval); } else { ifval=is_pstring_true((state->param->AbstractVal2pstringFuncPtr)(state->param->ext_data_state, abstrval)); } } return ifval; } static void tag_handler_if (struct tmplpro_state *state, const PSTRING* const TagOptVal) { struct tagstack_entry iftag; iftag.tag=HTML_TEMPLATE_TAG_IF; iftag.vcontext=state->is_visible; iftag.position=state->cur_pos; /* unused */ /* state->is_visible && means that we do not evaluate variable in shadow */ if (state->is_visible && is_var_true(state,TagOptVal)) { iftag.value=1; /* state->is_visible is not touched */ } else { iftag.value=0; state->is_visible=0; } tagstack_push(&(state->tag_stack), iftag); if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"tag_handler_if:visible context =%d value=%d ",iftag.vcontext,iftag.value); } static void tag_handler_unless (struct tmplpro_state *state, const PSTRING* const TagOptVal) { struct tagstack_entry iftag; iftag.tag=HTML_TEMPLATE_TAG_UNLESS; iftag.vcontext=state->is_visible; iftag.position=state->cur_pos; /* unused */ /* state->is_visible && means that we do not evaluate variable in shadow */ if (state->is_visible && !is_var_true(state,TagOptVal)) { iftag.value=1; /* state->is_visible is not touched */ } else { iftag.value=0; state->is_visible=0; } tagstack_push(&(state->tag_stack), iftag); if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"tag_handler_unless:visible context =%d value=%d ",iftag.vcontext,iftag.value); } static INLINE int test_stack (int tag) { // return (tagstack_notempty(&(state->tag_stack)) && (tagstack_top(&(state->tag_stack))->tag==tag)); return 1; } static void tag_stack_debug (struct tmplpro_state *state, int stack_tag_type) { if (stack_tag_type) { if (tagstack_notempty(&(state->tag_stack))) { struct tagstack_entry* iftag=tagstack_top(&(state->tag_stack)); if (iftag->tag!=stack_tag_type) { log_state(state,TMPL_LOG_ERROR, "ERROR: tag mismatch with %s\n",TAGNAME[iftag->tag]); } } else { log_state(state,TMPL_LOG_ERROR, "ERROR: opening tag %s not found\n",TAGNAME[stack_tag_type]); } } } static struct tagstack_entry tagstack_smart_pop(struct tmplpro_state *state) { int is_underflow=0; struct tagstack_entry curtag=tagstack_pop(&(state->tag_stack), &is_underflow); if (is_underflow) { log_state(state,TMPL_LOG_ERROR,"stack underflow:tag stack is empty. Cased by closing tag w/o matching opening tag.\n"); } return curtag; } static void tag_handler_closeif (struct tmplpro_state *state, const PSTRING* const TagOptVal) { struct tagstack_entry iftag; if (! test_stack(HTML_TEMPLATE_TAG_IF)) { tag_stack_debug(state,HTML_TEMPLATE_TAG_IF); return; } iftag=tagstack_smart_pop(state); if (0==state->is_visible) state->last_processed_pos=state->cur_pos; state->is_visible=iftag.vcontext; } static void tag_handler_closeunless (struct tmplpro_state *state, const PSTRING* const TagOptVal) { struct tagstack_entry iftag; if (! test_stack(HTML_TEMPLATE_TAG_UNLESS)) { tag_stack_debug(state,HTML_TEMPLATE_TAG_UNLESS); return; } iftag=tagstack_smart_pop(state); if (0==state->is_visible) state->last_processed_pos=state->cur_pos; state->is_visible=iftag.vcontext; } static void tag_handler_else (struct tmplpro_state *state, const PSTRING* const TagOptVal) { struct tagstack_entry* iftag; if (! test_stack(HTML_TEMPLATE_TAG_IF) && ! test_stack(HTML_TEMPLATE_TAG_UNLESS)) { tag_stack_debug(state,HTML_TEMPLATE_TAG_ELSE); return; } iftag=tagstack_top(&(state->tag_stack)); if (0==state->is_visible) state->last_processed_pos=state->cur_pos; if (iftag->value) { state->is_visible=0; } else if (1==iftag->vcontext) { state->is_visible=1; } if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"else:(pos " MOD_TD ") visible:context =%d, set to %d ", TO_PTRDIFF_T(iftag->position - state->top),iftag->vcontext,state->is_visible); } static void tag_handler_elsif (struct tmplpro_state *state, const PSTRING* const TagOptVal) { struct tagstack_entry *iftag; if (! test_stack(HTML_TEMPLATE_TAG_IF) && ! test_stack(HTML_TEMPLATE_TAG_UNLESS)) { tag_stack_debug(state,HTML_TEMPLATE_TAG_ELSIF); return; } iftag=tagstack_top(&(state->tag_stack)); if (0==state->is_visible) state->last_processed_pos=state->cur_pos; if (iftag->value) { state->is_visible=0; } else if (1==iftag->vcontext) { /* test only if vcontext==true; if the whole tag if..endif itself is invisible, skip the is_var_true test */ /*TODO: it is reasonable to skip is_var_true test in if/unless too */ if (is_var_true(state,TagOptVal)) { iftag->value=1; state->is_visible=1; } else { iftag->value=0; state->is_visible=0; } } if (debuglevel>=TMPL_LOG_DEBUG2) log_state(state,TMPL_LOG_DEBUG2,"elsif:(pos " MOD_TD ") visible:context =%d, set to %d ", TO_PTRDIFF_T(iftag->position - state->top), iftag->vcontext, state->is_visible); } static int next_loop (struct tmplpro_state* state) { #ifdef DEBUG log_state(state,TMPL_LOG_DEBUG2,"next_loop:before NextLoopFuncPtr\n"); #endif struct ProScopeEntry* currentScope = getCurrentScope(&state->param->var_scope_stack); if (!isScopeLoop(currentScope)) { log_state(state,TMPL_LOG_ERROR, "next_loop:at scope level %d: internal error - loop is null\n", curScopeLevel(&state->param->var_scope_stack)); return 0; } if (++currentScope->loop < currentScope->loop_count || currentScope->loop_count< 0) { ABSTRACT_MAP* arrayvalptr=(state->param->GetAbstractMapFuncPtr)(state->param->ext_data_state, currentScope->loops_AV,currentScope->loop); if ((arrayvalptr!=NULL)) { currentScope->param_HV=arrayvalptr; return 1; } else { /* either undefined loop ended normally or defined loop ended ubnormally */ if (currentScope->loop_count>0) log_state(state,TMPL_LOG_ERROR, "PARAM:LOOP:next_loop(%d): callback returned null scope\n", currentScope->loop); } } if (state->param->ExitLoopScopeFuncPtr) state->param->ExitLoopScopeFuncPtr(state->param->ext_data_state, currentScope->loops_AV); popScope(&state->param->var_scope_stack); return 0; } static int init_loop (struct tmplpro_state *state, const PSTRING* const TagOptVal) { int loop_count; ABSTRACT_ARRAY* loopptr=(ABSTRACT_ARRAY*) walk_through_nested_loops(state->param,TagOptVal[TAG_OPT_NAME]); if (loopptr==NULL) { return 0; } else { /* set loop array */ loopptr = (*state->param->AbstractVal2abstractArrayFuncPtr)(state->param->ext_data_state, loopptr); if (loopptr == NULL) { log_state(state,TMPL_LOG_ERROR, "PARAM:LOOP:loop argument:loop was expected but not found.\n"); return 0; } loop_count = (*state->param->GetAbstractArrayLengthFuncPtr)(state->param->ext_data_state, loopptr); /* 0 is an empty array; <0 is an undefined array (iterated until next_loop==NULL */ if (0==loop_count) return 0; pushScopeLoop(&state->param->var_scope_stack, loop_count, loopptr); return 1; } } static void tag_handler_loop (struct tmplpro_state *state, const PSTRING* const TagOptVal) { struct tagstack_entry iftag; iftag.tag=HTML_TEMPLATE_TAG_LOOP; iftag.vcontext=state->is_visible; iftag.value=0; iftag.position=state->cur_pos; /* loop start - to restore in */ #ifdef DEBUG log_state(state,TMPL_LOG_DEBUG2,"tag_handler_loop:before InitLoopFuncPtr\n"); #endif if (state->is_visible && init_loop(state,TagOptVal) && next_loop(state)) { iftag.value=1; /* the loop is non - empty */ } else { /* empty loop is equal to ... */ state->is_visible=0; } #ifdef DEBUG log_state(state,TMPL_LOG_DEBUG2,"tag_handler_loop:after InitLoopFuncPtr\n"); #endif tagstack_push(&(state->tag_stack), iftag); } static void tag_handler_closeloop (struct tmplpro_state *state, const PSTRING* const TagOptVal) { struct tagstack_entry* iftag_ptr; if (! test_stack(HTML_TEMPLATE_TAG_LOOP)) { tag_stack_debug(state,HTML_TEMPLATE_TAG_LOOP); return; } iftag_ptr=tagstack_top(&(state->tag_stack)); if (iftag_ptr->value==1 && next_loop(state)) { /* continue loop */ state->cur_pos=iftag_ptr->position; state->last_processed_pos=iftag_ptr->position; return; } else { /* finish loop */ struct tagstack_entry iftag; iftag=tagstack_smart_pop(state); state->is_visible=iftag.vcontext; state->last_processed_pos=state->cur_pos; } } static void tag_handler_unknown (struct tmplpro_state *state, const PSTRING* const TagOptVal) { log_state(state,TMPL_LOG_ERROR,"tag_handler_unknown: unknown tag\n"); } /* * Local Variables: * mode: c * End: */