Decompiler: simple cover test, make sure all opcode is tested
git-svn-id: svn://svn.lighttpd.net/xcache/trunk@761 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
This commit is contained in:
parent
26a6230a83
commit
1be06bf44c
|
@ -70,13 +70,13 @@ function value($value) // {{{
|
|||
return $value;
|
||||
}
|
||||
// }}}
|
||||
function unquoteName_($str, $asProperty, $indent = '') // {{{
|
||||
function unquoteName_($str, $asVariableName, $indent = '') // {{{
|
||||
{
|
||||
$str = str($str, $indent);
|
||||
if (preg_match("!^'[\\w_][\\w\\d_\\\\]*'\$!", $str)) {
|
||||
return str_replace('\\\\', '\\', substr($str, 1, -1));
|
||||
}
|
||||
else if ($asProperty) {
|
||||
else if ($asVariableName) {
|
||||
return "{" . $str . "}";
|
||||
}
|
||||
else {
|
||||
|
@ -84,7 +84,7 @@ function unquoteName_($str, $asProperty, $indent = '') // {{{
|
|||
}
|
||||
}
|
||||
// }}}
|
||||
function unquoteProperty($str, $indent = '') // {{{
|
||||
function unquoteVariableName($str, $indent = '') // {{{
|
||||
{
|
||||
return unquoteName_($str, true, $indent);
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ class Decompiler_Dim extends Decompiler_Value // {{{
|
|||
$last = count($this->offsets) - 1;
|
||||
foreach ($this->offsets as $i => $dim) {
|
||||
if ($this->isObject && $i == $last) {
|
||||
$exp .= '->' . unquoteProperty($dim, $indent);
|
||||
$exp .= '->' . unquoteVariableName($dim, $indent);
|
||||
}
|
||||
else {
|
||||
$exp .= '[' . str($dim, $indent) . ']';
|
||||
|
@ -436,6 +436,20 @@ class Decompiler
|
|||
|
||||
function Decompiler()
|
||||
{
|
||||
// {{{ testing
|
||||
// XC_UNDEF XC_OP_DATA
|
||||
$this->test = !empty($_ENV['XCACHE_DECOMPILER_TEST']);
|
||||
$this->usedOps = array();
|
||||
|
||||
if ($this->test) {
|
||||
$content = file_get_contents(__FILE__);
|
||||
for ($i = 0; $opname = xcache_get_opcode($i); $i ++) {
|
||||
if (!preg_match("/\\bXC_" . $opname . "\\b(?!')/", $content)) {
|
||||
echo "not recognized opcode ", $opname, "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
// {{{ opinfo
|
||||
$this->unaryops = array(
|
||||
XC_BW_NOT => '~',
|
||||
|
@ -618,6 +632,7 @@ class Decompiler
|
|||
if ($removeTailing) {
|
||||
$last = count($opcodes) - 1;
|
||||
if ($opcodes[$last]['opcode'] == XC_HANDLE_EXCEPTION) {
|
||||
$this->usedOps[XC_HANDLE_EXCEPTION] = true;
|
||||
unset($opcodes[$last]);
|
||||
--$last;
|
||||
}
|
||||
|
@ -881,6 +896,7 @@ class Decompiler
|
|||
$op = &$opcodes[$i];
|
||||
$opc = $op['opcode'];
|
||||
if ($opc == XC_NOP) {
|
||||
$this->usedOps[$opc] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -910,9 +926,11 @@ class Decompiler
|
|||
|
||||
$call = array(&$this, $opname);
|
||||
if (is_callable($call)) {
|
||||
$this->usedOps[$opc] = true;
|
||||
$this->{$opname}($op, $EX);
|
||||
}
|
||||
else if (isset($this->binops[$opc])) { // {{{
|
||||
$this->usedOps[$opc] = true;
|
||||
$op1val = $this->getOpVal($op1, $EX, false);
|
||||
$op2val = $this->getOpVal($op2, $EX, false);
|
||||
$rvalue = new Decompiler_Binop($this, $op1val, $opc, $op2val);
|
||||
|
@ -920,6 +938,7 @@ class Decompiler
|
|||
// }}}
|
||||
}
|
||||
else if (isset($this->unaryops[$opc])) { // {{{
|
||||
$this->usedOps[$opc] = true;
|
||||
$op1val = $this->getOpVal($op1, $EX);
|
||||
$myop = $this->unaryops[$opc];
|
||||
$rvalue = $myop . str($op1val);
|
||||
|
@ -927,6 +946,7 @@ class Decompiler
|
|||
// }}}
|
||||
}
|
||||
else {
|
||||
$covered = true;
|
||||
switch ($opc) {
|
||||
case XC_NEW: // {{{
|
||||
array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
|
||||
|
@ -1164,7 +1184,7 @@ class Decompiler
|
|||
if (!isset($obj)) {
|
||||
$obj = '$this';
|
||||
}
|
||||
$rvalue = str($obj) . "->" . unquoteProperty($this->getOpVal($op2, $EX), $EX);
|
||||
$rvalue = str($obj) . "->" . unquoteVariableName($this->getOpVal($op2, $EX), $EX);
|
||||
if ($res['op_type'] != XC_IS_UNUSED) {
|
||||
$resvar = $rvalue;
|
||||
}
|
||||
|
@ -1181,13 +1201,7 @@ class Decompiler
|
|||
case XC_ISSET_ISEMPTY:
|
||||
case XC_ISSET_ISEMPTY_VAR: // {{{
|
||||
if ($opc == XC_ISSET_ISEMPTY_VAR) {
|
||||
$rvalue = $this->getOpVal($op1, $EX);;
|
||||
if (preg_match($this->rQuotedName, $rvalue)) {
|
||||
$rvalue = '$' . substr($rvalue, 1, -1);
|
||||
}
|
||||
else {
|
||||
$rvalue = '${' . $rvalue . '}';
|
||||
}
|
||||
$rvalue = $this->getOpVal($op1, $EX);
|
||||
if ($op2['EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
|
||||
$class = $this->getOpVal($op2, $EX);
|
||||
$rvalue = $class . '::' . $rvalue;
|
||||
|
@ -1200,15 +1214,13 @@ class Decompiler
|
|||
$container = $this->getOpVal($op1, $EX);
|
||||
$dim = $this->getOpVal($op2, $EX);
|
||||
if ($opc == XC_ISSET_ISEMPTY_PROP_OBJ) {
|
||||
if (preg_match($this->rQuotedName, $dim)) {
|
||||
$rvalue = $container . "->" . substr($dim, 1, -1);
|
||||
}
|
||||
else {
|
||||
$rvalue = $container . "->{" . $dim . "}";
|
||||
if (!isset($container)) {
|
||||
$container = '$this';
|
||||
}
|
||||
$rvalue = $container . "->" . unquoteVariableName($dim);
|
||||
}
|
||||
else {
|
||||
$rvalue = $container . "[$dim]";
|
||||
$rvalue = $container . '[' . str($dim) .']';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1356,6 +1368,7 @@ class Decompiler
|
|||
else {
|
||||
break;
|
||||
}
|
||||
$this->usedOps[XC_ADD_INTERFACE] = true;
|
||||
|
||||
$fetchop = &$opcodes[$i + 1];
|
||||
$interface = $this->stripNamespace(unquoteName($this->getOpVal($fetchop['op2'], $EX), $EX));
|
||||
|
@ -1401,7 +1414,7 @@ class Decompiler
|
|||
break;
|
||||
case XC_PRINT: // {{{
|
||||
$op1val = $this->getOpVal($op1, $EX);
|
||||
$resvar = "print($op1val)";
|
||||
$resvar = "print(" . str($op1val) . ")";
|
||||
break;
|
||||
// }}}
|
||||
case XC_ECHO: // {{{
|
||||
|
@ -1583,7 +1596,7 @@ class Decompiler
|
|||
case XC_PRE_INC_OBJ: // {{{
|
||||
$flags = array_flip(explode('_', $opname));
|
||||
if (isset($flags['OBJ'])) {
|
||||
$resvar = $this->getOpVal($op1, $EX) . '->' . unquoteProperty($this->getOpVal($op2, $EX), $EX);
|
||||
$resvar = $this->getOpVal($op1, $EX) . '->' . unquoteVariableName($this->getOpVal($op2, $EX), $EX);
|
||||
}
|
||||
else {
|
||||
$resvar = $this->getOpVal($op1, $EX);
|
||||
|
@ -1660,8 +1673,12 @@ class Decompiler
|
|||
break;
|
||||
default: // {{{
|
||||
echo "\x1B[31m * TODO ", $opname, "\x1B[0m\n";
|
||||
$covered = false;
|
||||
// }}}
|
||||
}
|
||||
if ($covered) {
|
||||
$this->usedOps[$opc] = true;
|
||||
}
|
||||
}
|
||||
if (isset($resvar)) {
|
||||
if ($istmpres) {
|
||||
|
@ -2078,9 +2095,26 @@ class Decompiler
|
|||
|
||||
$this->dop_array($this->dc['op_array']);
|
||||
echo "\n?" . ">\n";
|
||||
|
||||
if (!empty($this->test)) {
|
||||
$this->outputUnusedOp();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// }}}
|
||||
function outputUnusedOp() // {{{
|
||||
{
|
||||
for ($i = 0; $opname = xcache_get_opcode($i); $i ++) {
|
||||
if ($opname == 'UNDEF') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($this->usedOps[$i])) {
|
||||
echo "not covered opcode ", $opname, "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
}
|
||||
|
||||
// {{{ defines
|
||||
|
@ -2186,10 +2220,10 @@ define('BYREF_FORCE_REST', 3);
|
|||
define('IS_NULL', 0);
|
||||
define('IS_LONG', 1);
|
||||
define('IS_DOUBLE', 2);
|
||||
define('IS_STRING', 3);
|
||||
define('IS_BOOL', ZEND_ENGINE_2 ? 3 : 6);
|
||||
define('IS_ARRAY', 4);
|
||||
define('IS_OBJECT', 5);
|
||||
define('IS_BOOL', 6);
|
||||
define('IS_STRING', ZEND_ENGINE_2 ? 6 : 3);
|
||||
define('IS_RESOURCE', 7);
|
||||
define('IS_CONSTANT', 8);
|
||||
define('IS_CONSTANT_ARRAY', 9);
|
||||
|
@ -2256,14 +2290,5 @@ foreach (array (
|
|||
define($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
//* XC_UNDEF XC_OP_DATA
|
||||
$content = file_get_contents(__FILE__);
|
||||
for ($i = 0; $opname = xcache_get_opcode($i); $i ++) {
|
||||
if (!preg_match("/\\bXC_" . $opname . "\\b(?!')/", $content)) {
|
||||
echo "not done ", $opname, "\n";
|
||||
}
|
||||
}
|
||||
// */
|
||||
// }}}
|
||||
|
||||
|
|
|
@ -205,6 +205,50 @@ $a = $obj->b--;
|
|||
$a = --$obj->b;
|
||||
$a = $b xor $c;
|
||||
$a = !$b;
|
||||
$a = $b === $c;
|
||||
$a = $b !== $c;
|
||||
$a = $b << 2;
|
||||
$a = $b >> 3;
|
||||
$a += $b;
|
||||
$a -= $b;
|
||||
$a *= $b;
|
||||
$a /= $b;
|
||||
$a <<= $b;
|
||||
$a >>= $b;
|
||||
$a &= $b;
|
||||
$a |= $b;
|
||||
$a .= $b;
|
||||
$a %= $b;
|
||||
$a ^= $b;
|
||||
$a = 'a' . 'b';
|
||||
$a = 'a' . 'abc';
|
||||
@f1();
|
||||
print('1');
|
||||
ref(&$a);
|
||||
$a = $array['index'];
|
||||
$a = $object->prop;
|
||||
$a = $this->prop;
|
||||
$array['index'] = 1;
|
||||
$object->prop = 1;
|
||||
$this->prop = 1;
|
||||
$a = isset($b);
|
||||
$a = empty($b);
|
||||
$a = isset($array['index']);
|
||||
$a = empty($array['index']);
|
||||
$a = isset($object->prop);
|
||||
$a = empty($object->prop);
|
||||
$a = isset($this->prop);
|
||||
$a = empty($this->prop);
|
||||
$a = (int) $b;
|
||||
$a = (double) $b;
|
||||
$a = (string) $b;
|
||||
$a = (array) $b;
|
||||
$a = (object) $b;
|
||||
$a = (bool) $b;
|
||||
$a = (unset) $b;
|
||||
$a = (array) $b;
|
||||
$a = (object) $b;
|
||||
// PHP6+ $a = (scalar) $b;
|
||||
$a = $b ? $c : $d;
|
||||
$a = f1() ? f2() : f3();
|
||||
$a = $b and $c;
|
||||
|
@ -322,5 +366,6 @@ $callback = function ($quantity, $product) use ($tax, &$total) {
|
|||
$total += $pricePerItem * $quantity * ($tax + 1);
|
||||
};
|
||||
// */
|
||||
exit();
|
||||
|
||||
?>
|
||||
|
|
Loading…
Reference in New Issue