<?php

ini_set('display_errors','1');
error_reporting(E_ALL);


define('SYMBOL_PARSE_NAME',0);
define('SYMBOL_PARSE_PARAM',1);

define('TC_SYMBOL',0);
define('TC_KNOWN',1); 
define('TC_PARAMETER',3);

// Should display 101112 ; on Quercus displays 101010
for ($i=10;$i<13;$i++)
{
	$x=do_template(array(
		'VAR'=>strval($i),
	));
	echo $x->bits[0][2][0]->bits[0][1];
}

function read_single_uncompiled_symbol($text,&$symbol_pos,$symbol_len)
{
	$type=TC_PARAMETER;
	$mode=SYMBOL_PARSE_NAME;
	$name='';
	$param=array(); // Note about Quercus: I have simplified the code to assume there's only a single param to go in here. However I did find if the array is removed and we write into a direct variable then the bug does not happen.
	$starting=true;

	while (true)
	{
		$next=$text[$symbol_pos];
		++$symbol_pos;

		switch ($mode)
		{
			case SYMBOL_PARSE_PARAM:
				switch ($next)
				{
					case '}':
						$ret=array($type,$name,$param);
						return $ret;

					case '{':
						$ret=read_single_uncompiled_symbol($text,$symbol_pos,$symbol_len);
						$param[0]->bits[]=$ret;
						break;

					default:
						$param[0]->attach($next);
				}
				break;

			case SYMBOL_PARSE_NAME:
				if ($starting)
				{
					$starting=false;
					switch($next)
					{
						case '$':
							$type=TC_SYMBOL;
							continue 2;
					}
				}
				switch ($next)
				{
					case '}':
						$ret=array($type,$name,array());
						return $ret;

					case ',':
						$mode=SYMBOL_PARSE_PARAM;
						$param[0]=new ocp_tempcode();
						break;

					default:
						$name.=$next;
				}
				break;
		}

		if ($symbol_pos>=$symbol_len)
		{
			return array(TC_KNOWN,'',array());
		}
	}
}

function do_template($parameters)
{
	static $TEMPLATE_CACHE=NULL;
	$codename='test';

	if (isset($TEMPLATE_CACHE)) // Primed cache. However on Quercus, as the call to "->bind" tampered with the cache data too, this is already hard-bound and thus returns the same result
	{
		$_data=$TEMPLATE_CACHE->bind($parameters,$codename);
		return $_data;
	}


	// Re-parse

	$text='{$BLAH,{VAR}}'; // I've hard-coded a template for this bug report, and simplifed the parsing to just assume it is reading in a single symbol
	$out=new ocp_tempcode();
	$symbol_len=strlen($text);
	$symbol_pos=1;
	$ret=read_single_uncompiled_symbol($text,$symbol_pos,$symbol_len);
	$out->bits[]=$ret;
	
	$TEMPLATE_CACHE=$out;

	return $out->bind($parameters,$codename); // On Quercus, $out ends up altered, which should be impossible
}

class ocp_tempcode
{
	var $bits=array(); // A list of tripes; each triple is: component type, name/data, binding parameters.

	function attach($attach)
	{
		$this->bits[]=array(TC_KNOWN,$attach,array());
	}

	function bind(&$parameters,$codename)
	{
		$out=new ocp_tempcode();

		foreach ($this->bits as $bit)
		{
			if ($bit[0]==TC_SYMBOL) // Binds data to symbols
			{
				foreach ($bit[2] as $i=>$param)
				{
					$bit[2][$i]=$param->bind($parameters,$codename); // On Quercus "$param->bind($parameters,$codename);" is actually modifying $param, which should be impossible
				}
			}

			if ($bit[0]==TC_PARAMETER)
			{
				$out->attach($parameters[$bit[1]]); // The actual binding operation
			}  else
			{
				$out->bits[]=$bit;
			}
		}

		return $out;
	}
}
