+ # allows 'proper' handling of for loop scope
+ # cur_scope is a stack of scopes, the last being the current
+ # when opening a for loop push scope onto end, when closing for loop pop
+ my @cur_scope = ("");
+ # flag representing if we've found a for loop this iteration
+ my $for_loop_found = 0;
+
+ for my $input_tmpl(<$ITMPL>){
+ my @parts = split "<", $input_tmpl;
+ for( my $i=0; $i<=$#parts; ++$i ){
+ my $input_tmpl = $i ? "<" . $parts[$i] : $parts[$i]; # add < sign back in to every part except the first
+ $for_loop_found = 0;
+
+ # handle poorly names variable such as f1!, f1+, f1-, f1| and mod
+ $input_tmpl =~ s/"(\w+)\|"/"$1pipe"/ig;
+ $input_tmpl =~ s/"(\w+)\+"/"$1plus"/ig;
+ $input_tmpl =~ s/"(\w+)\-"/"$1minus"/ig;
+ $input_tmpl =~ s/"(\w+)!"/"$1exclamation"/ig;
+ $input_tmpl =~ s/"(\w+),(\w+)"/"$1comma$2"/ig; #caused a problem in patron search
+ $input_tmpl =~ s/NAME="mod"/NAME="modname"/ig;
+ # handle 'naked' TMPL_VAR "parameter" by turning them into what they should be, TMPL_VAR NAME="parameter"
+ $input_tmpl =~ s/TMPL_VAR\s+"(\w+)"/TMPL_VAR NAME="$1"/ig;
+ # make an end (ESCAPE NAME DEFAULT) into a ned (NAME ESCAPE DEFAULT)
+ $input_tmpl =~ s/ESCAPE="(\w+?)"\s+NAME=['"](\w+?)['"]\s+DEFAULT=['"](.+?)['"]/NAME="$2" ESCAPE="$1" DEFAULT="$3"/ig;
+
+ # Process..
+ # NB: if you think you're seeing double, you probably are, *some* (read:most) patterns appear twice: once with quotations marks, once without.
+ # trying to combine them into a single pattern proved troublesome as a regex like ['"]?(.*?)['"]? was causing problems and fixing the problem caused (alot) more complex regex
+
+ # variables
+ $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?\s*(\w*?)\s*['"]?\s+ESCAPE=['"](\w*?)['"]\s+DEFAULT=['"]?(.*?)['"]?\s*-*>/[% DEFAULT $cur_scope[-1]$1="$3" |$2 %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]\s*(\w*?)\s*['"]\s+ESCAPE=['"]?(\w*?)['"]?\s*-*>/[% $cur_scope[-1]$1 |$2 %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?(\w*?)\s+ESCAPE=['"]?(\w*?)['"]?\s*-*>/[% $cur_scope[-1]$1 |$2 %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+ESCAPE=['"]?(\w*?)['"]?\s+NAME\s?=\s?['"]?([\w-]*?)['"]?\s*-*>/[% $cur_scope[-1]$2 |$1 %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?(\w*?)['"]?\s+DEFAULT=['"](.*?)['"]\s*-*>/[% DEFAULT $cur_scope[-1]$1="$2" %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?\s*(\w*?)\s*['"]?\s+DEFAULT=(.*?)\s*-*>/[% DEFAULT $cur_scope[-1]$1=$2 %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+NAME\s?=\s?['"]?\s*(\w*?)\s*['"]?\s*-*>/[% $cur_scope[-1]$1 %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% $1 %]/ig; # TMPL_VAR NAME and TMPL_VAR EXPR are logically equiv
+ $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+EXPR\s?=\s?(.*?)\s*-*>/[% $1 %]/ig;
+
+ # if, elseif and unless blocks
+ $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% IF ( $1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+EXPR\s?=\s?(.*?)\s*-*>/[% IF ( $1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+NAME\s?=\s?['"]\s*(\w*?)\s*['"]\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+NAME\s?=\s?(\w*?)\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+['"](.*?)['"]\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+([\w\s]*?)\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
+
+ $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% ELSIF ( $1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+EXPR\s?=\s?(.*?)\s*-*>/[% ELSIF ( $1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+NAME\s?=\s?['"](\w*?)['"]\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+NAME\s?=\s?(\w*?)\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+['"](\w*?)['"]\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+(\w*?)\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
+
+ $input_tmpl =~ s/<[!-]*\s*TMPL_ELSE\s*-*>/[% ELSE %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*\/TMPL_IF\s*-*>/[% END %]/ig;
+
+ $input_tmpl =~ s/<[!-]*\s*TMPL_UNLESS\s+NAME\s?=\s?['"]?(\w*?)['"]?\s*-*>/[% UNLESS ( $cur_scope[-1]$1 ) %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*\/TMPL_UNLESS\s*-*>/[% END %]/ig;
+ # includes
+ $input_tmpl =~ s/<[!-]*\s*TMPL_INCLUDE\s+NAME\s?=\s?"(.*?\.inc)"\s*-*>/[% INCLUDE '$1' %]/ig;
+ $input_tmpl =~ s/<[!-]*\s*TMPL_INCLUDE\s+NAME\s?=\s?"(.*?)"\s*-*>/[% INCLUDE $1 %]/ig;
+
+ #reverse scoping bug fix
+ for my $tag (@globals){
+ next unless $cur_scope[-1];
+ $input_tmpl =~ s/$cur_scope[-1]$tag/$tag/g;
+ }