(0004622)
|
sblommers
|
05-31-10 06:46
|
|
<?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;
}
} |
|