Avoid NPE for "mark occurences"
[phpeclipse.git] / net.sourceforge.phpeclipse.tests / src / net / sourceforge / phpeclipse / tests / parser / SmartyCompilerTestCase.java
1 package net.sourceforge.phpeclipse.tests.parser;
2 /*******************************************************************************
3  * Copyright (c) 2002 www.phpeclipse.de All rights
4  * reserved. This program and the accompanying materials are made available
5  * under the terms of the Common Public License v1.0 which accompanies this
6  * distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html
7  ******************************************************************************/
8 import net.sourceforge.phpdt.core.tests.util.AbstractCompilerTest;
9 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
10 /**
11  * Tests the php parser
12  */
13 public class SmartyCompilerTestCase extends AbstractCompilerTest {
14 //  Parser parser;
15   public SmartyCompilerTestCase(String name) {
16     super(name);
17   }
18   /**
19    * Test the PHP Parser with different PHP snippets
20    */
21   public void testPHPParser() {
22     checkHTML("<?php\n" +
23                 "\n" +
24                 "/**\n" +
25                 " * Project:     Smarty: the PHP compiling template engine\n" +
26                 " * File:        Smarty_Compiler.class.php\n" +
27                 " * Author:      Monte Ohrt <monte@ispi.net>\n" +
28                 " *              Andrei Zmievski <andrei@php.net>\n" +
29                 " *\n" +
30                 " * Version:     2.4.2\n" +
31                 " * Copyright:   2001,2002 ispi of Lincoln, Inc.\n" +
32                 " *\n" +
33                 " * This library is free software; you can redistribute it and/or\n" +
34                 " * modify it under the terms of the GNU Lesser General Public\n" +
35                 " * License as published by the Free Software Foundation; either\n" +
36                 " * version 2.1 of the License, or (at your option) any later version.\n" +
37                 " *\n" +
38                 " * This library is distributed in the hope that it will be useful,\n" +
39                 " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
40                 " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" +
41                 " * Lesser General Public License for more details.\n" +
42                 " *\n" +
43                 " * You should have received a copy of the GNU Lesser General Public\n" +
44                 " * License along with this library; if not, write to the Free Software\n" +
45                 " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n" +
46                 " *\n" +
47                 " * You may contact the authors of Smarty by e-mail at:\n" +
48                 " * monte@ispi.net\n" +
49                 " * andrei@php.net\n" +
50                 " *\n" +
51                 " * Or, write to:\n" +
52                 " * Monte Ohrt\n" +
53                 " * Director of Technology, ispi\n" +
54                 " * 237 S. 70th suite 220\n" +
55                 " * Lincoln, NE 68510\n" +
56                 " *\n" +
57                 " * The latest version of Smarty can be obtained from:\n" +
58                 " * http://www.phpinsider.com/\n" +
59                 " *\n" +
60                 " */\n" +
61                 "\n" +
62                 "class Smarty_Compiler extends Smarty {\n" +
63                 "       \n" +
64                 "    // internal vars\n" +
65                 "    public $_sectionelse_stack     =   array();    // keeps track of whether section had \'else\' part\n" +
66                 "    public $_foreachelse_stack     =   array();    // keeps track of whether foreach had \'else\' part\n" +
67                 "    public $_literal_blocks        =   array();    // keeps literal template blocks\n" +
68                 "    public $_php_blocks            =   array();    // keeps php code blocks\n" +
69                 "    public $_current_file          =   null;       // the current template being compiled\n" +
70                 "    public $_current_line_no       =   1;          // line number for error messages\n" +
71                 "    public $_capture_stack         =   array();    // keeps track of nested capture buffers\n" +
72                 "    public $_plugin_info           =   array();    // keeps track of plugins to load\n" +
73                 "    public $_init_smarty_vars      =   false;\n" +
74                 "       public $_permitted_tokens               =       array(\'true\',\'false\',\'yes\',\'no\',\'on\',\'off\');\n" +
75                 "    public $_db_qstr_regexp            =       null;           // regexps are setup in the constructor\n" +
76                 "    public $_si_qstr_regexp            =       null;\n" +
77                 "    public $_qstr_regexp                       =       null;\n" +
78                 "    public $_func_regexp                       =       null;\n" +
79                 "    public $_var_bracket_regexp        =       null;\n" +
80                 "    public $_dvar_guts_regexp          =       null;\n" +
81                 "    public $_dvar_regexp                       =       null;\n" +
82                 "    public $_cvar_regexp                       =       null;\n" +
83                 "    public $_svar_regexp                       =       null;\n" +
84                 "    public $_avar_regexp                       =       null;\n" +
85                 "    public $_mod_regexp                        =       null;\n" +
86                 "    public $_var_regexp                    =   null;\n" +
87                 "    public $_parenth_param_regexp      =       null;\n" +
88                 "       public $_func_call_regexp               =       null;\n" +
89                 "       public $_obj_ext_regexp         =       null;\n" +
90                 "       public $_obj_start_regexp               =       null;\n" +
91                 "       public $_obj_params_regexp              =       null;\n" +
92                 "       public $_obj_call_regexp                =       null;\n" +
93                 "\n" +
94                 "       /**\n" +
95                 "        * The class constructor.\n" +
96                 "        *\n" +
97                 "        * @access public\n" +
98                 "        */\n" +
99                 "    function Smarty_Compiler()\n" +
100                 "    {\n" +
101                 "               // matches double quoted strings:\n" +
102                 "               // \"foobar\"\n" +
103                 "               // \"foo\\\"bar\"\n" +
104                 "       $this->_db_qstr_regexp = \'\"[^\"\\\\\\\\]*(?:\\\\\\\\.[^\"\\\\\\\\]*)*\"\';\n" +
105                 "\n" +
106                 "               // matches single quoted strings:\n" +
107                 "               // \'foobar\'\n" +
108                 "               // \'foo\\\'bar\'\n" +
109                 "       $this->_si_qstr_regexp = \'\\\'[^\\\'\\\\\\\\]*(?:\\\\\\\\.[^\\\'\\\\\\\\]*)*\\\'\';\n" +
110                 "\n" +
111                 "               // matches single or double quoted strings\n" +
112                 "       $this->_qstr_regexp = \'(?:\' . $this->_db_qstr_regexp . \'|\' . $this->_si_qstr_regexp . \')\';\n" +
113                 "\n" +
114                 "               // matches bracket portion of vars\n" +
115                 "               // [0]\n" +
116                 "               // [foo]\n" +
117                 "               // [$bar]\n" +
118                 "               $this->_var_bracket_regexp = \'\\[\\$?[\\w\\.]+\\]\';\n" +
119                 "                               \n" +
120                 "               // matches $ vars (not objects):\n" +
121                 "               // $foo\n" +
122                 "               // $foo.bar\n" +
123                 "               // $foo.bar.foobar\n" +
124                 "               // $foo[0]\n" +
125                 "               // $foo[$bar]\n" +
126                 "               // $foo[5][blah]\n" +
127                 "               // $foo[5].bar[$foobar][4]\n" +
128                 "               $this->_dvar_guts_regexp = \'\\w+(?:\' . $this->_var_bracket_regexp\n" +
129                 "                               . \')*(?:\\.\\$?\\w+(?:\' . $this->_var_bracket_regexp . \')*)*\';\n" +
130                 "               $this->_dvar_regexp = \'\\$\' . $this->_dvar_guts_regexp;\n" +
131                 "\n" +
132                 "               // matches config vars:\n" +
133                 "               // #foo#\n" +
134                 "               // #foobar123_foo#\n" +
135                 "               $this->_cvar_regexp = \'\\#\\w+\\#\';\n" +
136                 "\n" +
137                 "               // matches section vars:\n" +
138                 "               // %foo.bar%\n" +
139                 "               $this->_svar_regexp = \'\\%\\w+\\.\\w+\\%\';\n" +
140                 "\n" +
141                 "               // matches all valid variables (no quotes, no modifiers)\n" +
142                 "               $this->_avar_regexp = \'(?:\' . $this->_dvar_regexp . \'|\'\n" +
143                 "                  . $this->_cvar_regexp . \'|\' . $this->_svar_regexp . \')\';\n" +
144                 "\n" +
145                 "               // matches valid modifier syntax:\n" +
146                 "               // |foo\n" +
147                 "               // |@foo\n" +
148                 "               // |foo:\"bar\"\n" +
149                 "               // |foo:$bar\n" +
150                 "               // |foo:\"bar\":$foobar\n" +
151                 "               // |foo|bar\n" +
152                 "               // |foo\n" +
153                 "               $this->_mod_regexp = \'(?:\\|@?\\w+(?::(?>\\w+|\'\n" +
154                 "                  . $this->_avar_regexp . \'|\' . $this->_qstr_regexp .\'))*)\';\n" +
155                 "\n" +
156                 "               // matches valid variable syntax:\n" +
157                 "               // $foo\n" +
158                 "               // $foo\n" +
159                 "               // #foo#\n" +
160                 "               // #foo#\n" +
161                 "               // \"text\"\n" +
162                 "               // \"text\"\n" +
163                 "               $this->_var_regexp = \'(?:\' . $this->_avar_regexp . \'|\' . $this->_qstr_regexp . \')\';\n" +
164                 "                               \n" +
165                 "               // matches valid object call (no objects allowed in parameters):\n" +
166                 "               // $foo->bar\n" +
167                 "               // $foo->bar()\n" +
168                 "               // $foo->bar(\"text\")\n" +
169                 "               // $foo->bar($foo, $bar, \"text\")\n" +
170                 "               // $foo->bar($foo|bar, \"foo\"|bar)\n" +
171                 "               // $foo->bar->foo()\n" +
172                 "               // $foo->bar->foo->bar()\n" +
173                 "               $this->_obj_ext_regexp = \'\\->(?:\\w+|\' . $this->_dvar_regexp . \')\';\n" +
174                 "       $this->_obj_params_regexp = \'\\((?:\\w+|\'\n" +
175                 "                               . $this->_var_regexp . \'(?>\' . $this->_mod_regexp . \'*)(?:\\s*,\\s*(?:(?:\\w+|\'\n" +
176                 "                               . $this->_var_regexp . \'(?>\' . $this->_mod_regexp . \'*))))*)?\\)\';          \n" +
177                 "       $this->_obj_start_regexp = \'(?:\' . $this->_dvar_regexp . \'(?:\' . $this->_obj_ext_regexp . \')+)\';\n" +
178                 "               $this->_obj_call_regexp = \'(?:\' . $this->_obj_start_regexp . \'(?:\' . $this->_obj_params_regexp . \')?)\';\n" +
179                 "               \n" +
180                 "               // matches valid function name:\n" +
181                 "               // foo123\n" +
182                 "               // _foo_bar\n" +
183                 "               $this->_func_regexp = \'[a-zA-Z_]\\w*\';\n" +
184                 "\n" +
185                 "               // matches valid registered object:\n" +
186                 "               // foo.bar\n" +
187                 "               $this->_reg_obj_regexp = \'[a-zA-Z_]\\w*->[a-zA-Z_]\\w*\';\n" +
188                 "                               \n" +
189                 "               // matches valid parameter values:\n" +
190                 "               // true\n" +
191                 "               // $foo\n" +
192                 "               // $foo|bar\n" +
193                 "               // #foo#\n" +
194                 "               // #foo#|bar\n" +
195                 "               // \"text\"\n" +
196                 "               // \"text\"|bar\n" +
197                 "               // $foo->bar\n" +
198                 "               $this->_param_regexp = \'(?:\\s*(?:\' . $this->_obj_call_regexp . \'|\'\n" +
199                 "                  . $this->_var_regexp  . \'|\\w+)(?>\' . $this->_mod_regexp . \'*)\\s*)\';            \n" +
200                 "               \n" +
201                 "               // matches valid parenthesised function parameters:\n" +
202                 "               // \n" +
203                 "               // \"text\"\n" +
204                 "               //      $foo, $bar, \"text\"\n" +
205                 "               // $foo|bar, \"foo\"|bar, $foo->bar($foo)|bar\n" +
206                 "       $this->_parenth_param_regexp = \'(?:\\((?:\\w+|\'\n" +
207                 "                               . $this->_param_regexp . \'(?:\\s*,\\s*(?:(?:\\w+|\'\n" +
208                 "                               . $this->_param_regexp . \')))*)?\\))\';\n" +
209                 "       \n" +
210                 "               // matches valid function call:\n" +
211                 "               // foo()\n" +
212                 "               // foo_bar($foo)\n" +
213                 "               // _foo_bar($foo,\"bar\")\n" +
214                 "               // foo123($foo,$foo->bar(),\"foo\")\n" +
215                 "       $this->_func_call_regexp = \'(?:\' . $this->_func_regexp . \'\\s*(?:\'\n" +
216                 "                  . $this->_parenth_param_regexp . \'))\';             \n" +
217                 "\n" +
218                 "       }                       \n" +
219                 "                       \n" +
220                 "       /**\n" +
221                 "        * compile a template file\n" +
222                 "        *\n" +
223                 "        * @access public\n" +
224                 "        * @param  $tpl_file\n" +
225                 "        * @param  $template_source\n" +
226                 "        * @param  $template_compiled\n" +
227                 "        */\n" +
228                 "    function _compile_file($tpl_file, $template_source, &$template_compiled)\n" +
229                 "    {\n" +
230                 "        if ($this->security) {\n" +
231                 "            // do not allow php syntax to be executed unless specified\n" +
232                 "            if ($this->php_handling == SMARTY_PHP_ALLOW &&\n" +
233                 "                !$this->security_settings[\'PHP_HANDLING\']) {\n" +
234                 "                $this->php_handling = SMARTY_PHP_PASSTHRU;\n" +
235                 "            }\n" +
236                 "        }\n" +
237                 "\n" +
238                 "        $this->_load_filters();\n" +
239                 "\n" +
240                 "        $this->_current_file = $tpl_file;\n" +
241                 "        $this->_current_line_no = 1;\n" +
242                 "        $ldq = preg_quote($this->left_delimiter, \'!\');\n" +
243                 "        $rdq = preg_quote($this->right_delimiter, \'!\');\n" +
244                 "\n" +
245                 "        // run template source through prefilter functions\n" +
246                 "        if (count($this->_plugins[\'prefilter\']) > 0) {\n" +
247                 "            foreach ($this->_plugins[\'prefilter\'] as $filter_name => $prefilter) {\n" +
248                 "                if ($prefilter === false) continue; \n" +
249                 "                if ($prefilter[3] || function_exists($prefilter[0])) {\n" +
250                 "                    $template_source = $prefilter[0]($template_source, $this);\n" +
251                 "                    $this->_plugins[\'prefilter\'][$filter_name][3] = true;\n" +
252                 "                } else {\n" +
253                 "                    $this->_trigger_fatal_error(\"[plugin] prefilter \'$filter_name\' is not implemented\");\n" +
254                 "                }\n" +
255                 "            }\n" +
256                 "        }\n" +
257                 "\n" +
258                 "        /* Annihilate the comments. */\n" +
259                 "        $template_source = preg_replace(\"!({$ldq})\\*(.*?)\\*({$rdq})!se\",\n" +
260                 "                                        \"\'\\\\1*\'.str_repeat(\\\"\\n\\\", substr_count(\'\\\\2\', \\\"\\n\\\")) .\'*\\\\3\'\",\n" +
261                 "                                        $template_source);\n" +
262                 "\n" +
263                 "        /* Pull out the literal blocks. */\n" +
264                 "        preg_match_all(\"!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s\", $template_source, $match);\n" +
265                 "        $this->_literal_blocks = $match[1];\n" +
266                 "        $template_source = preg_replace(\"!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s\",\n" +
267                 "                                        $this->quote_replace($this->left_delimiter.\'literal\'.$this->right_delimiter), $template_source);\n" +
268                 "\n" +
269                 "        /* Pull out the php code blocks. */\n" +
270                 "        preg_match_all(\"!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s\", $template_source, $match);\n" +
271                 "        $this->_php_blocks = $match[1];\n" +
272                 "        $template_source = preg_replace(\"!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s\",\n" +
273                 "                                        $this->quote_replace($this->left_delimiter.\'php\'.$this->right_delimiter), $template_source);\n" +
274                 "\n" +
275                 "        /* Gather all template tags. */\n" +
276                 "        preg_match_all(\"!{$ldq}\\s*(.*?)\\s*{$rdq}!s\", $template_source, $match);\n" +
277                 "        $template_tags = $match[1];\n" +
278                 "        /* Split content by template tags to obtain non-template content. */\n" +
279                 "        $text_blocks = preg_split(\"!{$ldq}.*?{$rdq}!s\", $template_source);\n" +
280                 "               \n" +
281                 "        /* loop through text blocks */\n" +
282                 "        for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {\n" +
283                 "            /* match anything resembling php tags */\n" +
284                 "            if (preg_match_all(\'!(<\\?(?:\\w+|=)?|\\?>|language\\s*=\\s*[\\\"\\\']?php[\\\"\\\']?)!is\', $text_blocks[$curr_tb], $sp_match)) {\n" +
285                 "                               /* replace tags with placeholders to prevent recursive replacements */\n" +
286                 "                               $sp_match[1] = array_unique($sp_match[1]);\n" +
287                 "                               usort($sp_match[1], \'_smarty_sort_length\');\n" +
288                 "                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {\n" +
289                 "                                       $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],\'%%%SMARTYSP\'.$curr_sp.\'%%%\',$text_blocks[$curr_tb]);\n" +
290                 "                               }\n" +
291                 "                /* process each one */\n" +
292                 "                for ($curr_sp = 0, $for_max2 = count($sp_match[0]); $curr_sp < $for_max2; $curr_sp++) {\n" +
293                 "                    if ($this->php_handling == SMARTY_PHP_PASSTHRU) {\n" +
294                 "                        /* echo php contents */\n" +
295                 "                        $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', \'<?php echo \\\'\'.str_replace(\"\'\", \"\\\'\", $sp_match[1][$curr_sp]).\'\\\'; ?>\'.\"\\n\", $text_blocks[$curr_tb]);\n" +
296                 "                    } else if ($this->php_handling == SMARTY_PHP_QUOTE) {\n" +
297                 "                        /* quote php tags */\n" +
298                 "                        $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);\n" +
299                 "                    } else if ($this->php_handling == SMARTY_PHP_REMOVE) {\n" +
300                 "                        /* remove php tags */\n" +
301                 "                        $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', \'\', $text_blocks[$curr_tb]);\n" +
302                 "                    } else {\n" +
303                 "                                               /* SMARTY_PHP_ALLOW, but echo non php starting tags */\n" +
304                 "                                               $sp_match[1][$curr_sp] = preg_replace(\'%(<\\?(?!php|=|$))%i\', \'<?php echo \\\'\\\\1\\\'?>\'.\"\\n\", $sp_match[1][$curr_sp]);\n" +
305                 "                                               $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);\n" +
306                 "                                       }\n" +
307                 "                }\n" +
308                 "            }\n" +
309                 "        }\n" +
310                 "\n" +
311                 "        /* Compile the template tags into PHP code. */\n" +
312                 "        $compiled_tags = array();\n" +
313                 "        for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {\n" +
314                 "            $this->_current_line_no += substr_count($text_blocks[$i], \"\\n\");\n" +
315                 "            $compiled_tags[] = $this->_compile_tag($template_tags[$i]);\n" +
316                 "            $this->_current_line_no += substr_count($template_tags[$i], \"\\n\");\n" +
317                 "        }\n" +
318                 "\n" +
319                 "        $template_compiled = \'\';\n" +
320                 "\n" +
321                 "        /* Interleave the compiled contents and text blocks to get the final result. */\n" +
322                 "        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {\n" +
323                 "            $template_compiled .= $text_blocks[$i].$compiled_tags[$i];\n" +
324                 "        }\n" +
325                 "        $template_compiled .= $text_blocks[$i];\n" +
326                 "\n" +
327                 "        /* Reformat data between \'strip\' and \'/strip\' tags, removing spaces, tabs and newlines. */\n" +
328                 "        if (preg_match_all(\"!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s\", $template_compiled, $match)) {\n" +
329                 "            $strip_tags = $match[0];\n" +
330                 "            $strip_tags_modified = preg_replace(\"!{$ldq}/?strip{$rdq}|[\\t ]+$|^[\\t ]+!m\", \'\', $strip_tags);\n" +
331                 "            $strip_tags_modified = preg_replace(\'![\\r\\n]+!m\', \'\', $strip_tags_modified);\n" +
332                 "            for ($i = 0, $for_max = count($strip_tags); $i < $for_max; $i++)\n" +
333                 "                $template_compiled = preg_replace(\"!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s\",\n" +
334                 "                                                  $this->quote_replace($strip_tags_modified[$i]),\n" +
335                 "                                                  $template_compiled, 1);\n" +
336                 "        }\n" +
337                 "\n" +
338                 "        // remove \\n from the end of the file, if any\n" +
339                 "        if ($template_compiled{strlen($template_compiled) - 1} == \"\\n\" ) {\n" +
340                 "            $template_compiled = substr($template_compiled, 0, -1);\n" +
341                 "        }\n" +
342                 "\n" +
343                 "        // run compiled template through postfilter functions\n" +
344                 "        if (count($this->_plugins[\'postfilter\']) > 0) {\n" +
345                 "            foreach ($this->_plugins[\'postfilter\'] as $filter_name => $postfilter) {\n" +
346                 "                if ($postfilter === false) continue;\n" +
347                 "                if ($postfilter[3] || function_exists($postfilter[0])) {\n" +
348                 "                    $template_compiled = $postfilter[0]($template_compiled, $this);\n" +
349                 "                    $this->_plugins[\'postfilter\'][$filter_name][3] = true;\n" +
350                 "                } else {\n" +
351                 "                    $this->_trigger_plugin_error(\"Smarty plugin error: postfilter \'$filter_name\' is not implemented\");\n" +
352                 "                }\n" +
353                 "            }\n" +
354                 "        }\n" +
355                 "\n" +
356                 "        // put header at the top of the compiled template\n" +
357                 "        $template_header = \"<?php /* Smarty version \".$this->_version.\", created on \".strftime(\"%Y-%m-%d %H:%M:%S\").\"\\n\";\n" +
358                 "        $template_header .= \"         compiled from \".$tpl_file.\" */ ?>\\n\";\n" +
359                 "\n" +
360                 "        /* Emit code to load needed plugins. */\n" +
361                 "        if (count($this->_plugin_info)) {\n" +
362                 "            $plugins_code = \'<?php $this->_load_plugins(array(\';\n" +
363                 "            foreach ($this->_plugin_info as $plugin_type => $plugins) {\n" +
364                 "                foreach ($plugins as $plugin_name => $plugin_info) {\n" +
365                 "                    $plugins_code .= \"\\narray(\'$plugin_type\', \'$plugin_name\', \'$plugin_info[0]\', $plugin_info[1], \";\n" +
366                 "                    $plugins_code .= $plugin_info[2] ? \'true),\' : \'false),\';\n" +
367                 "                }\n" +
368                 "            }\n" +
369                 "            $plugins_code .= \")); ?>\";\n" +
370                 "            $template_header .= $plugins_code;\n" +
371                 "            $this->_plugin_info = array();\n" +
372                 "        }\n" +
373                 "\n" +
374                 "        if ($this->_init_smarty_vars) {\n" +
375                 "            $template_header .= \"<?php \\$this->_assign_smarty_interface(); ?>\\n\";\n" +
376                 "            $this->_init_smarty_vars = false;\n" +
377                 "        }\n" +
378                 "\n" +
379                 "        $template_compiled = $template_header . $template_compiled;\n" +
380                 "\n" +
381                 "        return true;\n" +
382                 "    }\n" +
383                 "\n" +
384                 "       /**\n" +
385                 "        * Compile a template tag\n" +
386                 "        *\n" +
387                 "        * @access public\n" +
388                 "        * @param  $template_tag\n" +
389                 "        */\n" +
390                 "    function _compile_tag($template_tag)\n" +
391                 "    {          \n" +
392                 "                               \n" +
393                 "        /* Matched comment. */\n" +
394                 "        if ($template_tag{0} == \'*\' && $template_tag{strlen($template_tag) - 1} == \'*\')\n" +
395                 "            return \'\';\n" +
396                 "               \n" +
397                 "        /* Split tag into two three parts: command, command modifiers and the arguments. */\n" +
398                 "        if(! preg_match(\'/^(?:(\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp\n" +
399                 "                               . \'|\' . $this->_reg_obj_regexp . \'|\\/?\' . $this->_func_regexp . \')(\' . $this->_mod_regexp . \'*))\n" +
400                 "                      (?:\\s+(.*))?$\n" +
401                 "                    /xs\', $template_tag, $match)) {\n" +
402                 "                       $this->_syntax_error(\"unrecognized tag: $template_tag\", E_USER_ERROR, __FILE__, __LINE__);\n" +
403                 "               }\n" +
404                 "\n" +
405                 "        $tag_command = $match[1];\n" +
406                 "        $tag_modifier = isset($match[2]) ? $match[2] : null;\n" +
407                 "        $tag_args = isset($match[3]) ? $match[3] : null;\n" +
408                 "               \n" +
409                 "               \n" +
410                 "        /* If the tag name is a variable or object, we process it. */\n" +
411                 "        if (preg_match(\'!^\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp . \'$!\', $tag_command)) {\n" +
412                 "            $return = $this->_parse_var_props($tag_command . $tag_modifier, $this->_parse_attrs($tag_args));\n" +
413                 "                       if(isset($_tag_attrs[\'assign\'])) {\n" +
414                 "                               return \"<?php \\$this->assign(\'\" . $this->_dequote($_tag_attrs[\'assign\']) . \"\', $return ); ?>\\n\";  \n" +
415                 "                       } else {\n" +
416                 "               return \"<?php echo $return; ?>\\n\";\n" +
417                 "                       }\n" +
418                 "               }\n" +
419                 "               \n" +
420                 "           /* If the tag name is a registered object, we process it. */\n" +
421                 "        if (preg_match(\'!^\' . $this->_reg_obj_regexp . \'$!\', $tag_command)) {\n" +
422                 "                       return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);\n" +
423                 "               }\n" +
424                 "\n" +
425                 "        switch ($tag_command) {\n" +
426                 "            case \'include\':\n" +
427                 "                return $this->_compile_include_tag($tag_args);\n" +
428                 "\n" +
429                 "            case \'include_php\':\n" +
430                 "                return $this->_compile_include_php_tag($tag_args);\n" +
431                 "\n" +
432                 "            case \'if\':\n" +
433                 "                return $this->_compile_if_tag($tag_args);\n" +
434                 "\n" +
435                 "            case \'else\':\n" +
436                 "                return \'<?php else: ?>\';\n" +
437                 "\n" +
438                 "            case \'elseif\':\n" +
439                 "                return $this->_compile_if_tag($tag_args, true);\n" +
440                 "\n" +
441                 "            case \'/if\':\n" +
442                 "                return \'<?php endif; ?>\';\n" +
443                 "\n" +
444                 "            case \'capture\':\n" +
445                 "                return $this->_compile_capture_tag(true, $tag_args);\n" +
446                 "\n" +
447                 "            case \'/capture\':\n" +
448                 "                return $this->_compile_capture_tag(false);\n" +
449                 "\n" +
450                 "            case \'ldelim\':\n" +
451                 "                return $this->left_delimiter;\n" +
452                 "\n" +
453                 "            case \'rdelim\':\n" +
454                 "                return $this->right_delimiter;\n" +
455                 "\n" +
456                 "            case \'section\':\n" +
457                 "                array_push($this->_sectionelse_stack, false);\n" +
458                 "                return $this->_compile_section_start($tag_args);\n" +
459                 "\n" +
460                 "            case \'sectionelse\':\n" +
461                 "                $this->_sectionelse_stack[count($this->_sectionelse_stack)-1] = true;\n" +
462                 "                return \"<?php endfor; else: ?>\";\n" +
463                 "\n" +
464                 "            case \'/section\':\n" +
465                 "                if (array_pop($this->_sectionelse_stack))\n" +
466                 "                    return \"<?php endif; ?>\";\n" +
467                 "                else\n" +
468                 "                    return \"<?php endfor; endif; ?>\";\n" +
469                 "\n" +
470                 "            case \'foreach\':\n" +
471                 "                array_push($this->_foreachelse_stack, false);\n" +
472                 "                return $this->_compile_foreach_start($tag_args);\n" +
473                 "                break;\n" +
474                 "\n" +
475                 "            case \'foreachelse\':\n" +
476                 "                $this->_foreachelse_stack[count($this->_foreachelse_stack)-1] = true;\n" +
477                 "                return \"<?php endforeach; else: ?>\";\n" +
478                 "\n" +
479                 "            case \'/foreach\':\n" +
480                 "                if (array_pop($this->_foreachelse_stack))\n" +
481                 "                    return \"<?php endif; ?>\";\n" +
482                 "                else\n" +
483                 "                    return \"<?php endforeach; endif; ?>\";\n" +
484                 "\n" +
485                 "            case \'config_load\':\n" +
486                 "                return $this->_compile_config_load_tag($tag_args);\n" +
487                 "\n" +
488                 "            case \'strip\':\n" +
489                 "            case \'/strip\':\n" +
490                 "                return $this->left_delimiter.$tag_command.$this->right_delimiter;\n" +
491                 "\n" +
492                 "            case \'literal\':\n" +
493                 "                list (,$literal_block) = each($this->_literal_blocks);\n" +
494                 "                $this->_current_line_no += substr_count($literal_block, \"\\n\");\n" +
495                 "                return \"<?php echo \'\".str_replace(\"\'\", \"\\\'\", str_replace(\"\\\\\", \"\\\\\\\\\", $literal_block)).\"\'; ?>\\n\";\n" +
496                 "\n" +
497                 "            case \'php\':\n" +
498                 "                if ($this->security && !$this->security_settings[\'PHP_TAGS\']) {\n" +
499                 "                    $this->_syntax_error(\"(secure mode) php tags not permitted\", E_USER_WARNING, __FILE__, __LINE__);\n" +
500                 "                    return;\n" +
501                 "                }\n" +
502                 "                list (,$php_block) = each($this->_php_blocks);\n" +
503                 "                $this->_current_line_no += substr_count($php_block, \"\\n\");\n" +
504                 "                return \'<?php \'.$php_block.\' ?>\';\n" +
505                 "\n" +
506                 "            case \'insert\':\n" +
507                 "                return $this->_compile_insert_tag($tag_args);\n" +
508                 "\n" +
509                 "            default:\n" +
510                 "                if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {\n" +
511                 "                    return $output;\n" +
512                 "                } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {\n" +
513                 "                    return $output;\n" +
514                 "                } else {\n" +
515                 "                    return $this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier);\n" +
516                 "                }\n" +
517                 "        }\n" +
518                 "    }\n" +
519                 "\n" +
520                 "\n" +
521                 "       /**\n" +
522                 "        * compile the custom compiler tag\n" +
523                 "        *\n" +
524                 "        * @access public\n" +
525                 "        * @param  $tag_command\n" +
526                 "        * @param  $tag_args\n" +
527                 "        * @param  $output\n" +
528                 "        */\n" +
529                 "    function _compile_compiler_tag($tag_command, $tag_args, &$output)\n" +
530                 "    {\n" +
531                 "        $found = false;\n" +
532                 "        $have_function = true;\n" +
533                 "\n" +
534                 "        /*\n" +
535                 "         * First we check if the compiler function has already been registered\n" +
536                 "         * or loaded from a plugin file.\n" +
537                 "         */\n" +
538                 "        if (isset($this->_plugins[\'compiler\'][$tag_command])) {\n" +
539                 "            $found = true;\n" +
540                 "            $plugin_func = $this->_plugins[\'compiler\'][$tag_command][0];\n" +
541                 "            if (!function_exists($plugin_func)) {\n" +
542                 "                $message = \"compiler function \'$tag_command\' is not implemented\";\n" +
543                 "                $have_function = false;\n" +
544                 "            }\n" +
545                 "        }\n" +
546                 "        /*\n" +
547                 "         * Otherwise we need to load plugin file and look for the function\n" +
548                 "         * inside it.\n" +
549                 "         */\n" +
550                 "        else if ($plugin_file = $this->_get_plugin_filepath(\'compiler\', $tag_command)) {\n" +
551                 "            $found = true;\n" +
552                 "\n" +
553                 "            include_once $plugin_file;\n" +
554                 "\n" +
555                 "            $plugin_func = \'smarty_compiler_\' . $tag_command;\n" +
556                 "            if (!function_exists($plugin_func)) {\n" +
557                 "                $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n" +
558                 "                $have_function = false;\n" +
559                 "            } else {\n" +
560                 "                $this->_plugins[\'compiler\'][$tag_command] = array($plugin_func, null, null);\n" +
561                 "            }\n" +
562                 "        }\n" +
563                 "\n" +
564                 "        /*\n" +
565                 "         * True return value means that we either found a plugin or a\n" +
566                 "         * dynamically registered function. False means that we didn\'t and the\n" +
567                 "         * compiler should now emit code to load custom function plugin for this\n" +
568                 "         * tag.\n" +
569                 "         */\n" +
570                 "        if ($found) {\n" +
571                 "            if ($have_function) {\n" +
572                 "                $output = \'<?php \' . $plugin_func($tag_args, $this) . \' ?>\';\n" +
573                 "            } else {\n" +
574                 "                $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n" +
575                 "            }\n" +
576                 "            return true;\n" +
577                 "        } else {\n" +
578                 "            return false;\n" +
579                 "        }\n" +
580                 "    }\n" +
581                 "\n" +
582                 "\n" +
583                 "       /**\n" +
584                 "        * compile block function tag\n" +
585                 "        *\n" +
586                 "        * @access public\n" +
587                 "        * @param  $tag_command\n" +
588                 "        * @param  $tag_args\n" +
589                 "        * @param  $tag_modifier\n" +
590                 "        * @param  $output\n" +
591                 "        */\n" +
592                 "    function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)\n" +
593                 "    {\n" +
594                 "        if ($tag_command{0} == \'/\') {\n" +
595                 "            $start_tag = false;\n" +
596                 "            $tag_command = substr($tag_command, 1);\n" +
597                 "        } else\n" +
598                 "            $start_tag = true;\n" +
599                 "\n" +
600                 "        $found = false;\n" +
601                 "        $have_function = true;\n" +
602                 "\n" +
603                 "        /*\n" +
604                 "         * First we check if the block function has already been registered\n" +
605                 "         * or loaded from a plugin file.\n" +
606                 "         */\n" +
607                 "        if (isset($this->_plugins[\'block\'][$tag_command])) {\n" +
608                 "            $found = true;\n" +
609                 "            $plugin_func = $this->_plugins[\'block\'][$tag_command][0];\n" +
610                 "            if (!function_exists($plugin_func)) {\n" +
611                 "                $message = \"block function \'$tag_command\' is not implemented\";\n" +
612                 "                $have_function = false;\n" +
613                 "            }\n" +
614                 "        }\n" +
615                 "        /*\n" +
616                 "         * Otherwise we need to load plugin file and look for the function\n" +
617                 "         * inside it.\n" +
618                 "         */\n" +
619                 "        else if ($plugin_file = $this->_get_plugin_filepath(\'block\', $tag_command)) {\n" +
620                 "            $found = true;\n" +
621                 "\n" +
622                 "            include_once $plugin_file;\n" +
623                 "\n" +
624                 "            $plugin_func = \'smarty_block_\' . $tag_command;\n" +
625                 "            if (!function_exists($plugin_func)) {\n" +
626                 "                $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n" +
627                 "                $have_function = false;\n" +
628                 "            } else {\n" +
629                 "                $this->_plugins[\'block\'][$tag_command] = array($plugin_func, null, null);\n" +
630                 "            }\n" +
631                 "        }\n" +
632                 "\n" +
633                 "        if (!$found) {\n" +
634                 "            return false;\n" +
635                 "        } else if (!$have_function) {\n" +
636                 "            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n" +
637                 "            return true;\n" +
638                 "        }\n" +
639                 "\n" +
640                 "        /*\n" +
641                 "         * Even though we\'ve located the plugin function, compilation\n" +
642                 "         * happens only once, so the plugin will still need to be loaded\n" +
643                 "         * at runtime for future requests.\n" +
644                 "         */\n" +
645                 "        $this->_add_plugin(\'block\', $tag_command);\n" +
646                 "\n" +
647                 "        if ($start_tag) {\n" +
648                 "            $arg_list = array();\n" +
649                 "            $attrs = $this->_parse_attrs($tag_args);\n" +
650                 "            foreach ($attrs as $arg_name => $arg_value) {\n" +
651                 "                if (is_bool($arg_value))\n" +
652                 "                    $arg_value = $arg_value ? \'true\' : \'false\';\n" +
653                 "                $arg_list[] = \"\'$arg_name\' => $arg_value\";\n" +
654                 "            }\n" +
655                 "\n" +
656                 "            $output = \"<?php \\$this->_tag_stack[] = array(\'$tag_command\', array(\".implode(\',\', (array)$arg_list).\")); \\$this->_plugins[\'block\'][\'$tag_command\'][0](array(\".implode(\',\', (array)$arg_list).\"), null, \\$this); ob_start(); ?>\";\n" +
657                 "        } else {\n" +
658                 "            $output = \"<?php \\$this->_block_content = ob_get_contents(); ob_end_clean(); \";\n" +
659                 "                       $out_tag_text = \"\\$this->_plugins[\'block\'][\'$tag_command\'][0](\\$this->_tag_stack[count(\\$this->_tag_stack)-1][1], \\$this->_block_content, \\$this)\";\n" +
660                 "                       if($tag_modifier != \'\') {\n" +
661                 "                               $this->_parse_modifiers($out_tag_text, $tag_modifier);\n" +
662                 "                       }\n" +
663                 "                       $output .= \'echo \' . $out_tag_text . \';\';\n" +
664                 "                       $output .= \" array_pop(\\$this->_tag_stack); ?>\";\n" +
665                 "        }\n" +
666                 "\n" +
667                 "        return true;\n" +
668                 "    }\n" +
669                 "\n" +
670                 "\n" +
671                 "       /**\n" +
672                 "        * compile custom function tag\n" +
673                 "        *\n" +
674                 "        * @access public\n" +
675                 "        * @param  $tag_command\n" +
676                 "        * @param  $tag_args\n" +
677                 "        * @param  $tag_modifier\n" +
678                 "        */\n" +
679                 "    function _compile_custom_tag($tag_command, $tag_args, $tag_modifier)\n" +
680                 "    {\n" +
681                 "        $this->_add_plugin(\'function\', $tag_command);\n" +
682                 "\n" +
683                 "        $arg_list = array();\n" +
684                 "        $attrs = $this->_parse_attrs($tag_args);\n" +
685                 "        foreach ($attrs as $arg_name => $arg_value) {\n" +
686                 "            if (is_bool($arg_value))\n" +
687                 "                $arg_value = $arg_value ? \'true\' : \'false\';\n" +
688                 "            $arg_list[] = \"\'$arg_name\' => $arg_value\";\n" +
689                 "        }\n" +
690                 "               \n" +
691                 "               $return = \"\\$this->_plugins[\'function\'][\'$tag_command\'][0](array(\".implode(\',\', (array)$arg_list).\"), \\$this)\";\n" +
692                 "               \n" +
693                 "               if($tag_modifier != \'\') {\n" +
694                 "                       $this->_parse_modifiers($return, $tag_modifier);\n" +
695                 "               }\n" +
696                 "               \n" +
697                 "        return \'<?php echo \' . $return . \" ; ?>\\n\";\n" +
698                 "    }\n" +
699                 "\n" +
700                 "       /**\n" +
701                 "        * compile a registered object tag\n" +
702                 "        *\n" +
703                 "        * @access public\n" +
704                 "        * @param  $tag_command\n" +
705                 "        * @param  $attrs\n" +
706                 "        * @param  $tag_modifier\n" +
707                 "        */\n" +
708                 "    function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)\n" +
709                 "    {\n" +
710                 "               list($object, $obj_comp) = explode(\'->\', $tag_command);\n" +
711                 "\n" +
712                 "        $arg_list = array();\n" +
713                 "               if(count($attrs)) {\n" +
714                 "                       $_assign_var = false;\n" +
715                 "               foreach ($attrs as $arg_name => $arg_value) {\n" +
716                 "                               if($arg_name == \'assign\') {\n" +
717                 "                                       $_assign_var = $arg_value;\n" +
718                 "                                       unset($attrs[\'assign\']);\n" +
719                 "                                       continue;\n" +
720                 "                               }\n" +
721                 "               if (is_bool($arg_value))\n" +
722                 "                       $arg_value = $arg_value ? \'true\' : \'false\';\n" +
723                 "               $arg_list[] = \"\'$arg_name\' => $arg_value\";\n" +
724                 "               }\n" +
725                 "               }\n" +
726                 "                               \n" +
727                 "               if(!is_object($this->_reg_objects[$object][0])) {\n" +
728                 "                       $this->_trigger_fatal_error(\"registered \'$object\' is not an object\");\n" +
729                 "               } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {\n" +
730                 "                       $this->_trigger_fatal_error(\"\'$obj_comp\' is not a registered component of object \'$object\'\");\n" +
731                 "               } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {\n" +
732                 "                       // method\n" +
733                 "                       if($this->_reg_objects[$object][2]) {\n" +
734                 "                               // smarty object argument format\n" +
735                 "                               $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp(array(\".implode(\',\', (array)$arg_list).\"), \\$this)\";\n" +
736                 "                       } else {\n" +
737                 "                               // traditional argument format\n" +
738                 "                               $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp(\".implode(\',\', array_values($attrs)).\")\";\n" +
739                 "                       }\n" +
740                 "               } else {\n" +
741                 "                       // property\n" +
742                 "                       $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp\";\n" +
743                 "               }\n" +
744                 "               \n" +
745                 "               if($tag_modifier != \'\') {\n" +
746                 "                       $this->_parse_modifiers($return, $tag_modifier);\n" +
747                 "               }\n" +
748                 "               \n" +
749                 "               if($_assign_var) {\n" +
750                 "                       return \"<?php \\$this->assign(\'\" . $this->_dequote($_assign_var) .\"\',  $return); ?>\\n\";\n" +
751                 "               } else {\n" +
752                 "               return \'<?php echo \' . $return . \"; ?>\\n\";\n" +
753                 "               }\n" +
754                 "    }\n" +
755                 "       \n" +
756                 "       \n" +
757                 "\n" +
758                 "       /**\n" +
759                 "        * Compile {insert ...} tag\n" +
760                 "        *\n" +
761                 "        * @access public\n" +
762                 "        * @param  $tag_args\n" +
763                 "        */\n" +
764                 "    function _compile_insert_tag($tag_args)\n" +
765                 "    {\n" +
766                 "        $attrs = $this->_parse_attrs($tag_args);\n" +
767                 "        $name = $this->_dequote($attrs[\'name\']);\n" +
768                 "\n" +
769                 "        if (empty($name)) {\n" +
770                 "            $this->_syntax_error(\"missing insert name\", E_USER_ERROR, __FILE__, __LINE__);\n" +
771                 "        }\n" +
772                 "\n" +
773                 "        if (!empty($attrs[\'script\'])) {\n" +
774                 "            $delayed_loading = true;\n" +
775                 "        } else {\n" +
776                 "            $delayed_loading = false;                  \n" +
777                 "               }\n" +
778                 "\n" +
779                 "        foreach ($attrs as $arg_name => $arg_value) {\n" +
780                 "            if (is_bool($arg_value))\n" +
781                 "                $arg_value = $arg_value ? \'true\' : \'false\';\n" +
782                 "            $arg_list[] = \"\'$arg_name\' => $arg_value\";\n" +
783                 "        }\n" +
784                 "\n" +
785                 "        $this->_add_plugin(\'insert\', $name, $delayed_loading);\n" +
786                 "\n" +
787                 "        return \"<?php echo \\$this->_run_insert_handler(array(\".implode(\', \', (array)$arg_list).\")); ?>\\n\";\n" +
788                 "    }\n" +
789                 "\n" +
790                 "\n" +
791                 "       /**\n" +
792                 "        * Compile {config_load ...} tag\n" +
793                 "        *\n" +
794                 "        * @access public\n" +
795                 "        * @param  $tag_args\n" +
796                 "        */\n" +
797                 "    function _compile_config_load_tag($tag_args)\n" +
798                 "    {\n" +
799                 "        $attrs = $this->_parse_attrs($tag_args);\n" +
800                 "\n" +
801                 "        if (empty($attrs[\'file\'])) {\n" +
802                 "            $this->_syntax_error(\"missing \'file\' attribute in config_load tag\", E_USER_ERROR, __FILE__, __LINE__);\n" +
803                 "        }\n" +
804                 "\n" +
805                 "        if (empty($attrs[\'section\'])) {\n" +
806                 "            $attrs[\'section\'] = \'null\';\n" +
807                 "        }\n" +
808                 "\n" +
809                 "        if (isset($attrs[\'scope\'])) {\n" +
810                 "                       $scope = @$this->_dequote($attrs[\'scope\']);\r\n" +
811                 "            if ($scope != \'local\' &&\r\n" +
812                 "                $scope != \'parent\' &&\r\n" +
813                 "                $scope != \'global\') {\r\n" +
814                 "                $this->_syntax_error(\"invalid \'scope\' attribute value\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
815                 "            }\r\n" +
816                 "        } else {\r\n" +
817                 "            if (isset($attrs[\'global\']) && $attrs[\'global\'])\r\n" +
818                 "                $scope = \'parent\';\r\n" +
819                 "            else\r\n" +
820                 "                $scope = \'local\';\r\n" +
821                 "        }\r\n" +
822                 "\r\n" +
823                 "        return \'<?php $this->config_load(\' . $attrs[\'file\'] . \', \' . $attrs[\'section\'] . \", \'$scope\'); ?>\";\r\n" +
824                 "    }\r\n" +
825                 "\r\n" +
826                 "\r\n" +
827                 "       /**\r\n" +
828                 "        * Compile {include ...} tag\r\n" +
829                 "        *\r\n" +
830                 "        * @access public\r\n" +
831                 "        * $param  $tag_args\r\n" +
832                 "        */\r\n" +
833                 "    function _compile_include_tag($tag_args)\r\n" +
834                 "    {\r\n" +
835                 "        $attrs = $this->_parse_attrs($tag_args);\r\n" +
836                 "        $arg_list = array();\r\n" +
837                 "\r\n" +
838                 "        if (empty($attrs[\'file\'])) {\r\n" +
839                 "            $this->_syntax_error(\"missing \'file\' attribute in include tag\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
840                 "        }\r\n" +
841                 "\r\n" +
842                 "        foreach ($attrs as $arg_name => $arg_value) {\r\n" +
843                 "            if ($arg_name == \'file\') {\r\n" +
844                 "                $include_file = $arg_value;\r\n" +
845                 "                continue;\r\n" +
846                 "            } else if ($arg_name == \'assign\') {\r\n" +
847                 "                $assign_var = $arg_value;\r\n" +
848                 "                continue;\r\n" +
849                 "            }\r\n" +
850                 "            if (is_bool($arg_value))\r\n" +
851                 "                $arg_value = $arg_value ? \'true\' : \'false\';\r\n" +
852                 "            $arg_list[] = \"\'$arg_name\' => $arg_value\";\r\n" +
853                 "        }\r\n" +
854                 "\r\n" +
855                 "        $output = \'<?php \';\r\n" +
856                 "\r\n" +
857                 "        if (isset($assign_var)) {\r\n" +
858                 "                       $output .= \"ob_start();\\n\";\r\n" +
859                 "        }\r\n" +
860                 "\r\n" +
861                 "        $output .=  \r\n" +
862                 "            \"\\$_smarty_tpl_vars = \\$this->_tpl_vars;\\n\" .\r\n" +
863                 "            \"\\$this->_smarty_include(\".$include_file.\", array(\".implode(\',\', (array)$arg_list).\"));\\n\" .\r\n" +
864                 "            \"\\$this->_tpl_vars = \\$_smarty_tpl_vars;\\n\" .\r\n" +
865                 "            \"unset(\\$_smarty_tpl_vars);\\n\";\r\n" +
866                 "\r\n" +
867                 "        if (isset($assign_var)) {\r\n" +
868                 "                       $output .= \"\\$this->assign(\" . $assign_var . \", ob_get_contents()); ob_end_clean();\\n\";\r\n" +
869                 "        }\r\n" +
870                 "\r\n" +
871                 "        $output .= \' ?>\';\r\n" +
872                 "\r\n" +
873                 "               return $output;\r\n" +
874                 "\r\n" +
875                 "    }\r\n" +
876                 "\r\n" +
877                 "       /**\r\n" +
878                 "        * Compile {include ...} tag\r\n" +
879                 "        *\r\n" +
880                 "        * @access public\r\n" +
881                 "        * @param $tag_args\r\n" +
882                 "        */\r\n" +
883                 "    function _compile_include_php_tag($tag_args)\r\n" +
884                 "    {\r\n" +
885                 "        $attrs = $this->_parse_attrs($tag_args);\r\n" +
886                 "\r\n" +
887                 "        if (empty($attrs[\'file\'])) {\r\n" +
888                 "            $this->_syntax_error(\"missing \'file\' attribute in include_php tag\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
889                 "        }\r\n" +
890                 "\r\n" +
891                 "        $assign_var = $this->_dequote($attrs[\'assign\']);\r\n" +
892                 "\r\n" +
893                 "               $once_var = ( $attrs[\'once\'] === false ) ? \'false\' : \'true\';\r\n" +
894                 "\r\n" +
895                 "       foreach($attrs as $arg_name => $arg_value) {\r\n" +
896                 "               if($arg_name != \'file\' AND $arg_name != \'once\' AND $arg_name != \'assign\') {\r\n" +
897                 "               if(is_bool($arg_value))\r\n" +
898                 "                       $arg_value = $arg_value ? \'true\' : \'false\';\r\n" +
899                 "               $arg_list[] = \"\'$arg_name\' => $arg_value\";\r\n" +
900                 "               }\r\n" +
901                 "       }\r\n" +
902                 "\r\n" +
903                 "       $output =\r\n" +
904                 "               \"<?php \\$this->_smarty_include_php($attrs[file], \'$assign_var\', $once_var, \" .\r\n" +
905                 "               \"array(\".implode(\',\', (array)$arg_list).\")); ?>\";\r\n" +
906                 "                               \r\n" +
907                 "               return $output;\r\n" +
908                 "    }\r\n" +
909                 "       \r\n" +
910                 "\r\n" +
911                 "       /**\r\n" +
912                 "        * Compile {section ...} tag\r\n" +
913                 "        *\r\n" +
914                 "        * @access public\r\n" +
915                 "        * @param  $tag_args\r\n" +
916                 "        */\r\n" +
917                 "    function _compile_section_start($tag_args)\r\n" +
918                 "    {\r\n" +
919                 "        $attrs = $this->_parse_attrs($tag_args);\r\n" +
920                 "        $arg_list = array();\r\n" +
921                 "\r\n" +
922                 "        $output = \'<?php \';\r\n" +
923                 "        $section_name = $attrs[\'name\']; \r\n" +
924                 "        if (empty($section_name)) {\r\n" +
925                 "            $this->_syntax_error(\"missing section name\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
926                 "        }\r\n" +
927                 "\r\n" +
928                 "        $output .= \"if (isset(\\$this->_sections[$section_name])) unset(\\$this->_sections[$section_name]);\\n\";\r\n" +
929                 "        $section_props = \"\\$this->_sections[$section_name]\";\r\n" +
930                 "\r\n" +
931                 "        foreach ($attrs as $attr_name => $attr_value) {\r\n" +
932                 "            switch ($attr_name) {\r\n" +
933                 "                case \'loop\':\r\n" +
934                 "                    $output .= \"{$section_props}[\'loop\'] = is_array($attr_value) ? count($attr_value) : max(0, (int)$attr_value);\\n\";\r\n" +
935                 "                    break;\r\n" +
936                 "\r\n" +
937                 "                case \'show\':\r\n" +
938                 "                    if (is_bool($attr_value))\r\n" +
939                 "                        $show_attr_value = $attr_value ? \'true\' : \'false\';\r\n" +
940                 "                    else\r\n" +
941                 "                        $show_attr_value = \"(bool)$attr_value\";\r\n" +
942                 "                    $output .= \"{$section_props}[\'show\'] = $show_attr_value;\\n\";\r\n" +
943                 "                    break;\r\n" +
944                 "\r\n" +
945                 "                case \'name\':\r\n" +
946                 "                    $output .= \"{$section_props}[\'$attr_name\'] = $attr_value;\\n\";\r\n" +
947                 "                    break;\r\n" +
948                 "\r\n" +
949                 "                case \'max\':\r\n" +
950                 "                case \'start\':\r\n" +
951                 "                    $output .= \"{$section_props}[\'$attr_name\'] = (int)$attr_value;\\n\";\r\n" +
952                 "                    break;\r\n" +
953                 "\r\n" +
954                 "                case \'step\':\r\n" +
955                 "                    $output .= \"{$section_props}[\'$attr_name\'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\\n\";\r\n" +
956                 "                    break;\r\n" +
957                 "\r\n" +
958                 "                default:\r\n" +
959                 "                    $this->_syntax_error(\"unknown section attribute - \'$attr_name\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
960                 "                    break;\r\n" +
961                 "            }\r\n" +
962                 "        }\r\n" +
963                 "\r\n" +
964                 "        if (!isset($attrs[\'show\']))\r\n" +
965                 "            $output .= \"{$section_props}[\'show\'] = true;\\n\";\r\n" +
966                 "\r\n" +
967                 "        if (!isset($attrs[\'loop\']))\r\n" +
968                 "            $output .= \"{$section_props}[\'loop\'] = 1;\\n\";\r\n" +
969                 "\r\n" +
970                 "        if (!isset($attrs[\'max\']))\r\n" +
971                 "            $output .= \"{$section_props}[\'max\'] = {$section_props}[\'loop\'];\\n\";\r\n" +
972                 "        else\r\n" +
973                 "            $output .= \"if ({$section_props}[\'max\'] < 0)\\n\" .\r\n" +
974                 "                       \"    {$section_props}[\'max\'] = {$section_props}[\'loop\'];\\n\";\r\n" +
975                 "\r\n" +
976                 "        if (!isset($attrs[\'step\']))\r\n" +
977                 "            $output .= \"{$section_props}[\'step\'] = 1;\\n\";\r\n" +
978                 "\r\n" +
979                 "        if (!isset($attrs[\'start\']))\r\n" +
980                 "            $output .= \"{$section_props}[\'start\'] = {$section_props}[\'step\'] > 0 ? 0 : {$section_props}[\'loop\']-1;\\n\";\r\n" +
981                 "        else {\r\n" +
982                 "            $output .= \"if ({$section_props}[\'start\'] < 0)\\n\" .\r\n" +
983                 "                       \"    {$section_props}[\'start\'] = max({$section_props}[\'step\'] > 0 ? 0 : -1, {$section_props}[\'loop\'] + {$section_props}[\'start\']);\\n\" .\r\n" +
984                 "                       \"else\\n\" .\r\n" +
985                 "                       \"    {$section_props}[\'start\'] = min({$section_props}[\'start\'], {$section_props}[\'step\'] > 0 ? {$section_props}[\'loop\'] : {$section_props}[\'loop\']-1);\\n\";\r\n" +
986                 "        }\r\n" +
987                 "\r\n" +
988                 "        $output .= \"if ({$section_props}[\'show\']) {\\n\";\r\n" +
989                 "        if (!isset($attrs[\'start\']) && !isset($attrs[\'step\']) && !isset($attrs[\'max\'])) {\r\n" +
990                 "            $output .= \"    {$section_props}[\'total\'] = {$section_props}[\'loop\'];\\n\";\r\n" +
991                 "        } else {\r\n" +
992                 "            $output .= \"    {$section_props}[\'total\'] = min(ceil(({$section_props}[\'step\'] > 0 ? {$section_props}[\'loop\'] - {$section_props}[\'start\'] : {$section_props}[\'start\']+1)/abs({$section_props}[\'step\'])), {$section_props}[\'max\']);\\n\";\r\n" +
993                 "        }\r\n" +
994                 "        $output .= \"    if ({$section_props}[\'total\'] == 0)\\n\" .\r\n" +
995                 "                   \"        {$section_props}[\'show\'] = false;\\n\" .\r\n" +
996                 "                   \"} else\\n\" .\r\n" +
997                 "                   \"    {$section_props}[\'total\'] = 0;\\n\";\r\n" +
998                 "\r\n" +
999                 "        $output .= \"if ({$section_props}[\'show\']):\\n\";\r\n" +
1000                 "        $output .= \"\r\n" +
1001                 "            for ({$section_props}[\'index\'] = {$section_props}[\'start\'], {$section_props}[\'iteration\'] = 1;\r\n" +
1002                 "                 {$section_props}[\'iteration\'] <= {$section_props}[\'total\'];\r\n" +
1003                 "                 {$section_props}[\'index\'] += {$section_props}[\'step\'], {$section_props}[\'iteration\']++):\\n\";\r\n" +
1004                 "        $output .= \"{$section_props}[\'rownum\'] = {$section_props}[\'iteration\'];\\n\";\r\n" +
1005                 "        $output .= \"{$section_props}[\'index_prev\'] = {$section_props}[\'index\'] - {$section_props}[\'step\'];\\n\";\r\n" +
1006                 "        $output .= \"{$section_props}[\'index_next\'] = {$section_props}[\'index\'] + {$section_props}[\'step\'];\\n\";\r\n" +
1007                 "        $output .= \"{$section_props}[\'first\']      = ({$section_props}[\'iteration\'] == 1);\\n\";\r\n" +
1008                 "        $output .= \"{$section_props}[\'last\']       = ({$section_props}[\'iteration\'] == {$section_props}[\'total\']);\\n\";\r\n" +
1009                 "\r\n" +
1010                 "        $output .= \"?>\";\r\n" +
1011                 "\r\n" +
1012                 "        return $output;\r\n" +
1013                 "    }\r\n" +
1014                 "\r\n" +
1015                 "    \r\n" +
1016                 "       /**\r\n" +
1017                 "        * Compile {foreach ...} tag.\r\n" +
1018                 "        *\r\n" +
1019                 "        * @access public\r\n" +
1020                 "        * @param  $tag_args\r\n" +
1021                 "        */\r\n" +
1022                 "    function _compile_foreach_start($tag_args)\r\n" +
1023                 "    {\r\n" +
1024                 "        $attrs = $this->_parse_attrs($tag_args);\r\n" +
1025                 "        $arg_list = array();\r\n" +
1026                 "\r\n" +
1027                 "        if (empty($attrs[\'from\'])) {\r\n" +
1028                 "            $this->_syntax_error(\"missing \'from\' attribute\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1029                 "        }\r\n" +
1030                 "\r\n" +
1031                 "        if (empty($attrs[\'item\'])) {\r\n" +
1032                 "            $this->_syntax_error(\"missing \'item\' attribute\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1033                 "        }\r\n" +
1034                 "\r\n" +
1035                 "        $from = $attrs[\'from\'];\r\n" +
1036                 "        $item = $this->_dequote($attrs[\'item\']);\r\n" +
1037                 "        if (isset($attrs[\'name\']))\r\n" +
1038                 "            $name = $attrs[\'name\'];\r\n" +
1039                 "\r\n" +
1040                 "        $output = \'<?php \';\r\n" +
1041                 "        if (isset($name)) {\r\n" +
1042                 "            $output .= \"if (isset(\\$this->_foreach[$name])) unset(\\$this->_foreach[$name]);\\n\";\r\n" +
1043                 "            $foreach_props = \"\\$this->_foreach[$name]\";\r\n" +
1044                 "        }\r\n" +
1045                 "\r\n" +
1046                 "        $key_part = \'\';\r\n" +
1047                 "\r\n" +
1048                 "        foreach ($attrs as $attr_name => $attr_value) {\r\n" +
1049                 "            switch ($attr_name) {\r\n" +
1050                 "                case \'key\':\r\n" +
1051                 "                    $key  = $this->_dequote($attrs[\'key\']);\r\n" +
1052                 "                    $key_part = \"\\$this->_tpl_vars[\'$key\'] => \";\r\n" +
1053                 "                    break;\r\n" +
1054                 "\r\n" +
1055                 "                case \'name\':\r\n" +
1056                 "                    $output .= \"{$foreach_props}[\'$attr_name\'] = $attr_value;\\n\";\r\n" +
1057                 "                    break;\r\n" +
1058                 "            }\r\n" +
1059                 "        }\r\n" +
1060                 "\r\n" +
1061                 "        if (isset($name)) {\r\n" +
1062                 "            $output .= \"{$foreach_props}[\'total\'] = count((array)$from);\\n\";\r\n" +
1063                 "            $output .= \"{$foreach_props}[\'show\'] = {$foreach_props}[\'total\'] > 0;\\n\";\r\n" +
1064                 "            $output .= \"if ({$foreach_props}[\'show\']):\\n\";\r\n" +
1065                 "            $output .= \"{$foreach_props}[\'iteration\'] = 0;\\n\";\r\n" +
1066                 "            $output .= \"    foreach ((array)$from as $key_part\\$this->_tpl_vars[\'$item\']):\\n\";\r\n" +
1067                 "            $output .= \"        {$foreach_props}[\'iteration\']++;\\n\";\r\n" +
1068                 "            $output .= \"        {$foreach_props}[\'first\'] = ({$foreach_props}[\'iteration\'] == 1);\\n\";\r\n" +
1069                 "            $output .= \"        {$foreach_props}[\'last\']  = ({$foreach_props}[\'iteration\'] == {$foreach_props}[\'total\']);\\n\";\r\n" +
1070                 "        } else {\r\n" +
1071                 "            $output .= \"if (count((array)$from)):\\n\";\r\n" +
1072                 "            $output .= \"    foreach ((array)$from as $key_part\\$this->_tpl_vars[\'$item\']):\\n\";\r\n" +
1073                 "        }\r\n" +
1074                 "        $output .= \'?>\';\r\n" +
1075                 "\r\n" +
1076                 "        return $output;\r\n" +
1077                 "    }\r\n" +
1078                 "\r\n" +
1079                 "\r\n" +
1080                 "       /**\r\n" +
1081                 "        * Compile {capture} .. {/capture} tags\r\n" +
1082                 "        *\r\n" +
1083                 "        * @access public\r\n" +
1084                 "        * @param  $start\r\n" +
1085                 "        * @param  $tag_args\r\n" +
1086                 "        */\r\n" +
1087                 "    function _compile_capture_tag($start, $tag_args = \'\')\r\n" +
1088                 "    {\r\n" +
1089                 "        $attrs = $this->_parse_attrs($tag_args);\r\n" +
1090                 "\r\n" +
1091                 "        if ($start) {\r\n" +
1092                 "            if (isset($attrs[\'name\']))\r\n" +
1093                 "                $buffer = $attrs[\'name\'];\r\n" +
1094                 "            else\r\n" +
1095                 "                $buffer = \"\'default\'\";\r\n" +
1096                 "\r\n" +
1097                 "            $output = \"<?php ob_start(); ?>\";\r\n" +
1098                 "            $this->_capture_stack[] = $buffer;\r\n" +
1099                 "        } else {\r\n" +
1100                 "            $buffer = array_pop($this->_capture_stack);\r\n" +
1101                 "            $output = \"<?php \\$this->_smarty_vars[\'capture\'][$buffer] = ob_get_contents(); ob_end_clean(); ?>\";\r\n" +
1102                 "        }\r\n" +
1103                 "\r\n" +
1104                 "        return $output;\r\n" +
1105                 "    }\r\n" +
1106                 "\r\n" +
1107                 "       /**\r\n" +
1108                 "        * Compile {if ...} tag\r\n" +
1109                 "        *\r\n" +
1110                 "        * @access public\r\n" +
1111                 "        * @param  $tag_args\r\n" +
1112                 "        * @param  $elseif\r\n" +
1113                 "        */\r\n" +
1114                 "    function _compile_if_tag($tag_args, $elseif = false)\r\n" +
1115                 "    {\r\n" +
1116                 "\r\n" +
1117                 "        /* Tokenize args for \'if\' tag. */\r\n" +
1118                 "        preg_match_all(\'/(?>\r\n" +
1119                 "                               \' . $this->_obj_call_regexp . \'(?:\' . $this->_mod_regexp . \'*) | # valid object call\r\n" +
1120                 "                               \' . $this->_var_regexp . \'(?:\' . $this->_mod_regexp . \'*)   | # public or quoted string\r\n" +
1121                 "                               \\-?\\d+|!==|<=>|==|!=|<=|>=|\\&\\&|\\|\\||\\(|\\)|,|\\!|\\^|=|<|>|\\||\\%|\\+|\\-|\\/|\\*      | # valid non-word token\r\n" +
1122                 "                               \\b\\w+\\b                                                                                                              | # valid word token\r\n" +
1123                 "                               \\S+                                                           # anything else\r\n" +
1124                 "                               )/x\', $tag_args, $match);\r\n" +
1125                 "                               \r\n" +
1126                 "        $tokens = $match[0];\r\n" +
1127                 "               \r\n" +
1128                 "               // make sure we have balanced parenthesis\r\n" +
1129                 "               $token_count = array_count_values($tokens);\r\n" +
1130                 "               if(isset($token_count[\'(\']) && $token_count[\'(\'] != $token_count[\')\']) {\r\n" +
1131                 "                       $this->_syntax_error(\"unbalanced parenthesis in if statement\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1132                 "               }\r\n" +
1133                 "                                                                                               \r\n" +
1134                 "        $is_arg_stack = array();\r\n" +
1135                 "\r\n" +
1136                 "        for ($i = 0; $i < count($tokens); $i++) {\r\n" +
1137                 "\r\n" +
1138                 "            $token = &$tokens[$i];\r\n" +
1139                 "                       \r\n" +
1140                 "            switch (strtolower($token)) {\r\n" +
1141                 "                case \'!\':\r\n" +
1142                 "                case \'%\':\r\n" +
1143                 "                case \'!==\':\r\n" +
1144                 "                case \'==\':\r\n" +
1145                 "                case \'>\':\r\n" +
1146                 "                case \'<\':\r\n" +
1147                 "                case \'!=\':\r\n" +
1148                 "                case \'<=\':\r\n" +
1149                 "                case \'>=\':\r\n" +
1150                 "                case \'&&\':\r\n" +
1151                 "                case \'||\':\r\n" +
1152                 "                               case \'|\':\r\n" +
1153                 "                               case \'^\':\r\n" +
1154                 "                               case \'&\':\r\n" +
1155                 "                               case \'~\':\r\n" +
1156                 "                               case \')\':\r\n" +
1157                 "                               case \',\':\r\n" +
1158                 "                               case \'+\':\r\n" +
1159                 "                               case \'-\':\r\n" +
1160                 "                               case \'*\':\r\n" +
1161                 "                               case \'/\':\r\n" +
1162                 "                                       break;                                  \r\n" +
1163                 "\r\n" +
1164                 "                case \'eq\':\r\n" +
1165                 "                    $token = \'==\';\r\n" +
1166                 "                    break;\r\n" +
1167                 "\r\n" +
1168                 "                case \'ne\':\r\n" +
1169                 "                case \'neq\':\r\n" +
1170                 "                    $token = \'!=\';\r\n" +
1171                 "                    break;\r\n" +
1172                 "\r\n" +
1173                 "                case \'lt\':\r\n" +
1174                 "                    $token = \'<\';\r\n" +
1175                 "                    break;\r\n" +
1176                 "\r\n" +
1177                 "                case \'le\':\r\n" +
1178                 "                case \'lte\':\r\n" +
1179                 "                    $token = \'<=\';\r\n" +
1180                 "                    break;\r\n" +
1181                 "\r\n" +
1182                 "                case \'gt\':\r\n" +
1183                 "                    $token = \'>\';\r\n" +
1184                 "                    break;\r\n" +
1185                 "\r\n" +
1186                 "                case \'ge\':\r\n" +
1187                 "                case \'gte\':\r\n" +
1188                 "                    $token = \'>=\';\r\n" +
1189                 "                    break;\r\n" +
1190                 "\r\n" +
1191                 "                case \'and\':\r\n" +
1192                 "                    $token = \'&&\';\r\n" +
1193                 "                    break;\r\n" +
1194                 "\r\n" +
1195                 "                case \'or\':\r\n" +
1196                 "                    $token = \'||\';\r\n" +
1197                 "                    break;\r\n" +
1198                 "\r\n" +
1199                 "                case \'not\':\r\n" +
1200                 "                    $token = \'!\';\r\n" +
1201                 "                    break;\r\n" +
1202                 "\r\n" +
1203                 "                case \'mod\':\r\n" +
1204                 "                    $token = \'%\';\r\n" +
1205                 "                    break;\r\n" +
1206                 "\r\n" +
1207                 "                case \'(\':\r\n" +
1208                 "                    array_push($is_arg_stack, $i);\r\n" +
1209                 "                    break;\r\n" +
1210                 "                                       \r\n" +
1211                 "                case \'is\':\r\n" +
1212                 "                    /* If last token was a \')\', we operate on the parenthesized\r\n" +
1213                 "                       expression. The start of the expression is on the stack.\r\n" +
1214                 "                       Otherwise, we operate on the last encountered token. */\r\n" +
1215                 "                    if ($tokens[$i-1] == \')\')\r\n" +
1216                 "                        $is_arg_start = array_pop($is_arg_stack);\r\n" +
1217                 "                    else\r\n" +
1218                 "                        $is_arg_start = $i-1;\r\n" +
1219                 "                    /* Construct the argument for \'is\' expression, so it knows\r\n" +
1220                 "                       what to operate on. */\r\n" +
1221                 "                    $is_arg = implode(\' \', array_slice($tokens, $is_arg_start, $i - $is_arg_start));\r\n" +
1222                 "                                       \r\n" +
1223                 "                    /* Pass all tokens from next one until the end to the\r\n" +
1224                 "                       \'is\' expression parsing function. The function will\r\n" +
1225                 "                       return modified tokens, where the first one is the result\r\n" +
1226                 "                       of the \'is\' expression and the rest are the tokens it\r\n" +
1227                 "                       didn\'t touch. */                                       \r\n" +
1228                 "                    $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));\r\n" +
1229                 "                                                                               \r\n" +
1230                 "                    /* Replace the old tokens with the new ones. */\r\n" +
1231                 "                    array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);\r\n" +
1232                 "\r\n" +
1233                 "                    /* Adjust argument start so that it won\'t change from the\r\n" +
1234                 "                       current position for the next iteration. */\r\n" +
1235                 "                    $i = $is_arg_start;\r\n" +
1236                 "                    break;\r\n" +
1237                 "                                       \r\n" +
1238                 "                default:\r\n" +
1239                 "                                       if(preg_match(\'!^\' . $this->_func_regexp . \'$!\', $token) ) {\r\n" +
1240                 "                                                       // function call        \r\n" +
1241                 "                               if($this->security &&\r\n" +
1242                 "                                  !in_array($token, $this->security_settings[\'IF_FUNCS\'])) {\r\n" +
1243                 "                                       $this->_syntax_error(\"(secure mode) \'$token\' not allowed in if statement\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1244                 "                                                       }                                                       \r\n" +
1245                 "                                       } elseif(preg_match(\'!^\' . $this->_var_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $token)) {\r\n" +
1246                 "                                               // variable\r\n" +
1247                 "                                       $token = $this->_parse_var_props($token);\r\n" +
1248                 "                                       } elseif(preg_match(\'!^\' . $this->_obj_call_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $token)) {\r\n" +
1249                 "                                               // object\r\n" +
1250                 "                                       $token = $this->_parse_var_props($token);\r\n" +
1251                 "                                       } elseif(is_numeric($token)) {\r\n" +
1252                 "                                               // number, skip it\r\n" +
1253                 "                                       } else {\r\n" +
1254                 "                               $this->_syntax_error(\"unidentified token \'$token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1255                 "                                       }\r\n" +
1256                 "                    break;\r\n" +
1257                 "            }\r\n" +
1258                 "        }\r\n" +
1259                 "                               \r\n" +
1260                 "        if ($elseif)\r\n" +
1261                 "            return \'<?php elseif (\'.implode(\' \', $tokens).\'): ?>\';\r\n" +
1262                 "        else\r\n" +
1263                 "            return \'<?php if (\'.implode(\' \', $tokens).\'): ?>\';\r\n" +
1264                 "    }\r\n" +
1265                 "\r\n" +
1266                 "\r\n" +
1267                 "       /**\r\n" +
1268                 "        * Parse is expression\r\n" +
1269                 "        *\r\n" +
1270                 "        * @access public\r\n" +
1271                 "        * @param  $is_arg\r\n" +
1272                 "        * @param  $tokens\r\n" +
1273                 "        */\r\n" +
1274                 "    function _parse_is_expr($is_arg, $tokens)\r\n" +
1275                 "    {\r\n" +
1276                 "        $expr_end = 0;\r\n" +
1277                 "        $negate_expr = false;\r\n" +
1278                 "\r\n" +
1279                 "        if (($first_token = array_shift($tokens)) == \'not\') {\r\n" +
1280                 "            $negate_expr = true;\r\n" +
1281                 "            $expr_type = array_shift($tokens);\r\n" +
1282                 "        } else\r\n" +
1283                 "            $expr_type = $first_token;\r\n" +
1284                 "\r\n" +
1285                 "        switch ($expr_type) {\r\n" +
1286                 "            case \'even\':\r\n" +
1287                 "                if (@$tokens[$expr_end] == \'by\') {\r\n" +
1288                 "                    $expr_end++;\r\n" +
1289                 "                    $expr_arg = $tokens[$expr_end++];\r\n" +
1290                 "                    $expr = \"!(($is_arg / $expr_arg) % \" . $this->_parse_var_props($expr_arg) . \")\";\r\n" +
1291                 "                } else\r\n" +
1292                 "                    $expr = \"!($is_arg % 2)\";\r\n" +
1293                 "                break;\r\n" +
1294                 "\r\n" +
1295                 "            case \'odd\':\r\n" +
1296                 "                if (@$tokens[$expr_end] == \'by\') {\r\n" +
1297                 "                    $expr_end++;\r\n" +
1298                 "                    $expr_arg = $tokens[$expr_end++];\r\n" +
1299                 "                    $expr = \"(($is_arg / $expr_arg) % \". $this->_parse_var_props($expr_arg) . \")\";\r\n" +
1300                 "                } else\r\n" +
1301                 "                    $expr = \"($is_arg % 2)\";\r\n" +
1302                 "                break;\r\n" +
1303                 "\r\n" +
1304                 "            case \'div\':\r\n" +
1305                 "                if (@$tokens[$expr_end] == \'by\') {\r\n" +
1306                 "                    $expr_end++;\r\n" +
1307                 "                    $expr_arg = $tokens[$expr_end++];\r\n" +
1308                 "                    $expr = \"!($is_arg % \" . $this->_parse_var_props($expr_arg) . \")\";\r\n" +
1309                 "                } else {\r\n" +
1310                 "                    $this->_syntax_error(\"expecting \'by\' after \'div\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1311                 "                }\r\n" +
1312                 "                break;\r\n" +
1313                 "\r\n" +
1314                 "            default:\r\n" +
1315                 "                $this->_syntax_error(\"unknown \'is\' expression - \'$expr_type\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1316                 "                break;\r\n" +
1317                 "        }\r\n" +
1318                 "\r\n" +
1319                 "        if ($negate_expr) {\r\n" +
1320                 "            $expr = \"!($expr)\";\r\n" +
1321                 "        }\r\n" +
1322                 "               \r\n" +
1323                 "        array_splice($tokens, 0, $expr_end, $expr);            \r\n" +
1324                 "               \r\n" +
1325                 "        return $tokens;\r\n" +
1326                 "    }\r\n" +
1327                 "\r\n" +
1328                 "\r\n" +
1329                 "       /**\r\n" +
1330                 "        * Parse attribute string\r\n" +
1331                 "        *\r\n" +
1332                 "        * @access public\r\n" +
1333                 "        * @param  $tag_args\r\n" +
1334                 "        * @param  $quote\r\n" +
1335                 "        */\r\n" +
1336                 "    function _parse_attrs($tag_args, $quote = true)\r\n" +
1337                 "    {\r\n" +
1338                 "                               \r\n" +
1339                 "        /* Tokenize tag attributes. */\r\n" +
1340                 "        preg_match_all(\'/(?:\' . $this->_obj_call_regexp . \'|\' . $this->_qstr_regexp . \' | (?>[^\"\\\'=\\s]+)\r\n" +
1341                 "                         )+ |\r\n" +
1342                 "                         [=]\r\n" +
1343                 "                        /x\', $tag_args, $match);\r\n" +
1344                 "        $tokens       = $match[0];             \r\n" +
1345                 "                               \r\n" +
1346                 "        $attrs = array();\r\n" +
1347                 "        /* Parse state:\r\n" +
1348                 "            0 - expecting attribute name\r\n" +
1349                 "            1 - expecting \'=\'\r\n" +
1350                 "            2 - expecting attribute value (not \'=\') */\r\n" +
1351                 "        $state = 0;\r\n" +
1352                 "                               \r\n" +
1353                 "        foreach ($tokens as $token) {\r\n" +
1354                 "            switch ($state) {\r\n" +
1355                 "                case 0:\r\n" +
1356                 "                    /* If the token is a valid identifier, we set attribute name\r\n" +
1357                 "                       and go to state 1. */\r\n" +
1358                 "                    if (preg_match(\'!^\\w+$!\', $token)) {\r\n" +
1359                 "                        $attr_name = $token;\r\n" +
1360                 "                        $state = 1;\r\n" +
1361                 "                    } else\r\n" +
1362                 "                        $this->_syntax_error(\"invalid attribute name - \'$token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1363                 "                    break;\r\n" +
1364                 "\r\n" +
1365                 "                case 1:\r\n" +
1366                 "                    /* If the token is \'=\', then we go to state 2. */\r\n" +
1367                 "                    if ($token == \'=\') {\r\n" +
1368                 "                        $state = 2;\r\n" +
1369                 "                    } else\r\n" +
1370                 "                        $this->_syntax_error(\"expecting \'=\' after attribute name \'$last_token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1371                 "                    break;\r\n" +
1372                 "\r\n" +
1373                 "                case 2:\r\n" +
1374                 "                    /* If token is not \'=\', we set the attribute value and go to\r\n" +
1375                 "                       state 0. */\r\n" +
1376                 "                    if ($token != \'=\') {\r\n" +
1377                 "                        /* We booleanize the token if it\'s a non-quoted possible\r\n" +
1378                 "                           boolean value. */\r\n" +
1379                 "                        if (preg_match(\'!^(on|yes|true)$!\', $token))\r\n" +
1380                 "                            $token = true;\r\n" +
1381                 "                        else if (preg_match(\'!^(off|no|false)$!\', $token))\r\n" +
1382                 "                            $token = false;\r\n" +
1383                 "                        /* If the token is just a string,\r\n" +
1384                 "                           we double-quote it. */\r\n" +
1385                 "                        else if (preg_match(\'!^\\w+$!\', $token)) {\r\n" +
1386                 "                            $token = \'\"\'.$token.\'\"\';\r\n" +
1387                 "                                               }\r\n" +
1388                 "\r\n" +
1389                 "                        $attrs[$attr_name] = $token;\r\n" +
1390                 "                        $state = 0;\r\n" +
1391                 "                    } else\r\n" +
1392                 "                        $this->_syntax_error(\"\'=\' cannot be an attribute value\", E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1393                 "                    break;\r\n" +
1394                 "            }\r\n" +
1395                 "                       $last_token = $token;\r\n" +
1396                 "        }\r\n" +
1397                 "\r\n" +
1398                 "               if($state != 0) {\r\n" +
1399                 "                       if($state == 1) {\r\n" +
1400                 "                               $this->_syntax_error(\"expecting \'=\' after attribute name \'$last_token\'\", E_USER_ERROR, __FILE__, __LINE__);                               \r\n" +
1401                 "                       } else {\r\n" +
1402                 "                               $this->_syntax_error(\"missing attribute value\", E_USER_ERROR, __FILE__, __LINE__);                                                            \r\n" +
1403                 "                       }\r\n" +
1404                 "               }\r\n" +
1405                 "               \r\n" +
1406                 "        $this->_parse_vars_props($attrs);\r\n" +
1407                 "\r\n" +
1408                 "        return $attrs;\r\n" +
1409                 "    }\r\n" +
1410                 "\r\n" +
1411                 "       /**\r\n" +
1412                 "        * compile multiple variables and section properties tokens into\r\n" +
1413                 "        * PHP code\r\n" +
1414                 "        *\r\n" +
1415                 "        * @access public\r\n" +
1416                 "        * @param  $tokens\r\n" +
1417                 "        */\r\n" +
1418                 "    function _parse_vars_props(&$tokens)\r\n" +
1419                 "    {\r\n" +
1420                 "               foreach($tokens as $key => $val) {                      \r\n" +
1421                 "               $tokens[$key] = $this->_parse_var_props($val);\r\n" +
1422                 "               }\r\n" +
1423                 "       }\r\n" +
1424                 "               \r\n" +
1425                 "       /**\r\n" +
1426                 "        * compile single variable and section properties token into\r\n" +
1427                 "        * PHP code\r\n" +
1428                 "        *\r\n" +
1429                 "        * @access public\r\n" +
1430                 "        * @param  $val\r\n" +
1431                 "        * @param  $tag_attrs\r\n" +
1432                 "        */\r\n" +
1433                 "    function _parse_var_props($val, $tag_attrs = null)\r\n" +
1434                 "    {                                  \r\n" +
1435                 "\r\n" +
1436                 "               $val = trim($val);\r\n" +
1437                 "\r\n" +
1438                 "        if(preg_match(\'!^(\' . $this->_obj_call_regexp . \'|\' . $this->_dvar_regexp . \')(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n" +
1439                 "                               // $ variable or object\r\n" +
1440                 "                return $this->_parse_var($val, $tag_attrs);\r\n" +
1441                 "                       }                       \r\n" +
1442                 "        elseif(preg_match(\'!^\' . $this->_db_qstr_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n" +
1443                 "                               // double quoted text\r\n" +
1444                 "                               preg_match(\'!^(\' . $this->_db_qstr_regexp . \')(\'. $this->_mod_regexp . \'*)$!\', $val, $match);\r\n" +
1445                 "                $return = $this->_expand_quoted_text($match[1]);\r\n" +
1446                 "                               if($match[2] != \'\') {\r\n" +
1447                 "                                       $this->_parse_modifiers($return, $match[2]);\r\n" +
1448                 "                               }\r\n" +
1449                 "                               return $return;\r\n" +
1450                 "                       }                       \r\n" +
1451                 "        elseif(preg_match(\'!^\' . $this->_si_qstr_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n" +
1452                 "                               // single quoted text\r\n" +
1453                 "                               preg_match(\'!^(\' . $this->_si_qstr_regexp . \')(\'. $this->_mod_regexp . \'*)$!\', $val, $match);\r\n" +
1454                 "                               if($match[2] != \'\') {\r\n" +
1455                 "                                       $this->_parse_modifiers($match[1], $match[2]);\r\n" +
1456                 "                       return $match[1];\r\n" +
1457                 "                               }       \r\n" +
1458                 "                       }                       \r\n" +
1459                 "        elseif(preg_match(\'!^\' . $this->_cvar_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n" +
1460                 "                               // config var\r\n" +
1461                 "                return $this->_parse_conf_var($val);\r\n" +
1462                 "                       }                       \r\n" +
1463                 "        elseif(preg_match(\'!^\' . $this->_svar_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n" +
1464                 "                               // section var\r\n" +
1465                 "                return $this->_parse_section_prop($val);\r\n" +
1466                 "                       }\r\n" +
1467                 "               elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {\r\n" +
1468                 "                       // literal string\r\n" +
1469                 "                       return $this->_expand_quoted_text(\'\"\' . $val .\'\"\');\r\n" +
1470                 "               }\r\n" +
1471                 "               return $val;\r\n" +
1472                 "    }\r\n" +
1473                 "\r\n" +
1474                 "       /**\r\n" +
1475                 "        * expand quoted text with embedded variables\r\n" +
1476                 "        *\r\n" +
1477                 "        * @access public\r\n" +
1478                 "        * @param  $var_expr\r\n" +
1479                 "        */\r\n" +
1480                 "    function _expand_quoted_text($var_expr)\r\n" +
1481                 "    {\r\n" +
1482                 "               // if contains unescaped $, expand it\r\n" +
1483                 "               if(preg_match_all(\'|(?<!\\\\\\\\)\\$\' . $this->_dvar_guts_regexp . \'|\', $var_expr, $match)) {\r\n" +
1484                 "                       rsort($match[0]);\r\n" +
1485                 "                       reset($match[0]);\r\n" +
1486                 "                       foreach($match[0] as $var) {\r\n" +
1487                 "                $var_expr = str_replace ($var, \'\".\' . $this->_parse_var($var) . \'.\"\', $var_expr);\r\n" +
1488                 "                       }\r\n" +
1489                 "            return preg_replace(\'!\\.\"\"|\"\"\\.!\', \'\', $var_expr);\r\n" +
1490                 "               } else {\r\n" +
1491                 "                       return $var_expr;\r\n" +
1492                 "               }\r\n" +
1493                 "       }\r\n" +
1494                 "       \r\n" +
1495                 "       /**\r\n" +
1496                 "        * parse variable expression into PHP code\r\n" +
1497                 "        *\r\n" +
1498                 "        * @access public\r\n" +
1499                 "        * @param  $var_expr\r\n" +
1500                 "        */\r\n" +
1501                 "    function _parse_var($var_expr)\r\n" +
1502                 "    {\r\n" +
1503                 "                               \r\n" +
1504                 "               preg_match(\'!(\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp . \')(\' . $this->_mod_regexp . \'*)$!\', $var_expr, $match);\r\n" +
1505                 "                               \r\n" +
1506                 "        $var_ref = substr($match[1],1);\r\n" +
1507                 "        $modifiers = $match[2];\r\n" +
1508                 "                                               \r\n" +
1509                 "               if(!empty($this->default_modifiers) && !preg_match(\'!(^|\\|)smarty:nodefaults($|\\|)!\',$modifiers)) {\r\n" +
1510                 "                       $_default_mod_string = implode(\'|\',(array)$this->default_modifiers);\r\n" +
1511                 "                       $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . \'|\' . $modifiers;\r\n" +
1512                 "               }\r\n" +
1513                 "\r\n" +
1514                 "               // get [foo] and .foo and ->foo() pieces                        \r\n" +
1515                 "        preg_match_all(\'!(?:^\\w+)|(?:\' . $this->_obj_ext_regexp . \')+(?:\' . $this->_obj_params_regexp . \')?|(?:\' . $this->_var_bracket_regexp . \')|\\.\\$?\\w+!\', $var_ref, $match);          \r\n" +
1516                 "               \r\n" +
1517                 "        $indexes = $match[0];\r\n" +
1518                 "        $var_name = array_shift($indexes);\r\n" +
1519                 "                               \r\n" +
1520                 "        /* Handle $smarty.* variable references as a special case. */\r\n" +
1521                 "        if ($var_name == \'smarty\') {\r\n" +
1522                 "            /*\r\n" +
1523                 "             * If the reference could be compiled, use the compiled output;\r\n" +
1524                 "             * otherwise, fall back on the $smarty variable generated at\r\n" +
1525                 "             * run-time.\r\n" +
1526                 "             */\r\n" +
1527                 "            if (($smarty_ref = $this->_compile_smarty_ref($indexes)) !== null) {\r\n" +
1528                 "                $output = $smarty_ref;\r\n" +
1529                 "            } else {\r\n" +
1530                 "                $var_name = substr(array_shift($indexes), 1);\r\n" +
1531                 "                $output = \"\\$this->_smarty_vars[\'$var_name\']\";\r\n" +
1532                 "            }\r\n" +
1533                 "        } else {\r\n" +
1534                 "            $output = \"\\$this->_tpl_vars[\'$var_name\']\";\r\n" +
1535                 "        }\r\n" +
1536                 "\r\n" +
1537                 "        foreach ($indexes as $index) {                 \r\n" +
1538                 "            if ($index{0} == \'[\') {\r\n" +
1539                 "                $index = substr($index, 1, -1);\r\n" +
1540                 "                if (is_numeric($index)) {\r\n" +
1541                 "                    $output .= \"[$index]\";\r\n" +
1542                 "                } elseif ($index{0} == \'$\') {\r\n" +
1543                 "                    $output .= \"[\\$this->_tpl_vars[\'\" . substr($index, 1) . \"\']]\";\r\n" +
1544                 "                } else {\r\n" +
1545                 "                    $parts = explode(\'.\', $index);\r\n" +
1546                 "                    $section = $parts[0];\r\n" +
1547                 "                    $section_prop = isset($parts[1]) ? $parts[1] : \'index\';\r\n" +
1548                 "                    $output .= \"[\\$this->_sections[\'$section\'][\'$section_prop\']]\";\r\n" +
1549                 "                }\r\n" +
1550                 "            } else if ($index{0} == \'.\') {\r\n" +
1551                 "                if ($index{1} == \'$\')\r\n" +
1552                 "                    $output .= \"[\\$this->_tpl_vars[\'\" . substr($index, 2) . \"\']]\";\r\n" +
1553                 "                else\r\n" +
1554                 "                    $output .= \"[\'\" . substr($index, 1) . \"\']\";\r\n" +
1555                 "            } else if (substr($index,0,2) == \'->\') {\r\n" +
1556                 "                               if(substr($index,2,2) == \'__\') {\r\n" +
1557                 "                                       $this->_syntax_error(\'call to internal object members is not allowed\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1558                 "                               } elseif($this->security && substr($index,2,1) == \'_\') {\r\n" +
1559                 "                                       $this->_syntax_error(\'(secure) call to private object member is not allowed\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1560                 "                               } else {\r\n" +
1561                 "                                       if(preg_match(\'!((?:\' . $this->_obj_ext_regexp . \')+)(\' . $this->_obj_params_regexp . \')?!\', $index, $match)) {\r\n" +
1562                 "                                               if(!empty($match[2])) {\r\n" +
1563                 "                                                       // parse object parameters\r\n" +
1564                 "                                                       $index = str_replace($match[2], $this->_parse_parenth_args($match[2]), $index);\r\n" +
1565                 "                                               }\r\n" +
1566                 "                                               if(preg_match_all(\'!\' . $this->_dvar_regexp . \'!\', $match[1], $_dvar_match)) {\r\n" +
1567                 "                                                       // parse embedded variables\r\n" +
1568                 "                                                       $_match_replace = $match[1];\r\n" +
1569                 "                                                       foreach($_dvar_match[0] as $_curr_var) {\r\n" +
1570                 "                                                               $_match_replace = str_replace($_curr_var, \'{\' . $this->_parse_var($_curr_var) . \'}\', $_match_replace);\r\n" +
1571                 "                                                       }\r\n" +
1572                 "                                                       $index = str_replace($match[1], $_match_replace, $index);\r\n" +
1573                 "                                               }\r\n" +
1574                 "                                       }\r\n" +
1575                 "                                       $output .= $index;\r\n" +
1576                 "                               }\r\n" +
1577                 "            } else {\r\n" +
1578                 "                $output .= $index;\r\n" +
1579                 "            }\r\n" +
1580                 "        }\r\n" +
1581                 "\r\n" +
1582                 "               // look for variables imbedded in quoted strings, replace them\r\n" +
1583                 "        if(preg_match(\'!\' . $this->_qstr_regexp . \'!\', $output, $match)) {\r\n" +
1584                 "                       $output = str_replace($match[0], $this->_expand_quoted_text($match[0]), $output);\r\n" +
1585                 "               }\r\n" +
1586                 "               \r\n" +
1587                 "        $this->_parse_modifiers($output, $modifiers);\r\n" +
1588                 "\r\n" +
1589                 "        return $output;\r\n" +
1590                 "    }\r\n" +
1591                 "\r\n" +
1592                 "       /**\r\n" +
1593                 "        * parse arguments in function call parenthesis\r\n" +
1594                 "        *\r\n" +
1595                 "        * @access public\r\n" +
1596                 "        * @param  $parenth_args\r\n" +
1597                 "        */\r\n" +
1598                 "    function _parse_parenth_args($parenth_args)\r\n" +
1599                 "    {\r\n" +
1600                 "               preg_match_all(\'!\' . $this->_param_regexp . \'!\',$parenth_args, $match);\r\n" +
1601                 "               $match = $match[0];\r\n" +
1602                 "               rsort($match);\r\n" +
1603                 "               reset($match);                                          \r\n" +
1604                 "               $orig_vals = $match;\r\n" +
1605                 "               $this->_parse_vars_props($match);\r\n" +
1606                 "               return str_replace($orig_vals, $match, $parenth_args);\r\n" +
1607                 "       }       \r\n" +
1608                 "               \r\n" +
1609                 "       /**\r\n" +
1610                 "        * parse configuration variable expression into PHP code\r\n" +
1611                 "        *\r\n" +
1612                 "        * @access public\r\n" +
1613                 "        * @param  $conf_var_expr\r\n" +
1614                 "        */\r\n" +
1615                 "    function _parse_conf_var($conf_var_expr)\r\n" +
1616                 "    {\r\n" +
1617                 "        $parts = explode(\'|\', $conf_var_expr, 2);\r\n" +
1618                 "        $var_ref = $parts[0];\r\n" +
1619                 "        $modifiers = isset($parts[1]) ? $parts[1] : \'\';\r\n" +
1620                 "\r\n" +
1621                 "        $var_name = substr($var_ref, 1, -1);\r\n" +
1622                 "\r\n" +
1623                 "        $output = \"\\$this->_config[0][\'vars\'][\'$var_name\']\";\r\n" +
1624                 "\r\n" +
1625                 "        $this->_parse_modifiers($output, $modifiers);\r\n" +
1626                 "\r\n" +
1627                 "        return $output;\r\n" +
1628                 "    }\r\n" +
1629                 "\r\n" +
1630                 "\r\n" +
1631                 "       /**\r\n" +
1632                 "        * parse section property expression into PHP code\r\n" +
1633                 "        *\r\n" +
1634                 "        * @access public\r\n" +
1635                 "        * @param  $section_prop_expr\r\n" +
1636                 "        */\r\n" +
1637                 "    function _parse_section_prop($section_prop_expr)\r\n" +
1638                 "    {\r\n" +
1639                 "        $parts = explode(\'|\', $section_prop_expr, 2);\r\n" +
1640                 "        $var_ref = $parts[0];\r\n" +
1641                 "        $modifiers = isset($parts[1]) ? $parts[1] : \'\';\r\n" +
1642                 "\r\n" +
1643                 "        preg_match(\'!%(\\w+)\\.(\\w+)%!\', $var_ref, $match);\r\n" +
1644                 "        $section_name = $match[1];\r\n" +
1645                 "        $prop_name = $match[2];\r\n" +
1646                 "\r\n" +
1647                 "        $output = \"\\$this->_sections[\'$section_name\'][\'$prop_name\']\";\r\n" +
1648                 "\r\n" +
1649                 "        $this->_parse_modifiers($output, $modifiers);\r\n" +
1650                 "\r\n" +
1651                 "        return $output;\r\n" +
1652                 "    }\r\n" +
1653                 "\r\n" +
1654                 "\r\n" +
1655                 "       /**\r\n" +
1656                 "        * parse modifier chain into PHP code\r\n" +
1657                 "        *\r\n" +
1658                 "        * @access public\r\n" +
1659                 "        * @param  $output\r\n" +
1660                 "        * @param  $modifier_string\r\n" +
1661                 "        */\r\n" +
1662                 "    function _parse_modifiers(&$output, $modifier_string)\r\n" +
1663                 "    {\r\n" +
1664                 "        preg_match_all(\'!\\|(@?\\w+)((?>:(?:\'. $this->_qstr_regexp . \'|[^|]+))*)!\', \'|\' . $modifier_string, $match);\r\n" +
1665                 "        list(, $modifiers, $modifier_arg_strings) = $match;\r\n" +
1666                 "\r\n" +
1667                 "        for ($i = 0, $for_max = count($modifiers); $i < $for_max; $i++) {\r\n" +
1668                 "            $modifier_name = $modifiers[$i];\r\n" +
1669                 "                       \r\n" +
1670                 "                       if($modifier_name == \'smarty\') {\r\n" +
1671                 "                               // skip smarty modifier\r\n" +
1672                 "                               continue;\r\n" +
1673                 "                       }\r\n" +
1674                 "                       \r\n" +
1675                 "            preg_match_all(\'!:(\' . $this->_qstr_regexp . \'|[^:]+)!\', $modifier_arg_strings[$i], $match);\r\n" +
1676                 "            $modifier_args = $match[1];\r\n" +
1677                 "\r\n" +
1678                 "            if ($modifier_name{0} == \'@\') {\r\n" +
1679                 "                $map_array = \'false\';\r\n" +
1680                 "                $modifier_name = substr($modifier_name, 1);\r\n" +
1681                 "            } else {\r\n" +
1682                 "                $map_array = \'true\';\r\n" +
1683                 "            }\r\n" +
1684                 "                       \r\n" +
1685                 "            $this->_add_plugin(\'modifier\', $modifier_name);\r\n" +
1686                 "\r\n" +
1687                 "            $this->_parse_vars_props($modifier_args);\r\n" +
1688                 "\r\n" +
1689                 "            if (count($modifier_args) > 0)\r\n" +
1690                 "                $modifier_args = \', \'.implode(\', \', $modifier_args);\r\n" +
1691                 "            else\r\n" +
1692                 "                $modifier_args = \'\';\r\n" +
1693                 "\r\n" +
1694                 "            $output = \"\\$this->_run_mod_handler(\'$modifier_name\', $map_array, $output$modifier_args)\";\r\n" +
1695                 "        }\r\n" +
1696                 "    }\r\n" +
1697                 "\r\n" +
1698                 "\r\n" +
1699                 "       /**\r\n" +
1700                 "        * add plugin\r\n" +
1701                 "        *\r\n" +
1702                 "        * @access public\r\n" +
1703                 "        * @param  $type\r\n" +
1704                 "        * @param  $name\r\n" +
1705                 "        * @param  $delayed_loading\r\n" +
1706                 "        */\r\n" +
1707                 "    function _add_plugin($type, $name, $delayed_loading = null)\r\n" +
1708                 "    {\r\n" +
1709                 "        if (!isset($this->_plugin_info[$type])) {\r\n" +
1710                 "            $this->_plugin_info[$type] = array();\r\n" +
1711                 "        }\r\n" +
1712                 "        if (!isset($this->_plugin_info[$type][$name])) {\r\n" +
1713                 "            $this->_plugin_info[$type][$name] = array($this->_current_file,\r\n" +
1714                 "                                                      $this->_current_line_no,\r\n" +
1715                 "                                                      $delayed_loading);\r\n" +
1716                 "        }\r\n" +
1717                 "    }\r\n" +
1718                 "    \r\n" +
1719                 "\r\n" +
1720                 "       /**\r\n" +
1721                 "        * Compiles references of type $smarty.foo\r\n" +
1722                 "        *\r\n" +
1723                 "        * @access public\r\n" +
1724                 "        * @param  $indexes\r\n" +
1725                 "        */\r\n" +
1726                 "    function _compile_smarty_ref(&$indexes)\r\n" +
1727                 "    {\r\n" +
1728                 "        /* Extract the reference name. */\r\n" +
1729                 "        $ref = substr($indexes[0], 1);\r\n" +
1730                 "\r\n" +
1731                 "        switch ($ref) {\r\n" +
1732                 "            case \'now\':\r\n" +
1733                 "                $compiled_ref = \'time()\';\r\n" +
1734                 "                if (count($indexes) > 1) {\r\n" +
1735                 "                    $this->_syntax_error(\'$smarty\' . implode(\'\', $indexes) .\' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1736                 "                }\r\n" +
1737                 "                break;\r\n" +
1738                 "\r\n" +
1739                 "            case \'foreach\':\r\n" +
1740                 "            case \'section\':\r\n" +
1741                 "                if ($indexes[1]{0} != \'.\') {\r\n" +
1742                 "                    $this->_syntax_error(\'$smarty\' . implode(\'\', array_slice($indexes, 0, 2)) . \' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1743                 "                }\r\n" +
1744                 "                $name = substr($indexes[1], 1);\r\n" +
1745                 "                array_shift($indexes);\r\n" +
1746                 "                if ($ref == \'foreach\')\r\n" +
1747                 "                    $compiled_ref = \"\\$this->_foreach[\'$name\']\";\r\n" +
1748                 "                else\r\n" +
1749                 "                    $compiled_ref = \"\\$this->_sections[\'$name\']\";\r\n" +
1750                 "                break;\r\n" +
1751                 "\r\n" +
1752                 "            case \'get\':\r\n" +
1753                 "                array_shift($indexes);\r\n" +
1754                 "                $compiled_ref = \"\\$_GET\";\r\n" +
1755                 "                if ($name = substr($indexes[0], 1))\r\n" +
1756                 "                    $compiled_ref .= \"[\'$name\']\";\r\n" +
1757                 "                break;\r\n" +
1758                 "\r\n" +
1759                 "            case \'post\':\r\n" +
1760                 "                array_shift($indexes);\r\n" +
1761                 "                $name = substr($indexes[0], 1);\r\n" +
1762                 "                $compiled_ref = \"\\$_POST\";\r\n" +
1763                 "                if ($name = substr($indexes[0], 1))\r\n" +
1764                 "                    $compiled_ref .= \"[\'$name\']\";\r\n" +
1765                 "                break;\r\n" +
1766                 "\r\n" +
1767                 "            case \'cookies\':\r\n" +
1768                 "                array_shift($indexes);\r\n" +
1769                 "                $name = substr($indexes[0], 1);\r\n" +
1770                 "                $compiled_ref = \"\\$_COOKIE\";\r\n" +
1771                 "                if ($name = substr($indexes[0], 1))\r\n" +
1772                 "                    $compiled_ref .= \"[\'$name\']\";\r\n" +
1773                 "                break;\r\n" +
1774                 "\r\n" +
1775                 "            case \'env\':\r\n" +
1776                 "                array_shift($indexes);\r\n" +
1777                 "                $compiled_ref = \"\\$_ENV\";\r\n" +
1778                 "                if ($name = substr($indexes[0], 1))\r\n" +
1779                 "                    $compiled_ref .= \"[\'$name\']\";\r\n" +
1780                 "                break;\r\n" +
1781                 "\r\n" +
1782                 "            case \'server\':\r\n" +
1783                 "                array_shift($indexes);\r\n" +
1784                 "                $name = substr($indexes[0], 1);\r\n" +
1785                 "                $compiled_ref = \"\\$_SERVER\";\r\n" +
1786                 "                if ($name = substr($indexes[0], 1))\r\n" +
1787                 "                    $compiled_ref .= \"[\'$name\']\";\r\n" +
1788                 "                break;\r\n" +
1789                 "\r\n" +
1790                 "            case \'session\':\r\n" +
1791                 "                array_shift($indexes);\r\n" +
1792                 "                $name = substr($indexes[0], 1);\r\n" +
1793                 "                $compiled_ref = \"\\$_SESSION\";\r\n" +
1794                 "                if ($name = substr($indexes[0], 1))\r\n" +
1795                 "                    $compiled_ref .= \"[\'$name\']\";\r\n" +
1796                 "                break;\r\n" +
1797                 "\r\n" +
1798                 "            /*\r\n" +
1799                 "             * These cases are handled either at run-time or elsewhere in the\r\n" +
1800                 "             * compiler.\r\n" +
1801                 "             */\r\n" +
1802                 "            case \'request\':\r\n" +
1803                 "                $this->_init_smarty_vars = true;\r\n" +
1804                 "                return null;\r\n" +
1805                 "\r\n" +
1806                 "            case \'capture\':\r\n" +
1807                 "                return null;\r\n" +
1808                 "\r\n" +
1809                 "            case \'template\':\r\n" +
1810                 "                $compiled_ref = \"\'$this->_current_file\'\";\r\n" +
1811                 "                if (count($indexes) > 1) {\r\n" +
1812                 "                    $this->_syntax_error(\'$smarty\' . implode(\'\', $indexes) .\' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1813                 "                }\r\n" +
1814                 "                break;\r\n" +
1815                 "                               \r\n" +
1816                 "                       case \'version\':\r\n" +
1817                 "                               $compiled_ref = \"\'$this->_version\'\";\r\n" +
1818                 "                               break;\r\n" +
1819                 "\r\n" +
1820                 "                       case \'const\':\r\n" +
1821                 "                array_shift($indexes);\r\n" +
1822                 "                               $compiled_ref = \'defined(\\\'\' . substr($indexes[0],1) . \'\\\') ? \' . substr($indexes[0],1) . \' : null\';\r\n" +
1823                 "                break;\r\n" +
1824                 "\r\n" +
1825                 "            default:\r\n" +
1826                 "                $this->_syntax_error(\'$smarty.\' . $ref . \' is an unknown reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n" +
1827                 "                break;\r\n" +
1828                 "        }\r\n" +
1829                 "\r\n" +
1830                 "        array_shift($indexes);\r\n" +
1831                 "        return $compiled_ref;\r\n" +
1832                 "    }\r\n" +
1833                 "\r\n" +
1834                 "\r\n" +
1835                 "       /**\r\n" +
1836                 "        * load pre- and post-filters\r\n" +
1837                 "        *\r\n" +
1838                 "        * @access public\r\n" +
1839                 "        */\r\n" +
1840                 "    function _load_filters()\r\n" +
1841                 "    {\r\n" +
1842                 "        if (count($this->_plugins[\'prefilter\']) > 0) {\r\n" +
1843                 "            foreach ($this->_plugins[\'prefilter\'] as $filter_name => $prefilter) {\r\n" +
1844                 "                if ($prefilter === false) {\r\n" +
1845                 "                    unset($this->_plugins[\'prefilter\'][$filter_name]);\r\n" +
1846                 "                    $this->_load_plugins(array(array(\'prefilter\', $filter_name, null, null, false)));\r\n" +
1847                 "                }\r\n" +
1848                 "            }\r\n" +
1849                 "        }\r\n" +
1850                 "        if (count($this->_plugins[\'postfilter\']) > 0) {\r\n" +
1851                 "            foreach ($this->_plugins[\'postfilter\'] as $filter_name => $postfilter) {\r\n" +
1852                 "                if ($postfilter === false) {\r\n" +
1853                 "                    unset($this->_plugins[\'postfilter\'][$filter_name]);\r\n" +
1854                 "                    $this->_load_plugins(array(array(\'postfilter\', $filter_name, null, null, false)));\r\n" +
1855                 "                }\r\n" +
1856                 "            }\r\n" +
1857                 "        }\r\n" +
1858                 "    }\r\n" +
1859                 "\r\n" +
1860                 "\r\n" +
1861                 "       /**\r\n" +
1862                 "        * display Smarty syntax error\r\n" +
1863                 "        *\r\n" +
1864                 "        * @access public\r\n" +
1865                 "        * @param  $error_msg\r\n" +
1866                 "        * @param  $error_type\r\n" +
1867                 "        * @param  $file\r\n" +
1868                 "        * @param  $line\r\n" +
1869                 "        */\r\n" +
1870                 "    function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)\r\n" +
1871                 "    {\r\n" +
1872                 "               if(isset($file) && isset($line)) {\r\n" +
1873                 "                       $info = \' (\'.basename($file).\", line $line)\";\r\n" +
1874                 "               } else {\r\n" +
1875                 "                       $info = null;\r\n" +
1876                 "               }\r\n" +
1877                 "        trigger_error(\'Smarty: [in \' . $this->_current_file . \' line \' .\r\n" +
1878                 "                      $this->_current_line_no . \"]: syntax error: $error_msg$info\", $error_type);\r\n" +
1879                 "    }\r\n" +
1880                 "}\r\n" +
1881                 "\r\n" +
1882                 "/**\r\n" +
1883                 " * compare to values by their string length\r\n" +
1884                 " *\r\n" +
1885                 " * @access private\r\n" +
1886                 " * @param  $a\r\n" +
1887                 " * @param  $b\r\n" +
1888                 " */\r\n" +
1889                 "function _smarty_sort_length($a, $b)\r\n" +
1890                 "{\r\n" +
1891                 "       if($a == $b)\r\n" +
1892                 "               return 0;\r\n" +
1893                 "\r\n" +
1894                 "       if(strlen($a) == strlen($b))\r\n" +
1895                 "               return ($a > $b) ? -1 : 1;\r\n" +
1896                 "\r\n" +
1897                 "       return (strlen($a) > strlen($b)) ? -1 : 1;\r\n" +
1898                 "}\r\n" +
1899                 "\r\n" +
1900                 "\r\n" +
1901                 "/* vim: set et: */\r\n" +
1902                 "\r\n" +
1903                 "?>\r\n" +
1904                 "");
1905   }
1906   private void checkPHP(String strEval) {
1907     if (Scanner.DEBUG) {
1908       System.out.println("\n------------------------------------");
1909       System.out.println(strEval);
1910     }
1911     checkParsePHP(
1912         strEval.toCharArray(),
1913                 "");
1914 //    parser.phpParserTester(strEval, 1);
1915   }
1916 }