Decompiler: ?: and ? :
git-svn-id: svn://svn.lighttpd.net/xcache/trunk@799 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
This commit is contained in:
parent
79015d6a30
commit
674e498132
|
@ -149,7 +149,6 @@ class Decompiler_Binop extends Decompiler_Code // {{{
|
|||
var $op1;
|
||||
var $op2;
|
||||
var $parent;
|
||||
var $indent;
|
||||
|
||||
function Decompiler_Binop($parent, $op1, $opc, $op2)
|
||||
{
|
||||
|
@ -163,20 +162,53 @@ class Decompiler_Binop extends Decompiler_Code // {{{
|
|||
{
|
||||
$opstr = $this->parent->binops[$this->opc];
|
||||
|
||||
$op1 = foldToCode($this->op1, $indent);
|
||||
if (is_a($this->op1, 'Decompiler_Binop') && $this->op1->opc != $this->opc) {
|
||||
$op1 = "(" . str($op1, $indent) . ")";
|
||||
if (is_a($this->op1, 'Decompiler_TriOp') || is_a($this->op1, 'Decompiler_Binop') && $this->op1->opc != $this->opc) {
|
||||
$op1 = "(" . str($this->op1, $indent) . ")";
|
||||
}
|
||||
$op2 = foldToCode($this->op2, $indent);
|
||||
if (is_a($this->op2, 'Decompiler_Binop') && $this->op2->opc != $this->opc && substr($opstr, -1) != '=') {
|
||||
$op2 = "(" . str($op2, $indent) . ")";
|
||||
else {
|
||||
$op1 = $this->op1;
|
||||
}
|
||||
|
||||
if (is_a($this->op2, 'Decompiler_TriOp') || is_a($this->op2, 'Decompiler_Binop') && $this->op2->opc != $this->opc && substr($opstr, -1) != '=') {
|
||||
$op2 = "(" . str($this->op2, $indent) . ")";
|
||||
}
|
||||
else {
|
||||
$op2 = $this->op2;
|
||||
}
|
||||
|
||||
if (str($op1) == '0' && ($this->opc == XC_ADD || $this->opc == XC_SUB)) {
|
||||
return $opstr . str($op2, $indent);
|
||||
}
|
||||
|
||||
return str($op1) . ' ' . $opstr . ' ' . str($op2);
|
||||
return str($op1, $indent) . ' ' . $opstr . ' ' . str($op2, $indent);
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
class Decompiler_TriOp extends Decompiler_Code // {{{
|
||||
{
|
||||
var $condition;
|
||||
var $trueValue;
|
||||
var $falseValue;
|
||||
|
||||
function Decompiler_TriOp($condition, $trueValue, $falseValue)
|
||||
{
|
||||
$this->condition = $condition;
|
||||
$this->trueValue = $trueValue;
|
||||
$this->falseValue = $falseValue;
|
||||
}
|
||||
|
||||
function toCode($indent)
|
||||
{
|
||||
$trueValue = $this->trueValue;
|
||||
if (is_a($this->trueValue, 'Decompiler_TriOp')) {
|
||||
$trueValue = "(" . str($trueValue, $indent) . ")";
|
||||
}
|
||||
$falseValue = $this->falseValue;
|
||||
if (is_a($this->falseValue, 'Decompiler_TriOp')) {
|
||||
$falseValue = "(" . str($falseValue, $indent) . ")";
|
||||
}
|
||||
|
||||
return str($this->condition) . ' ? ' . str($trueValue) . ' : ' . str($falseValue);
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
|
@ -485,6 +517,7 @@ class Decompiler
|
|||
XC_BW_XOR => "^",
|
||||
XC_ASSIGN_BW_XOR => "^=",
|
||||
XC_BOOL_XOR => "xor",
|
||||
XC_JMP_SET => "?:",
|
||||
);
|
||||
// }}}
|
||||
$this->includeTypes = array( // {{{
|
||||
|
@ -706,6 +739,28 @@ class Decompiler
|
|||
$firstOp = &$opcodes[$first];
|
||||
$lastOp = &$opcodes[$last];
|
||||
|
||||
// {{{ ?: excludign JMP_SET
|
||||
if ($firstOp['opcode'] == XC_JMPZ && !empty($firstOp['jmpouts'])
|
||||
&& $last >= $first + 3
|
||||
&& $opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN
|
||||
&& $opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_JMP && $opcodes[$firstOp['jmpouts'][0] - 1]['jmpouts'][0] == $last + 1
|
||||
&& $lastOp['opcode'] == XC_QM_ASSIGN
|
||||
) {
|
||||
$trueFirst = $first + 1;
|
||||
$trueLast = $firstOp['jmpouts'][0] - 2;
|
||||
$falseFirst = $firstOp['jmpouts'][0];
|
||||
$falseLast = $last;
|
||||
$this->removeJmpInfo($EX, $first);
|
||||
|
||||
$condition = $this->getOpVal($firstOp['op1'], $EX);
|
||||
$this->recognizeAndDecompileClosedBlocks($EX, $trueFirst, $trueLast, $indent . INDENT);
|
||||
$trueValue = $this->getOpVal($opcodes[$trueLast]['op1'], $EX, false, true);
|
||||
$this->recognizeAndDecompileClosedBlocks($EX, $falseFirst, $falseLast, $indent . INDENT);
|
||||
$falseValue = $this->getOpVal($opcodes[$falseLast]['op1'], $EX, false, true);
|
||||
$T[$opcodes[$trueLast]['result']['var']] = new Decompiler_TriOp($condition, $trueValue, $falseValue);
|
||||
return false;
|
||||
}
|
||||
// }}}
|
||||
// {{{ try/catch
|
||||
if (!empty($firstOp['jmpins']) && !empty($opcodes[$firstOp['jmpins'][0]]['isCatchBegin'])) {
|
||||
$catchBlocks = array();
|
||||
|
@ -973,7 +1028,12 @@ class Decompiler
|
|||
if ($blockFirst > $starti) {
|
||||
$this->decompileBasicBlock($EX, $starti, $blockFirst - 1, $indent);
|
||||
}
|
||||
$this->decompileComplexBlock($EX, $blockFirst, $blockLast, $indent);
|
||||
if ($this->decompileComplexBlock($EX, $blockFirst, $blockLast, $indent) === false) {
|
||||
if ($EX['lastBlock'] == 'complex') {
|
||||
echo PHP_EOL;
|
||||
}
|
||||
$EX['lastBlock'] = null;
|
||||
}
|
||||
$starti = $blockLast + 1;
|
||||
$i = $starti;
|
||||
}
|
||||
|
@ -1029,7 +1089,7 @@ class Decompiler
|
|||
case XC_JMPNZ:
|
||||
case XC_JMPZ_EX:
|
||||
case XC_JMPNZ_EX:
|
||||
case XC_JMP_SET:
|
||||
// case XC_JMP_SET:
|
||||
// case XC_FE_RESET:
|
||||
case XC_FE_FETCH:
|
||||
// case XC_JMP_NO_CTOR:
|
||||
|
@ -1110,6 +1170,7 @@ class Decompiler
|
|||
$EX['silence'] = 0;
|
||||
$EX['recvs'] = array();
|
||||
$EX['uses'] = array();
|
||||
$EX['lastBlock'] = null;
|
||||
|
||||
$first = 0;
|
||||
$last = count($opcodes) - 1;
|
||||
|
@ -1273,6 +1334,10 @@ class Decompiler
|
|||
// echo $i, ' '; $this->dumpop($op, $EX); //var_dump($op);
|
||||
|
||||
$resvar = null;
|
||||
unset($curResVar);
|
||||
if (array_key_exists($res['var'], $T)) {
|
||||
$curResVar = &$T[$res['var']];
|
||||
}
|
||||
if ((ZEND_ENGINE_2_4 ? ($res['op_type'] & EXT_TYPE_UNUSED) : ($res['EA.type'] & EXT_TYPE_UNUSED)) || $res['op_type'] == XC_IS_UNUSED) {
|
||||
$istmpres = false;
|
||||
}
|
||||
|
@ -1816,10 +1881,10 @@ class Decompiler
|
|||
if ($opc == XC_ADD_ARRAY_ELEMENT) {
|
||||
$assoc = $this->getOpVal($op2, $EX);
|
||||
if (isset($assoc)) {
|
||||
$T[$res['var']]->value[] = array($assoc, $rvalue);
|
||||
$curResVar->value[] = array($assoc, $rvalue);
|
||||
}
|
||||
else {
|
||||
$T[$res['var']]->value[] = array(null, $rvalue);
|
||||
$curResVar->value[] = array(null, $rvalue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1841,7 +1906,12 @@ class Decompiler
|
|||
break;
|
||||
// }}}
|
||||
case XC_QM_ASSIGN: // {{{
|
||||
$resvar = $this->getOpVal($op1, $EX);
|
||||
if (isset($curResVar) && is_a($curResVar, 'Decompiler_Binop')) {
|
||||
$curResVar->op2 = $this->getOpVal($op1, $EX);
|
||||
}
|
||||
else {
|
||||
$resvar = $this->getOpVal($op1, $EX);
|
||||
}
|
||||
break;
|
||||
// }}}
|
||||
case XC_BOOL: // {{{
|
||||
|
@ -1893,9 +1963,7 @@ class Decompiler
|
|||
case XC_JMP_NO_CTOR:
|
||||
break;
|
||||
case XC_JMP_SET: // ?:
|
||||
$resvar = $this->getOpVal($op1, $EX);
|
||||
$op['cond'] = $resvar;
|
||||
$op['isjmp'] = true;
|
||||
$resvar = new Decompiler_Binop($this, $this->getOpVal($op1, $EX), XC_JMP_SET, null);
|
||||
break;
|
||||
case XC_JMPNZ: // while
|
||||
case XC_JMPZNZ: // for
|
||||
|
|
|
@ -404,10 +404,12 @@ echo $a::CONST_VALUE;
|
|||
echo CONST_VALUE;
|
||||
$this::__construct();
|
||||
$obj::__construct();
|
||||
|
||||
$a = $b ?: $d;
|
||||
$a = ($b ?: $d) + $c;
|
||||
$a = f1() ?: f2();
|
||||
$a = $b ? $c : $d;
|
||||
$a = ($b ? $c : $d) + $c;
|
||||
$a = f1() ? f3() : f2();
|
||||
|
||||
if ($b ?: $d) {
|
||||
echo 'if ($b ?: $d)';
|
||||
|
|
Loading…
Reference in New Issue