Changeset 766 in svn for branches/1.3


Ignore:
Timestamp:
2011-04-18T06:29:25+02:00 (4 years ago)
Author:
Xuefer
Message:

merge changes from trunk

Location:
branches/1.3
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • branches/1.3

  • branches/1.3/ChangeLog

    r726 r766  
    111.3.2 2011-??-??
    22========
     3 * adds 30 seconds timeout to "compiling" flag
     4 * decompiler: improves decompiling
    35 * disassembler: DECLARE_INHERITED_CLASS/DELAYED class not found
    46 * disassembler: don't dump builtin functions
  • branches/1.3/Decompiler.class.php

    r739 r766  
    1111function str($code, $indent = '') // {{{
    1212{
     13    if (is_array($code)) {
     14        $array = array();
     15        foreach ($code as $key => $value) {
     16            $array[$key] = str($value, $indent);
     17        }
     18        return $array;
     19    }
    1320    if (is_object($code)) {
    14         if (get_class($code) != 'Decompiler_Code') {
    15             $code = toCode($code, $indent);
    16         }
    17         return $code->__toString();
     21        $code = foldToCode($code, $indent);
     22        return $code->toCode($indent);
    1823    }
    1924
     
    2126}
    2227// }}}
    23 function toCode($src, $indent = '') // {{{
     28function foldToCode($src, $indent = '') // {{{ wrap or rewrap anything to Decompiler_Code
    2429{
    2530    if (is_array($indent)) {
     
    2732    }
    2833
    29     if (is_object($src)) {
    30         if (!method_exists($src, 'toCode')) {
    31             var_dump($src);
    32             exit('no toCode');
    33         }
    34         return new Decompiler_Code($src->toCode($indent));
    35     }
    36 
    37     return new Decompiler_Code($src);
     34    if (!is_object($src)) {
     35        return new Decompiler_Code($src);
     36    }
     37
     38    if (!method_exists($src, 'toCode')) {
     39        var_dump($src);
     40        exit('no toCode');
     41    }
     42    if (get_class($src) != 'Decompiler_Code') {
     43        // rewrap it
     44        $src = new Decompiler_Code($src->toCode($indent));
     45    }
     46
     47    return $src;
    3848}
    3949// }}}
     
    6171}
    6272// }}}
     73function unquoteName_($str, $asVariableName, $indent = '') // {{{
     74{
     75    $str = str($str, $indent);
     76    if (preg_match("!^'[\\w_][\\w\\d_\\\\]*'\$!", $str)) {
     77        return str_replace('\\\\', '\\', substr($str, 1, -1));
     78    }
     79    else if ($asVariableName) {
     80        return "{" . $str . "}";
     81    }
     82    else {
     83        return $str;
     84    }
     85}
     86// }}}
     87function unquoteVariableName($str, $indent = '') // {{{
     88{
     89    return unquoteName_($str, true, $indent);
     90}
     91// }}}
     92function unquoteName($str, $indent = '') // {{{
     93{
     94    return unquoteName_($str, false, $indent);
     95}
     96// }}}
    6397class Decompiler_Object // {{{
    6498{
     
    76110    function toCode($indent)
    77111    {
    78         return var_export($this->value, true);
     112        $code = var_export($this->value, true);
     113        if (gettype($this->value) == 'string') {
     114            switch ($this->value) {
     115            case "\r":
     116                return '"\\r"';
     117            case "\n":
     118                return '"\\n"';
     119            case "\r\n":
     120                return '"\\r\\n"';
     121            }
     122            $code = str_replace("\r\n", '\' . "\\r\\n" . \'', $code);
     123            $code = str_replace("\r", '\' . "\\r" . \'', $code);
     124            $code = str_replace("\n", '\' . "\\n" . \'', $code);
     125        }
     126        return $code;
    79127    }
    80128}
     
    86134    function Decompiler_Code($src)
    87135    {
     136        assert('isset($src)');
    88137        $this->src = $src;
    89138    }
    90139
    91140    function toCode($indent)
    92     {
    93         return $this;
    94     }
    95 
    96     function __toString()
    97141    {
    98142        return $this->src;
     
    118162    function toCode($indent)
    119163    {
    120         $op1 = toCode($this->op1, $indent);
     164        $opstr = $this->parent->binops[$this->opc];
     165
     166        $op1 = foldToCode($this->op1, $indent);
    121167        if (is_a($this->op1, 'Decompiler_Binop') && $this->op1->opc != $this->opc) {
    122             $op1 = "($op1)";
    123         }
    124         $opstr = $this->parent->binops[$this->opc];
    125         if ($op1 == '0' && $this->opc == XC_SUB) {
    126             return $opstr . toCode($this->op2, $indent);
    127         }
    128         return $op1 . ' ' . $opstr . ' ' . toCode($this->op2, $indent);
     168            $op1 = "(" . str($op1, $indent) . ")";
     169        }
     170        $op2 = foldToCode($this->op2, $indent);
     171        if (is_a($this->op2, 'Decompiler_Binop') && $this->op2->opc != $this->opc && substr($opstr, -1) != '=') {
     172            $op2 = "(" . str($op2, $indent) . ")";
     173        }
     174
     175        if (str($op1) == '0' && ($this->opc == XC_ADD || $this->opc == XC_SUB)) {
     176            return $opstr . str($op2, $indent);
     177        }
     178
     179        return str($op1) . ' ' . $opstr . ' ' . str($op2);
    129180    }
    130181}
     
    148199            return '$' . substr($this->src, 1, -1);
    149200        case ZEND_FETCH_STATIC:
     201            if (ZEND_ENGINE_2_3) {
     202                // closure local variable?
     203                return str($this->src);
     204            }
    150205            die('static fetch cant to string');
    151206        case ZEND_FETCH_GLOBAL:
     
    178233    var $offsets = array();
    179234    var $isLast = false;
     235    var $isObject = false;
    180236    var $assign = null;
    181237
     
    183239    {
    184240        if (is_a($this->value, 'Decompiler_ListBox')) {
    185             $exp = toCode($this->value->obj->src, $indent);
     241            $exp = str($this->value->obj->src, $indent);
    186242        }
    187243        else {
    188             $exp = toCode($this->value, $indent);
    189         }
    190         foreach ($this->offsets as $dim) {
    191             $exp .= '[' . toCode($dim, $indent) . ']';
     244            $exp = str($this->value, $indent);
     245        }
     246        $last = count($this->offsets) - 1;
     247        foreach ($this->offsets as $i => $dim) {
     248            if ($this->isObject && $i == $last) {
     249                $exp .= '->' . unquoteVariableName($dim, $indent);
     250            }
     251            else {
     252                $exp .= '[' . str($dim, $indent) . ']';
     253            }
    192254        }
    193255        return $exp;
     
    212274            $dim->value = $this->src;
    213275            if (!isset($dim->assign)) {
    214                 return toCode($dim, $indent);
    215             }
    216             return toCode($this->dims[0]->assign, $indent) . ' = ' . toCode($dim, $indent);
     276                return str($dim, $indent);
     277            }
     278            return str($this->dims[0]->assign, $indent) . ' = ' . str($dim, $indent);
    217279        }
    218280        /* flatten dims */
     
    223285                $assign = &$assign[$offset];
    224286            }
    225             $assign = toCode($dim->assign, $indent);
    226         }
    227         return $this->toList($assigns) . ' = ' . toCode($this->src, $indent);
     287            $assign = foldToCode($dim->assign, $indent);
     288        }
     289        return str($this->toList($assigns)) . ' = ' . str($this->src, $indent);
    228290    }
    229291
     
    370432class Decompiler
    371433{
    372     var $rName = '!^[\\w_][\\w\\d_]*$!';
    373     var $rQuotedName = "!^'[\\w_][\\w\\d_]*'\$!";
     434    var $namespace;
     435    var $namespaceDecided;
    374436
    375437    function Decompiler()
    376438    {
     439        // {{{ testing
     440        // XC_UNDEF XC_OP_DATA
     441        $this->test = !empty($_ENV['XCACHE_DECOMPILER_TEST']);
     442        $this->usedOps = array();
     443
     444        if ($this->test) {
     445            $content = file_get_contents(__FILE__);
     446            for ($i = 0; $opname = xcache_get_opcode($i); $i ++) {
     447                if (!preg_match("/\\bXC_" . $opname . "\\b(?!')/", $content)) {
     448                    echo "not recognized opcode ", $opname, "\n";
     449                }
     450            }
     451        }
     452        // }}}
    377453        // {{{ opinfo
    378454        $this->unaryops = array(
     
    421497                // }}}
    422498    }
     499    function detectNamespace($name) // {{{
     500    {
     501        if ($this->namespaceDecided) {
     502            return;
     503        }
     504
     505        if (strpos($name, '\\') !== false) {
     506            $this->namespace = strtok($name, '\\');
     507            echo 'namespace ', $this->namespace, ";\n\n";
     508        }
     509
     510        $this->namespaceDecided = true;
     511    }
     512    // }}}
     513    function stripNamespace($name) // {{{
     514    {
     515        $len = strlen($this->namespace) + 1;
     516        if (substr($name, 0, $len) == $this->namespace . '\\') {
     517            return substr($name, $len);
     518        }
     519        else {
     520            return $name;
     521        }
     522    }
     523    // }}}
    423524    function outputPhp(&$opcodes, $opline, $last, $indent) // {{{
    424525    {
     
    428529            $op = $opcodes[$i];
    429530            if (isset($op['php'])) {
    430                 $toticks = isset($op['ticks']) ? $op['ticks'] : 0;
     531                $toticks = isset($op['ticks']) ? (int) str($op['ticks']) : 0;
    431532                if ($curticks != $toticks) {
    432                     if (!$toticks) {
    433                         echo $origindent, "}\n";
     533                    $oldticks = $curticks;
     534                    $curticks = $toticks;
     535                    if (!$curticks) {
     536                        echo $origindent, "}\n\n";
    434537                        $indent = $origindent;
    435538                    }
    436539                    else {
    437                         if ($curticks) {
    438                             echo $origindent, "}\n";
    439                         }
    440                         else if (!$curticks) {
     540                        if ($oldticks) {
     541                            echo $origindent, "}\n\n";
     542                        }
     543                        else if (!$oldticks) {
    441544                            $indent .= INDENT;
    442545                        }
    443                         echo $origindent, "declare(ticks=$curticks) {\n";
    444                     }
    445                     $curticks = $toticks;
    446                 }
    447                 echo $indent, toCode($op['php'], $indent), ";\n";
     546                        echo $origindent, "declare (ticks=$curticks) {\n";
     547                    }
     548                }
     549                echo $indent, str($op['php'], $indent), ";\n";
    448550            }
    449551        }
     
    457559        switch ($op['op_type']) {
    458560        case XC_IS_CONST:
    459             return toCode(value($op['constant']), $EX);
     561            return foldToCode(value($op['constant']), $EX);
    460562
    461563        case XC_IS_VAR:
     
    464566            $ret = $T[$op['var']];
    465567            if ($tostr) {
    466                 $ret = toCode($ret, $EX);
     568                $ret = foldToCode($ret, $EX);
    467569            }
    468570            if ($free) {
     
    531633            $last = count($opcodes) - 1;
    532634            if ($opcodes[$last]['opcode'] == XC_HANDLE_EXCEPTION) {
    533                 unset($opcodes[$last]);
     635                $this->usedOps[XC_HANDLE_EXCEPTION] = true;
     636                $opcodes[$last]['opcode'] = XC_NOP;
    534637                --$last;
    535638            }
     
    537640                $op1 = $opcodes[$last]['op1'];
    538641                if ($op1['op_type'] == XC_IS_CONST && array_key_exists('constant', $op1) && $op1['constant'] === $defaultReturnValue) {
    539                     unset($opcodes[$last]);
     642                    $opcodes[$last]['opcode'] = XC_NOP;
    540643                    --$last;
    541644                }
     
    562665            $op['line'] = $i;
    563666            switch ($op['opcode']) {
     667            case XC_CONT:
     668            case XC_BRK:
     669                $op['jmpouts'] = array();
     670                break;
     671
     672            case XC_GOTO:
    564673            case XC_JMP:
    565674                $target = $op['op1']['var'];
     
    580689            case XC_JMPZ_EX:
    581690            case XC_JMPNZ_EX:
     691            case XC_JMP_SET:
    582692            // case XC_FE_RESET:
    583693            case XC_FE_FETCH:
     
    678788            $body = ob_get_clean();
    679789
    680             $as = toCode($op['fe_as'], $EX);
     790            $as = foldToCode($op['fe_as'], $EX);
    681791            if (isset($op['fe_key'])) {
    682                 $as = toCode($op['fe_key'], $EX) . ' => ' . $as;
    683             }
    684             echo "{$indent}foreach (" . toCode($op['fe_src'], $EX) . " as $as) {\n";
     792                $as = str($op['fe_key'], $EX) . ' => ' . str($as);
     793            }
     794            echo "{$indent}foreach (" . str($op['fe_src'], $EX) . " as $as) {\n";
    685795            echo $body;
    686796            echo "{$indent}}";
     
    711821            return;
    712822        }
    713         if (!empty($op['jmpouts']) && isset($op['isjmp'])) {
     823        if (isset($op['jmpouts']) && isset($op['isjmp'])) {
    714824            if (isset($op['cond'])) {
    715                 echo "{$indent}check ($op[cond]) {\n";
     825                echo "{$indent}check (" . str($op["cond"]) . ") {\n";
    716826                echo INDENT;
    717827            }
    718             echo $indent;
    719             echo xcache_get_opcode($op['opcode']), ' line', $op['jmpouts'][0];
    720             if (isset($op['jmpouts'][1])) {
    721                 echo ', line', $op['jmpouts'][1];
    722             }
    723             echo ";";
    724             // echo ' // <- line', $op['line'];
    725             echo "\n";
     828            switch ($op['opcode']) {
     829            case XC_CONT:
     830            case XC_BRK:
     831                break;
     832
     833            case XC_GOTO:
     834                echo $indent, 'goto', ' line', $op['jmpouts'][0], ';', "\n";
     835                break;
     836
     837            default:
     838                echo $indent;
     839                echo xcache_get_opcode($op['opcode']), ' line', $op['jmpouts'][0];
     840                if (isset($op['jmpouts'][1])) {
     841                    echo ', line', $op['jmpouts'][1];
     842                }
     843                echo ";";
     844                // echo ' // <- line', $op['line'];
     845                echo "\n";
     846            }
    726847            if (isset($op['cond'])) echo "$indent}\n";
    727848        }
     
    751872            // $this->dumpop($op, $EX);
    752873            // any true comes here, so it's a "or"
    753             $cond = implode(' and ', $op['cond_false']);
     874            $cond = implode(' and ', str($op['cond_false']));
    754875            // var_dump($op['cond'] = $cond);
    755876            /*
     
    765886    }
    766887    // }}}
    767     function unquoteName($str) // {{{
    768     {
    769         if (preg_match($this->rQuotedName, $str)) {
    770             $str = substr($str, 1, -1);
    771         }
    772         return $str;
    773     }
    774     // }}}
    775888    function dasmBasicBlock(&$EX, $opline, $last) // {{{
    776889    {
     
    784897            $opc = $op['opcode'];
    785898            if ($opc == XC_NOP) {
     899                $this->usedOps[$opc] = true;
    786900                continue;
    787901            }
     
    799913                continue;
    800914            }
    801             // $this->dumpop($op, $EX); //var_dump($op);
     915            // echo $i, ' '; $this->dumpop($op, $EX); //var_dump($op);
    802916
    803917            $resvar = null;
     
    813927            $call = array(&$this, $opname);
    814928            if (is_callable($call)) {
     929                $this->usedOps[$opc] = true;
    815930                $this->{$opname}($op, $EX);
    816931            }
    817932            else if (isset($this->binops[$opc])) { // {{{
     933                $this->usedOps[$opc] = true;
    818934                $op1val = $this->getOpVal($op1, $EX, false);
    819935                $op2val = $this->getOpVal($op2, $EX, false);
     
    823939            }
    824940            else if (isset($this->unaryops[$opc])) { // {{{
     941                $this->usedOps[$opc] = true;
    825942                $op1val = $this->getOpVal($op1, $EX);
    826943                $myop = $this->unaryops[$opc];
    827                 $rvalue = "$myop$op1val";
     944                $rvalue = $myop . str($op1val);
    828945                $resvar = $rvalue;
    829946                // }}}
    830947            }
    831948            else {
     949                $covered = true;
    832950                switch ($opc) {
    833951                case XC_NEW: // {{{
     
    835953                    $EX['object'] = (int) $res['var'];
    836954                    $EX['called_scope'] = null;
    837                     $EX['fbc'] = 'new ' . $this->unquoteName($this->getOpVal($op1, $EX));
     955                    $EX['fbc'] = 'new ' . unquoteName($this->getOpVal($op1, $EX), $EX);
    838956                    if (!ZEND_ENGINE_2) {
    839957                        $resvar = '$new object$';
    840958                    }
     959                    break;
     960                    // }}}
     961                case XC_THROW: // {{{
     962                    $resvar = 'throw ' . str($this->getOpVal($op1, $EX));
     963                    break;
     964                    // }}}
     965                case XC_CLONE: // {{{
     966                    $resvar = 'clone ' . str($this->getOpVal($op1, $EX));
     967                    break;
     968                    // }}}
     969                case XC_CATCH: // {{{
     970                    $resvar = 'catch (' . str($this->getOpVal($op1, $EX)) . ' ' . str($this->getOpVal($op2, $EX)) . ')';
     971                    break;
     972                    // }}}
     973                case XC_INSTANCEOF: // {{{
     974                    $resvar = str($this->getOpVal($op1, $EX)) . ' instanceof ' . str($this->getOpVal($op2, $EX));
    841975                    break;
    842976                    // }}}
     
    857991                    }
    858992                    else {
    859                         $class = $op2['constant'];
    860                         if (is_object($class)) {
    861                             $class = get_class($class);
     993                        $class = $this->getOpVal($op2, $EX);
     994                        if (isset($op2['constant'])) {
     995                            $class = $this->stripNamespace(unquoteName($class));
    862996                        }
    863997                    }
     
    8661000                    // }}}
    8671001                case XC_FETCH_CONSTANT: // {{{
     1002                    if ($op1['op_type'] == XC_IS_UNUSED) {
     1003                        $resvar = $this->stripNamespace($op2['constant']);
     1004                        break;
     1005                    }
     1006
    8681007                    if ($op1['op_type'] == XC_IS_CONST) {
    869                         $resvar = $op1['constant'];
    870                     }
    871                     else if ($op1['op_type'] == XC_IS_UNUSED) {
    872                         $resvar = $op2['constant'];
     1008                        $resvar = $this->stripNamespace($op1['constant']);
    8731009                    }
    8741010                    else {
    875                         $class = $T[$op1['var']];
    876                         assert($class[0] == 'class');
    877                         $resvar = $class[1] . '::' . $op2['constant'];
    878                     }
     1011                        $resvar = $this->getOpVal($op1, $EX);
     1012                    }
     1013
     1014                    $resvar = str($resvar) . '::' . unquoteName($this->getOpVal($op2, $EX));
    8791015                    break;
    8801016                    // }}}
     
    8971033                    case ZEND_FETCH_STATIC_MEMBER:
    8981034                        $class = $this->getOpVal($op2, $EX);
    899                         $rvalue = $class . '::$' . $this->unquoteName($rvalue);
     1035                        $rvalue = str($class) . '::$' . unquoteName($rvalue, $EX);
    9001036                        break;
    9011037                    default:
    902                         $name = $this->unquoteName($rvalue);
    903                         $globalname = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[$rvalue]";
     1038                        $name = unquoteName($rvalue, $EX);
     1039                        $globalname = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[" . str($rvalue) . "]";
    9041040                        $rvalue = new Decompiler_Fetch($rvalue, $fetchtype, $globalname);
    9051041                        break;
    9061042                    }
    9071043                    if ($opc == XC_UNSET_VAR) {
    908                         $op['php'] = "unset(" . toCode($rvalue, $EX) . ")";
     1044                        $op['php'] = "unset(" . str($rvalue, $EX) . ")";
    9091045                        $lastphpop = &$op;
    9101046                    }
     
    9231059                case XC_FETCH_DIM_IS:
    9241060                case XC_ASSIGN_DIM:
     1061                case XC_UNSET_DIM_OBJ: // PHP 4 only
    9251062                case XC_UNSET_DIM:
    926                 case XC_UNSET_DIM_OBJ:
     1063                case XC_UNSET_OBJ:
    9271064                    $src = $this->getOpVal($op1, $EX, false);
    9281065                    if (is_a($src, "Decompiler_ForeachBox")) {
     
    9311068                        break;
    9321069                    }
    933                     else if (is_a($src, "Decompiler_DimBox")) {
     1070
     1071                    if (is_a($src, "Decompiler_DimBox")) {
    9341072                        $dimbox = $src;
    9351073                    }
    9361074                    else {
    9371075                        if (!is_a($src, "Decompiler_ListBox")) {
    938                             $list = new Decompiler_List($this->getOpVal($op1, $EX, false));
     1076                            $op1val = $this->getOpVal($op1, $EX, false);
     1077                            $list = new Decompiler_List(isset($op1val) ? $op1val : '$this');
    9391078
    9401079                            $src = new Decompiler_ListBox($list);
     
    9601099                        $dim->isLast = true;
    9611100                    }
     1101                    if ($opc == XC_UNSET_OBJ) {
     1102                        $dim->isObject = true;
     1103                    }
    9621104                    unset($dim);
    9631105                    $rvalue = $dimbox;
     1106                    unset($dimbox);
    9641107
    9651108                    if ($opc == XC_ASSIGN_DIM) {
     
    9671110                        ++ $i;
    9681111                        $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX);
    969                         $resvar = toCode($lvalue, $EX) . ' = ' . $rvalue;
    970                     }
    971                     else if ($opc == XC_UNSET_DIM) {
    972                         $op['php'] = "unset(" . toCode($rvalue, $EX) . ")";
     1112                        $resvar = str($lvalue, $EX) . ' = ' . str($rvalue);
     1113                    }
     1114                    else if ($opc == XC_UNSET_DIM || $opc == XC_UNSET_OBJ) {
     1115                        $op['php'] = "unset(" . str($rvalue, $EX) . ")";
    9731116                        $lastphpop = &$op;
    9741117                    }
     
    9911134                        $dim->assign = $lvalue;
    9921135                        if ($dim->isLast) {
    993                             $resvar = toCode($dim->value, $EX);
     1136                            $resvar = foldToCode($dim->value, $EX);
    9941137                        }
    9951138                        unset($dim);
    9961139                        break;
    9971140                    }
    998                     $resvar = "$lvalue = " . toCode($rvalue, $EX);
     1141                    $resvar = "$lvalue = " . str($rvalue, $EX);
    9991142                    break;
    10001143                    // }}}
     
    10031146                    $rvalue = $this->getOpVal($op2, $EX, false);
    10041147                    if (is_a($rvalue, 'Decompiler_Fetch')) {
    1005                         $src = toCode($rvalue->src, $EX);
    1006                         if (substr($src, 1, -1) == substr($lvalue, 1)) {
     1148                        $src = str($rvalue->src, $EX);
     1149                        if ('$' . unquoteName($src) == $lvalue) {
    10071150                            switch ($rvalue->fetchType) {
    10081151                            case ZEND_FETCH_GLOBAL:
     
    10131156                                $statics = &$EX['op_array']['static_variables'];
    10141157                                $resvar = 'static ' . $lvalue;
    1015                                 $name = substr($src, 1, -1);
     1158                                $name = unquoteName($src);
    10161159                                if (isset($statics[$name])) {
    10171160                                    $var = $statics[$name];
    10181161                                    $resvar .= ' = ';
    1019                                     $resvar .= toCode(value($var), $EX);
     1162                                    $resvar .= str(value($var), $EX);
    10201163                                }
    10211164                                unset($statics);
     
    10261169                    }
    10271170                    // TODO: PHP_6 global
    1028                     $rvalue = toCode($rvalue, $EX);
     1171                    $rvalue = str($rvalue, $EX);
    10291172                    $resvar = "$lvalue = &$rvalue";
    10301173                    break;
     
    10421185                        $obj = '$this';
    10431186                    }
    1044                     $prop = $this->getOpVal($op2, $EX);
    1045                     if (preg_match($this->rQuotedName, $prop)) {
    1046                         $prop = substr($prop, 1, -1);;
    1047                         $rvalue = "{$obj}->$prop";
    1048                     }
    1049                     else {
    1050                         $rvalue = "{$obj}->{" . "$prop}";
    1051                     }
     1187                    $rvalue = str($obj) . "->" . unquoteVariableName($this->getOpVal($op2, $EX), $EX);
    10521188                    if ($res['op_type'] != XC_IS_UNUSED) {
    10531189                        $resvar = $rvalue;
     
    10571193                        $lvalue = $rvalue;
    10581194                        $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX);
    1059                         $resvar = "$lvalue = $rvalue";
     1195                        $resvar = "$lvalue = " . str($rvalue);
    10601196                    }
    10611197                    break;
     
    10661202                case XC_ISSET_ISEMPTY_VAR: // {{{
    10671203                    if ($opc == XC_ISSET_ISEMPTY_VAR) {
    1068                         $rvalue = $this->getOpVal($op1, $EX);;
    1069                         if (preg_match($this->rQuotedName, $rvalue)) {
    1070                             $rvalue = '$' . substr($rvalue, 1, -1);
    1071                         }
    1072                         else {
    1073                             $rvalue = '${' . $rvalue . '}';
    1074                         }
     1204                        $rvalue = $this->getOpVal($op1, $EX);
    10751205                        if ($op2['EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
    10761206                            $class = $this->getOpVal($op2, $EX);
     
    10851215                        $dim = $this->getOpVal($op2, $EX);
    10861216                        if ($opc == XC_ISSET_ISEMPTY_PROP_OBJ) {
    1087                             if (preg_match($this->rQuotedName, $dim)) {
    1088                                 $rvalue = $container . "->" . substr($dim, 1, -1);
     1217                            if (!isset($container)) {
     1218                                $container = '$this';
    10891219                            }
    1090                             else {
    1091                                 $rvalue = $container . "->{" . $dim . "}";
    1092                             }
     1220                            $rvalue = $container . "->" . unquoteVariableName($dim);
    10931221                        }
    10941222                        else {
    1095                             $rvalue = $container . "[$dim]";
     1223                            $rvalue = $container . '[' . str($dim) .']';
    10961224                        }
    10971225                    }
     
    11131241                case XC_SEND_VAR: // {{{
    11141242                    $ref = ($opc == XC_SEND_REF ? '&' : '');
    1115                     $EX['argstack'][] = $ref . $this->getOpVal($op1, $EX);
     1243                    $EX['argstack'][] = $ref . str($this->getOpVal($op1, $EX));
    11161244                    break;
    11171245                    // }}}
    11181246                case XC_INIT_STATIC_METHOD_CALL:
    1119                 case XC_INIT_METHOD_CALL:
    1120                 case XC_INIT_FCALL_BY_FUNC:
    1121                 case XC_INIT_FCALL_BY_NAME: // {{{
    1122                     if (($ext & ZEND_CTOR_CALL)) {
    1123                         break;
    1124                     }
     1247                case XC_INIT_METHOD_CALL: // {{{
    11251248                    array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
    11261249                    if ($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL || $op1['op_type'] != XC_IS_UNUSED) {
     
    11311254                        if ($opc == XC_INIT_STATIC_METHOD_CALL || /* PHP4 */ isset($op1['constant'])) {
    11321255                            $EX['object'] = null;
    1133                             $EX['called_scope'] = $this->unquoteName($obj);
     1256                            $EX['called_scope'] = $this->stripNamespace(unquoteName($obj, $EX));
    11341257                        }
    11351258                        else {
     
    11461269                    }
    11471270
    1148                     if ($opc == XC_INIT_FCALL_BY_FUNC) {
    1149                         $which = $op1['var'];
    1150                         $EX['fbc'] = $EX['op_array']['funcs'][$which]['name'];
    1151                     }
    1152                     else {
    1153                         $EX['fbc'] = $this->getOpVal($op2, $EX, false);
    1154                     }
     1271                    $EX['fbc'] = $this->getOpVal($op2, $EX, false);
     1272                    if (($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL) && !isset($EX['fbc'])) {
     1273                        $EX['fbc'] = '__construct';
     1274                    }
     1275                    break;
     1276                    // }}}
     1277                case XC_INIT_NS_FCALL_BY_NAME:
     1278                case XC_INIT_FCALL_BY_NAME: // {{{
     1279                    array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
     1280                    if (!ZEND_ENGINE_2 && ($ext & ZEND_CTOR_CALL)) {
     1281                        break;
     1282                    }
     1283                    $EX['object'] = null;
     1284                    $EX['called_scope'] = null;
     1285                    $EX['fbc'] = $this->getOpVal($op2, $EX);
     1286                    break;
     1287                    // }}}
     1288                case XC_INIT_FCALL_BY_FUNC: // {{{ deprecated even in PHP 4?
     1289                    $EX['object'] = null;
     1290                    $EX['called_scope'] = null;
     1291                    $which = $op1['var'];
     1292                    $EX['fbc'] = $EX['op_array']['funcs'][$which]['name'];
    11551293                    break;
    11561294                    // }}}
     
    11621300                    break;
    11631301                case XC_DO_FCALL:
    1164                     $fname = $this->unquoteName($this->getOpVal($op1, $EX, false));
     1302                    $fname = unquoteName($this->getOpVal($op1, $EX, false), $EX);
    11651303                    $args = $this->popargs($EX, $ext);
    11661304                    $resvar = $fname . "($args)";
     
    11691307                    $object = null;
    11701308
    1171                     $fname = $this->unquoteName($EX['fbc']);
     1309                    $fname = unquoteName($EX['fbc'], $EX);
    11721310                    if (!is_int($EX['object'])) {
    11731311                        $object = $EX['object'];
     
    11761314                    $args = $this->popargs($EX, $ext);
    11771315
    1178                     $resvar =
    1179                         (isset($object) ? $object . '->' : '' )
    1180                         . (isset($EX['called_scope']) ? $EX['called_scope'] . '::' : '' )
    1181                         . $fname . "($args)";
     1316                    $prefix = (isset($object) ? $object . '->' : '' )
     1317                        . (isset($EX['called_scope']) ? $EX['called_scope'] . '::' : '' );
     1318                    $resvar = $prefix
     1319                        . (!$prefix ? $this->stripNamespace($fname) : $fname)
     1320                        . "($args)";
    11821321                    unset($args);
    11831322
     
    12031342                    }
    12041343                    $class = &$this->dc['class_table'][$key];
    1205                     $class['name'] = $this->unquoteName($this->getOpVal($op2, $EX));
     1344                    if (!isset($class['name'])) {
     1345                        $class['name'] = unquoteName($this->getOpVal($op2, $EX), $EX);
     1346                    }
    12061347                    if ($opc == XC_DECLARE_INHERITED_CLASS || $opc == XC_DECLARE_INHERITED_CLASS_DELAYED) {
    12071348                        $ext /= XC_SIZEOF_TEMP_VARIABLE;
     
    12131354                    }
    12141355
    1215                     while ($i + 2 < $ic
    1216                      && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE
    1217                      && $opcodes[$i + 2]['op1']['var'] == $res['var']
    1218                      && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) {
     1356                    for (;;) {
     1357                        if ($i + 1 < $ic
     1358                         && $opcodes[$i + 1]['opcode'] == XC_ADD_INTERFACE
     1359                         && $opcodes[$i + 1]['op1']['var'] == $res['var']) {
     1360                            // continue
     1361                        }
     1362                        else if ($i + 2 < $ic
     1363                         && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE
     1364                         && $opcodes[$i + 2]['op1']['var'] == $res['var']
     1365                         && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) {
     1366                            // continue
     1367                        }
     1368                        else {
     1369                            break;
     1370                        }
     1371                        $this->usedOps[XC_ADD_INTERFACE] = true;
     1372
    12191373                        $fetchop = &$opcodes[$i + 1];
    1220                         $impl = $this->unquoteName($this->getOpVal($fetchop['op2'], $EX));
     1374                        $interface = $this->stripNamespace(unquoteName($this->getOpVal($fetchop['op2'], $EX), $EX));
    12211375                        $addop = &$opcodes[$i + 2];
    1222                         $class['interfaces'][$addop['extended_value']] = $impl;
     1376                        $class['interfaces'][$addop['extended_value']] = $interface;
    12231377                        unset($fetchop, $addop);
    12241378                        $i += 2;
    12251379                    }
    12261380                    $this->dclass($class);
     1381                    echo "\n";
    12271382                    unset($class);
    12281383                    break;
     
    12391394                    switch ($opc) {
    12401395                    case XC_ADD_CHAR:
    1241                         $op2val = toCode(chr($op2val), $EX);
     1396                        $op2val = value(chr(str($op2val)));
    12421397                        break;
    12431398                    case XC_ADD_STRING:
    1244                         $op2val = toCode($op2val, $EX);
    12451399                        break;
    12461400                    case XC_ADD_VAR:
    12471401                        break;
    12481402                    }
    1249                     if ($op1val == "''") {
     1403                    if (str($op1val) == "''") {
    12501404                        $rvalue = $op2val;
    12511405                    }
    1252                     else if ($op2val == "''") {
     1406                    else if (str($op2val) == "''") {
    12531407                        $rvalue = $op1val;
    12541408                    }
    12551409                    else {
    1256                         $rvalue = $op1val . ' . ' . $op2val;
     1410                        $rvalue = str($op1val) . ' . ' . str($op2val);
    12571411                    }
    12581412                    $resvar = $rvalue;
     
    12611415                case XC_PRINT: // {{{
    12621416                    $op1val = $this->getOpVal($op1, $EX);
    1263                     $resvar = "print($op1val)";
     1417                    $resvar = "print(" . str($op1val) . ")";
    12641418                    break;
    12651419                    // }}}
    12661420                case XC_ECHO: // {{{
    12671421                    $op1val = $this->getOpVal($op1, $EX);
    1268                     $resvar = "echo $op1val";
     1422                    $resvar = "echo " . str($op1val);
    12691423                    break;
    12701424                    // }}}
     
    13141468                    // }}}
    13151469                case XC_RETURN: // {{{
    1316                     $resvar = "return " . $this->getOpVal($op1, $EX);
     1470                    $resvar = "return " . str($this->getOpVal($op1, $EX));
    13171471                    break;
    13181472                    // }}}
     
    13201474                    $type = $op2['var']; // hack
    13211475                    $keyword = $this->includeTypes[$type];
    1322                     $resvar = "$keyword(" . $this->getOpVal($op1, $EX) . ")";
     1476                    $resvar = "$keyword " . str($this->getOpVal($op1, $EX));
    13231477                    break;
    13241478                    // }}}
     
    13571511                    // }}}
    13581512                case XC_JMP_NO_CTOR:
     1513                    break;
     1514                case XC_JMP_SET: // ?:
     1515                    $resvar = $this->getOpVal($op1, $EX);
     1516                    $op['cond'] = $resvar;
     1517                    $op['isjmp'] = true;
    13591518                    break;
    13601519                case XC_JMPNZ: // while
     
    13791538                        var_dump($op);// exit;
    13801539                    }
    1381                     if ($opc == XC_JMPZ_EX || $opc == XC_JMPNZ_EX || $opc == XC_JMPZ) {
     1540                    if ($opc == XC_JMPZ_EX || $opc == XC_JMPNZ_EX) {
    13821541                        $targetop = &$EX['opcodes'][$op2['opline_num']];
    13831542                        if ($opc == XC_JMPNZ_EX) {
    1384                             $targetop['cond_true'][] = toCode($rvalue, $EX);
     1543                            $targetop['cond_true'][] = foldToCode($rvalue, $EX);
    13851544                        }
    13861545                        else {
    1387                             $targetop['cond_false'][] = toCode($rvalue, $EX);
     1546                            $targetop['cond_false'][] = foldToCode($rvalue, $EX);
    13881547                        }
    13891548                        unset($targetop);
     
    13951554                    break;
    13961555                    // }}}
     1556                case XC_CONT:
     1557                case XC_BRK:
     1558                    $op['cond'] = null;
     1559                    $op['isjmp'] = true;
     1560                    $resvar = $opc == XC_CONT ? 'continue' : 'break';
     1561                    $count = str($this->getOpVal($op2, $EX));
     1562                    if ($count != '1') {
     1563                        $resvar .= ' ' . $count;
     1564                    }
     1565                    break;
     1566                case XC_GOTO:
    13971567                case XC_JMP: // {{{
    13981568                    $op['cond'] = null;
     
    14011571                    // }}}
    14021572                case XC_CASE:
    1403                 case XC_BRK:
     1573                    $switchValue = $this->getOpVal($op1, $EX);
     1574                    $caseValue = $this->getOpVal($op2, $EX);
     1575                    $resvar = str($switchValue) . ' == ' . str($caseValue);
    14041576                    break;
    14051577                case XC_RECV_INIT:
     
    14251597                    $flags = array_flip(explode('_', $opname));
    14261598                    if (isset($flags['OBJ'])) {
    1427                         $resvar = $this->getOpVal($op1, $EX);
    1428                         $prop = $this->unquoteName($this->getOpVal($op2, $EX));
    1429                         if ($prop{0} == '$') {
    1430                             $resvar = $resvar . "{" . $prop . "}";
    1431                         }
    1432                         else {
    1433                             $resvar = $resvar . "->" . $prop;
    1434                         }
     1599                        $resvar = $this->getOpVal($op1, $EX) . '->' . unquoteVariableName($this->getOpVal($op2, $EX), $EX);
    14351600                    }
    14361601                    else {
     
    14391604                    $opstr = isset($flags['DEC']) ? '--' : '++';
    14401605                    if (isset($flags['POST'])) {
    1441                         $resvar .= ' ' . $opstr;
     1606                        $resvar .= $opstr;
    14421607                    }
    14431608                    else {
    1444                         $resvar = "$opstr $resvar";
     1609                        $resvar = "$opstr$resvar";
    14451610                    }
    14461611                    break;
     
    14531618                case XC_END_SILENCE: // {{{
    14541619                    $EX['silence'] --;
    1455                     $lastresvar = '@' . toCode($lastresvar, $EX);
    1456                     break;
    1457                     // }}}
    1458                 case XC_CONT: // {{{
     1620                    $lastresvar = '@' . str($lastresvar, $EX);
    14591621                    break;
    14601622                    // }}}
     
    14801642                case XC_EXT_NOP:
    14811643                    break;
     1644                case XC_DECLARE_FUNCTION:
     1645                    $this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']);
     1646                    break;
     1647                case XC_DECLARE_LAMBDA_FUNCTION: // {{{
     1648                    ob_start();
     1649                    $this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']);
     1650                    $resvar = ob_get_clean();
     1651                    $istmpres = true;
     1652                    break;
     1653                    // }}}
     1654                case XC_DECLARE_CONST:
     1655                    $name = $this->stripNamespace(unquoteName($this->getOpVal($op1, $EX), $EX));
     1656                    $value = str($this->getOpVal($op2, $EX));
     1657                    $resvar = 'const ' . $name . ' = ' . $value;
     1658                    break;
    14821659                case XC_DECLARE_FUNCTION_OR_CLASS:
    14831660                    /* always removed by compiler */
     
    14871664                    // $EX['tickschanged'] = true;
    14881665                    break;
     1666                case XC_RAISE_ABSTRACT_ERROR:
     1667                    // abstract function body is empty, don't need this code
     1668                    break;
     1669                case XC_USER_OPCODE:
     1670                    echo '// ZEND_USER_OPCODE, impossible to decompile';
     1671                    break;
     1672                case XC_OP_DATA:
     1673                    break;
    14891674                default: // {{{
    14901675                    echo "\x1B[31m * TODO ", $opname, "\x1B[0m\n";
    1491                     // }}}
     1676                    $covered = false;
     1677                    // }}}
     1678                }
     1679                if ($covered) {
     1680                    $this->usedOps[$opc] = true;
    14921681                }
    14931682            }
     
    15231712            $a = array_pop($EX['argstack']);
    15241713            if (is_array($a)) {
    1525                 array_unshift($args, toCode($a, $EX));
     1714                array_unshift($args, foldToCode($a, $EX));
    15261715            }
    15271716            else {
     
    15361725        $op1 = $op['op1'];
    15371726        $op2 = $op['op2'];
    1538         $d = array('opname' => xcache_get_opcode($op['opcode']), 'opcode' => $op['opcode']);
    1539 
    1540         foreach (array('op1' => 'op1', 'op2' => 'op2', 'result' => 'res') as $k => $kk) {
     1727        $d = array(xcache_get_opcode($op['opcode']), $op['opcode']);
     1728
     1729        foreach (array('op1' => '1:', 'op2' => '2:', 'result' => '>') as $k => $kk) {
    15411730            switch ($op[$k]['op_type']) {
    15421731            case XC_IS_UNUSED:
    1543                 $d[$kk] = '*UNUSED* ' . $op[$k]['opline_num'];
     1732                $d[$kk] = 'U:' . $op[$k]['opline_num'];
    15441733                break;
    15451734
    15461735            case XC_IS_VAR:
    15471736                $d[$kk] = '$' . $op[$k]['var'];
    1548                 if ($kk != 'res') {
    1549                     $d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
     1737                if ($k != 'result') {
     1738                    $d[$kk] .= ':' . str($this->getOpVal($op[$k], $EX));
    15501739                }
    15511740                break;
     
    15531742            case XC_IS_TMP_VAR:
    15541743                $d[$kk] = '#' . $op[$k]['var'];
    1555                 if ($kk != 'res') {
    1556                     $d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
     1744                if ($k != 'result') {
     1745                    $d[$kk] .= ':' . str($this->getOpVal($op[$k], $EX));
    15571746                }
    15581747                break;
     
    15631752
    15641753            default:
    1565                 if ($kk == 'res') {
     1754                if ($k == 'result') {
    15661755                    var_dump($op);
    15671756                    exit;
     
    15731762            }
    15741763        }
    1575         $d['ext'] = $op['extended_value'];
    1576 
    1577         var_dump($d);
     1764        $d[';'] = $op['extended_value'];
     1765
     1766        foreach ($d as $k => $v) {
     1767            echo is_int($k) ? '' : $k, str($v), "\t";
     1768        }
     1769        echo PHP_EOL;
    15781770    }
    15791771    // }}}
     
    16021794                $ai = $op_array['arg_info'][$i];
    16031795                if (!empty($ai['class_name'])) {
    1604                     echo $ai['class_name'], ' ';
     1796                    echo $this->stripNamespace($ai['class_name']), ' ';
    16051797                    if (!ZEND_ENGINE_2_2 && $ai['allow_null']) {
    16061798                        echo 'or NULL ';
     
    16381830                    }
    16391831                }
    1640                 echo toCode($arg[0], $indent);
     1832                echo str($arg[0], $indent);
    16411833            }
    16421834            if (isset($arg[1])) {
    1643                 echo ' = ', toCode($arg[1], $indent);
     1835                echo ' = ', str($arg[1], $indent);
    16441836            }
    16451837        }
     
    16481840    function dfunction($func, $indent = '', $nobody = false) // {{{
    16491841    {
     1842        $this->detectNamespace($func['op_array']['function_name']);
     1843
    16501844        if ($nobody) {
    1651             $body = ";\n";
    16521845            $EX = array();
    16531846            $EX['op_array'] = &$func['op_array'];
     
    16641857        }
    16651858
    1666         echo 'function ', $func['op_array']['function_name'], '(';
     1859        $functionName = $this->stripNamespace($func['op_array']['function_name']);
     1860        if ($functionName == '{closure}') {
     1861            $functionName = '';
     1862        }
     1863        echo 'function ', $functionName, '(';
    16671864        $this->dargs($EX, $indent);
    1668         echo ")\n";
    1669         echo $indent, "{\n";
    1670         echo $body;
    1671         echo "$indent}\n";
     1865        echo ")";
     1866        if ($nobody) {
     1867            echo ";\n";
     1868        }
     1869        else {
     1870            if ($functionName !== '') {
     1871                echo "\n";
     1872                echo $indent, "{\n";
     1873            }
     1874            else {
     1875                echo " {\n";
     1876            }
     1877
     1878            echo $body;
     1879            echo "$indent}";
     1880            if ($functionName !== '') {
     1881                echo "\n";
     1882            }
     1883        }
    16721884    }
    16731885    // }}}
    16741886    function dclass($class, $indent = '') // {{{
    16751887    {
     1888        $this->detectNamespace($class['name']);
     1889
    16761890        // {{{ class decl
    16771891        if (!empty($class['doc_comment'])) {
     
    16831897        if (!empty($class['ce_flags'])) {
    16841898            if ($class['ce_flags'] & ZEND_ACC_INTERFACE) {
    1685                 echo 'interface ';
    16861899                $isinterface = true;
    16871900            }
    16881901            else {
    1689                 if ($class['ce_flags'] & ZEND_ACC_IMPLICIT_ABSTRACT) {
     1902                if ($class['ce_flags'] & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
    16901903                    echo "abstract ";
    16911904                }
    1692                 if ($class['ce_flags'] & ZEND_ACC_FINAL) {
     1905                if ($class['ce_flags'] & ZEND_ACC_FINAL_CLASS) {
    16931906                    echo "final ";
    16941907                }
    16951908            }
    16961909        }
    1697         echo 'class ', $class['name'];
     1910        echo $isinterface ? 'interface ' : 'class ', $this->stripNamespace($class['name']);
    16981911        if ($class['parent']) {
    16991912            echo ' extends ', $class['parent'];
     
    17171930                    echo $newindent;
    17181931                    echo $prefix, $name, ' = ';
    1719                     echo toCode(value($v), $newindent);
     1932                    echo str(value($v), $newindent);
    17201933                    echo ";\n";
    17211934                }
     
    17912004                if (isset($value)) {
    17922005                    echo ' = ';
    1793                     echo toCode(value($value), $newindent);
     2006                    echo str(value($value), $newindent);
    17942007                }
    17952008                echo ";\n";
     
    18102023                    }
    18112024                    echo $newindent;
     2025                    $isAbstractMethod = false;
    18122026                    if (isset($opa['fn_flags'])) {
    1813                         if ($opa['fn_flags'] & ZEND_ACC_ABSTRACT) {
     2027                        if (($opa['fn_flags'] & ZEND_ACC_ABSTRACT) && !$isinterface) {
    18142028                            echo "abstract ";
     2029                            $isAbstractMethod = true;
    18152030                        }
    18162031                        if ($opa['fn_flags'] & ZEND_ACC_FINAL) {
     
    18362051                        }
    18372052                    }
    1838                     $this->dfunction($func, $newindent, $isinterface);
     2053                    $this->dfunction($func, $newindent, $isinterface || $isAbstractMethod);
    18392054                    if ($opa['function_name'] == 'Decompiler') {
    18402055                        //exit;
     
    18672082    function output() // {{{
    18682083    {
    1869         echo "<?". "php\n";
     2084        echo "<?". "php\n\n";
    18702085        foreach ($this->dc['class_table'] as $key => $class) {
    18712086            if ($key{0} != "\0") {
     2087                $this->dclass($class);
    18722088                echo "\n";
    1873                 $this->dclass($class);
    18742089            }
    18752090        }
     
    18772092        foreach ($this->dc['function_table'] as $key => $func) {
    18782093            if ($key{0} != "\0") {
     2094                $this->dfunction($func);
    18792095                echo "\n";
    1880                 $this->dfunction($func);
    1881             }
    1882         }
    1883 
    1884         echo "\n";
     2096            }
     2097        }
     2098
    18852099        $this->dop_array($this->dc['op_array']);
    18862100        echo "\n?" . ">\n";
     2101
     2102        if (!empty($this->test)) {
     2103            $this->outputUnusedOp();
     2104        }
    18872105        return true;
    18882106    }
    18892107    // }}}
     2108    function outputUnusedOp() // {{{
     2109    {
     2110        for ($i = 0; $opname = xcache_get_opcode($i); $i ++) {
     2111            if ($opname == 'UNDEF')  {
     2112                continue;
     2113            }
     2114
     2115            if (!isset($this->usedOps[$i])) {
     2116                echo "not covered opcode ", $opname, "\n";
     2117            }
     2118        }
     2119    }
     2120    // }}}
    18902121}
    18912122
    18922123// {{{ defines
    1893 define('ZEND_ACC_STATIC',         0x01);
    1894 define('ZEND_ACC_ABSTRACT',       0x02);
    1895 define('ZEND_ACC_FINAL',          0x04);
    1896 define('ZEND_ACC_IMPLEMENTED_ABSTRACT',       0x08);
    1897 
    1898 define('ZEND_ACC_IMPLICIT_ABSTRACT_CLASS',    0x10);
    1899 define('ZEND_ACC_EXPLICIT_ABSTRACT_CLASS',    0x20);
    1900 define('ZEND_ACC_FINAL_CLASS',                0x40);
    1901 define('ZEND_ACC_INTERFACE',                  0x80);
    1902 define('ZEND_ACC_PUBLIC',     0x100);
    1903 define('ZEND_ACC_PROTECTED',  0x200);
    1904 define('ZEND_ACC_PRIVATE',    0x400);
    1905 define('ZEND_ACC_PPP_MASK',  (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE));
    1906 
    1907 define('ZEND_ACC_CHANGED',    0x800);
    1908 define('ZEND_ACC_IMPLICIT_PUBLIC',    0x1000);
    1909 
    1910 define('ZEND_ACC_CTOR',       0x2000);
    1911 define('ZEND_ACC_DTOR',       0x4000);
    1912 define('ZEND_ACC_CLONE',      0x8000);
    1913 
    1914 define('ZEND_ACC_ALLOW_STATIC',   0x10000);
    1915 
    1916 define('ZEND_ACC_SHADOW', 0x2000);
    1917 
    19182124define('ZEND_ENGINE_2_4', PHP_VERSION >= "5.3.99");
    19192125define('ZEND_ENGINE_2_3', ZEND_ENGINE_2_4 || PHP_VERSION >= "5.3.");
     
    19212127define('ZEND_ENGINE_2_1', ZEND_ENGINE_2_2 || PHP_VERSION >= "5.1.");
    19222128define('ZEND_ENGINE_2',   ZEND_ENGINE_2_1 || PHP_VERSION >= "5.0.");
     2129
     2130define('ZEND_ACC_STATIC',         0x01);
     2131define('ZEND_ACC_ABSTRACT',       0x02);
     2132define('ZEND_ACC_FINAL',          0x04);
     2133define('ZEND_ACC_IMPLEMENTED_ABSTRACT',       0x08);
     2134
     2135define('ZEND_ACC_IMPLICIT_ABSTRACT_CLASS',    0x10);
     2136define('ZEND_ACC_EXPLICIT_ABSTRACT_CLASS',    0x20);
     2137define('ZEND_ACC_FINAL_CLASS',                0x40);
     2138define('ZEND_ACC_INTERFACE',                  0x80);
     2139if (ZEND_ENGINE_2_4) {
     2140    define('ZEND_ACC_TRAIT',                  0x120);
     2141}
     2142define('ZEND_ACC_PUBLIC',     0x100);
     2143define('ZEND_ACC_PROTECTED',  0x200);
     2144define('ZEND_ACC_PRIVATE',    0x400);
     2145define('ZEND_ACC_PPP_MASK',  (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE));
     2146
     2147define('ZEND_ACC_CHANGED',    0x800);
     2148define('ZEND_ACC_IMPLICIT_PUBLIC',    0x1000);
     2149
     2150define('ZEND_ACC_CTOR',       0x2000);
     2151define('ZEND_ACC_DTOR',       0x4000);
     2152define('ZEND_ACC_CLONE',      0x8000);
     2153
     2154define('ZEND_ACC_ALLOW_STATIC',   0x10000);
     2155
     2156define('ZEND_ACC_SHADOW', 0x2000);
    19232157
    19242158if (ZEND_ENGINE_2_4) {
     
    19902224define('IS_LONG',     1);
    19912225define('IS_DOUBLE',   2);
    1992 define('IS_STRING',   3);
     2226define('IS_BOOL',     ZEND_ENGINE_2 ? 3 : 6);
    19932227define('IS_ARRAY',    4);
    19942228define('IS_OBJECT',   5);
    1995 define('IS_BOOL',     6);
     2229define('IS_STRING',   ZEND_ENGINE_2 ? 6 : 3);
    19962230define('IS_RESOURCE', 7);
    19972231define('IS_CONSTANT', 8);
     
    20192253    'XC_ASSIGN_DIM' => -1,
    20202254    'XC_UNSET_DIM' => -1,
    2021     'XC_FETCH_OBJ_' => -1,
     2255    'XC_UNSET_OBJ' => -1,
    20222256    'XC_ASSIGN_OBJ' => -1,
    20232257    'XC_ISSET_ISEMPTY_DIM_OBJ' => -1,
     
    20402274    'XC_FETCH_DIM_' => -1,
    20412275    'XC_UNSET_DIM_OBJ' => -1,
    2042     'XC_FETCH_OBJ_' => -1,
    20432276    'XC_ISSET_ISEMPTY' => -1,
    20442277    'XC_INIT_FCALL_BY_FUNC' => -1,
    20452278    'XC_DO_FCALL_BY_FUNC' => -1,
    20462279    'XC_DECLARE_FUNCTION_OR_CLASS' => -1,
     2280    'XC_INIT_NS_FCALL_BY_NAME' => -1,
     2281    'XC_GOTO' => -1,
     2282    'XC_CATCH' => -1,
     2283    'XC_THROW' => -1,
     2284    'XC_INSTANCEOF' => -1,
     2285    'XC_DECLARE_FUNCTION' => -1,
     2286    'XC_RAISE_ABSTRACT_ERROR' => -1,
     2287    'XC_DECLARE_CONST' => -1,
     2288    'XC_USER_OPCODE' => -1,
     2289    'XC_JMP_SET' => -1,
     2290    'XC_DECLARE_LAMBDA_FUNCTION' => -1,
    20472291) as $k => $v) {
    20482292    if (!defined($k)) {
     
    20502294    }
    20512295}
    2052 
    2053 /* XC_UNDEF XC_OP_DATA
    2054 $content = file_get_contents(__FILE__);
    2055 for ($i = 0; $opname = xcache_get_opcode($i); $i ++) {
    2056     if (!preg_match("/\\bXC_" . $opname . "\\b(?!')/", $content)) {
    2057         echo "not done ", $opname, "\n";
    2058     }
    2059 }
    2060 // */
    20612296// }}}
    20622297
  • branches/1.3/NEWS

    r726 r766  
    111.3.2 2011-??-??
    22========
     3 * adds 30 seconds timeout to "compiling" flag
     4 * improves decompiling
    35 * memory leak on recompile
    46 * disassembler fixes and updates for new PHP
  • branches/1.3/decompilesample.php

    r739 r766  
    11<?php
    22
    3 class ClassName
    4 {
     3//* >= PHP 5.3
     4namespace ns;
     5// */
     6
     7abstract class ClassName
     8{
     9    const CONST_VALUE = 'A constant value';
     10
    511    /** doc */
    612    static public $static = array(
     
    2935    public function __construct($a, $b)
    3036    {
    31     }
     37        echo CONST_VALUE;
     38        echo ClassName::CONST_VALUE;
     39        unset(ClassName::$classProp);
     40        unset($obj->objProp);
     41        unset($this->thisProp);
     42        unset($array['index']->valueProp);
     43        unset($obj->array['index']);
     44        unset($this->array['index']);
     45        $obj->objProp = 1;
     46        $this->thisProp = 1;
     47        $array['index']->valueProp = 1;
     48        $array['index'] = 1;
     49        $array[1] = 1;
     50    }
     51
     52    /** doc */
     53    abstract public function abastractMethod();
    3254
    3355    /** doc */
     
    6587}
    6688
     89interface IInterface
     90{
     91    public function nothing();
     92}
     93
     94function f1($f)
     95{
     96    echo __FUNCTION__;
     97    echo $f;
     98}
     99
     100final class Child extends ClassName implements IInterface
     101{
     102    public function __construct()
     103    {
     104        parent::__construct();
     105        ClassName::__construct();
     106        echo __CLASS__;
     107        echo __METHOD__;
     108        throw new Exception();
     109        $this->methodCall();
     110    }
     111
     112    public function __destruct()
     113    {
     114        parent::__destruct();
     115        functionCall();
     116    }
     117
     118    static public function __callStatic($name, $args)
     119    {
     120    }
     121
     122    public function __toString()
     123    {
     124    }
     125
     126    public function __set($name, $value)
     127    {
     128    }
     129
     130    public function __get($name)
     131    {
     132    }
     133
     134    public function __isset($name)
     135    {
     136    }
     137
     138    public function __unset($name)
     139    {
     140    }
     141
     142    public function __sleep()
     143    {
     144    }
     145
     146    public function __wakeup()
     147    {
     148    }
     149
     150    public function __clone()
     151    {
     152        return array();
     153    }
     154}
     155
     156if ($late) {
     157class LateBindingClass
     158{}
     159
     160function lateBindingFunction($arg)
     161{
     162    echo 'lateFunction';
     163}
     164}
     165
     166echo "\r\n";
     167echo "\r";
     168echo "\n";
     169echo str_replace(array('a' => 'a', 'b' => 'c'), 'b');
     170$object = new ClassName();
     171$object = new $className();
     172$result = $object instanceof ClassName;
     173$cloned = clone $object;
     174$a = 1;
     175$a = $b + $c;
     176$a = $b + 1;
     177$a = 1 + $b;
     178$a = $b - $c;
     179$a = $b * $c;
     180$a = $b / $c;
     181$a = $b % $c;
     182$a = $b . $c;
     183$a = $b = $c;
     184$a = $b & $c;
     185$a = $b | $c;
     186$a = $b ^ $c;
     187$a = ~$b;
     188$a = -$b;
     189$a = +$b;
     190$a = $b >> $c;
     191$a = $b >> $c;
     192$a = $b == $c;
     193$a = $b === $c;
     194$a = $b != $c;
     195$a = $b < $c;
     196$a = $b <= $c;
     197$a = $b <= $c;
     198$a = $b++;
     199$a = ++$b;
     200$a = $obj->b++;
     201$a = ++$obj->b;
     202$a = $b--;
     203$a = --$b;
     204$a = $obj->b--;
     205$a = --$obj->b;
     206$a = $b xor $c;
     207$a = !$b;
     208$a = $b === $c;
     209$a = $b !== $c;
     210$a = $b << 2;
     211$a = $b >> 3;
     212$a += $b;
     213$a -= $b;
     214$a *= $b;
     215$a /= $b;
     216$a <<= $b;
     217$a >>= $b;
     218$a &= $b;
     219$a |= $b;
     220$a .= $b;
     221$a %= $b;
     222$a ^= $b;
     223$a = 'a' . 'b';
     224$a = 'a' . 'abc';
     225@f1();
     226print('1');
     227ref(&$a);
     228$a = $array['index'];
     229$a = $object->prop;
     230$a = $this->prop;
     231$array['index'] = 1;
     232$object->prop = 1;
     233$this->prop = 1;
     234$a = isset($b);
     235$a = empty($b);
     236$a = isset($array['index']);
     237$a = empty($array['index']);
     238$a = isset($object->prop);
     239$a = empty($object->prop);
     240$a = isset($this->prop);
     241$a = empty($this->prop);
     242$a = (int) $b;
     243$a = (double) $b;
     244$a = (string) $b;
     245$a = (array) $b;
     246$a = (object) $b;
     247$a = (bool) $b;
     248$a = (unset) $b;
     249$a = (array) $b;
     250$a = (object) $b;
     251// PHP6+ $a = (scalar) $b;
     252$a = $b ? $c : $d;
     253$a = f1() ? f2() : f3();
     254$a = $b and $c;
     255$a = $b or $c;
     256$a = $b && $c;
     257$a = $b || $c;
     258
     259try {
     260    echo 'outer try 1';
     261    try {
     262        echo 'inner try';
     263    }
     264    catch (InnerException $e) {
     265        echo $e;
     266    }
     267    echo 'outer try 2';
     268}
     269catch (OuterException $e) {
     270    echo $e;
     271}
     272
     273if ($a) {
     274    echo 'if ($a)';
     275}
     276else if ($b) {
     277    echo 'else if ($b)';
     278}
     279else {
     280    echo 'else';
     281}
     282
     283while (false) {
     284    echo 'while';
     285}
     286
     287do {
     288    echo 'do/while';
     289} while (false);
     290
     291for ($i = 1; $i < 10; ++$i) {
     292    echo $i;
     293    break;
     294}
     295
     296foreach ($array as $key => $value) {
     297    foreach ($array as $key => $value) {
     298        echo $key . ' = ' . $value . "\n";
     299        break 2;
     300        continue;
     301    }
     302}
     303
     304switch ($switch) {
     305case 'case1':
     306    echo 'case1';
     307    break;
     308
     309case 'case2':
     310    echo 'case2';
     311    break;
     312
     313default:
     314    echo 'default';
     315    break;
     316}
     317
     318declare (ticks=1) {
     319    echo 1;
     320    echo 2;
     321}
     322
     323require 'require.php';
     324require_once 'require_once.php';
     325include 'include.php';
     326include_once 'include_once.php';
     327echo __FILE__;
     328echo __LINE__;
     329
     330//*
     331echo 'PHP 5.3+ code testing';
     332const CONST_VALUE = 1;
     333echo $this::CONST_VALUE;
     334echo $a::CONST_VALUE;
     335echo CONST_VALUE;
     336$this::__construct();
     337$obj::__construct();
     338
     339$a = $b ?: $d;
     340$a = ($b ?: $d) + $c;
     341$a = f1() ?: f2();
     342
     343echo 'goto a';
     344goto a;
     345
     346for ($i = 1; $i <= 2; ++$i) {
     347    goto a;
     348}
     349
     350a:
     351echo 'label a';
     352echo preg_replace_callback('~-([a-z])~', function ($match) {
     353    return strtoupper($match[1]);
     354}, 'hello-world');
     355$greet = function ($name) {
     356    printf("Hello %s\r\n", $name);
     357};
     358$greet('World');
     359$greet('PHP');
     360$total = 0;
     361$tax = 1;
     362$callback = function ($quantity, $product) use ($tax, &$total) {
     363    static $static = array(1);
     364    $tax = 'tax';
     365    $pricePerItem = constant('PRICE_' . strtoupper($product));
     366    $total += $pricePerItem * $quantity * ($tax + 1);
     367};
     368// */
     369exit();
    67370
    68371?>
  • branches/1.3/disassembler.c

    r726 r766  
    3737    add_assoc_zval_ex(dst, ZEND_STRS("op_array"), zv);
    3838
     39    buf = emalloc(bufsize);
     40
    3941    ALLOC_INIT_ZVAL(list);
    4042    array_init(list);
    4143    b = TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead;
    4244    for (; b; b = b->pListNext) {
     45        int keysize, keyLength;
     46
    4347        ALLOC_INIT_ZVAL(zv);
    4448        array_init(zv);
    4549        xc_dasm_zend_function(zv, b->pData TSRMLS_CC);
    46 
    47         add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, zv);
    48     }
    49     add_assoc_zval_ex(dst, ZEND_STRS("function_table"), list);
    50    
    51     buf = emalloc(bufsize);
    52     ALLOC_INIT_ZVAL(list);
    53     array_init(list);
    54     b = TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead;
    55     for (; b; b = b->pListNext) {
    56         int keysize, keyLength;
    57 
    58         ALLOC_INIT_ZVAL(zv);
    59         array_init(zv);
    60         xc_dasm_zend_class_entry(zv, CestToCePtr(*(xc_cest_t *)b->pData) TSRMLS_CC);
    6150
    6251        keysize = BUCKET_KEY_SIZE(b) + 2;
     
    8271            }
    8372        }
     73
     74        add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), keyLength, zv);
     75    }
     76    add_assoc_zval_ex(dst, ZEND_STRS("function_table"), list);
     77   
     78    ALLOC_INIT_ZVAL(list);
     79    array_init(list);
     80    b = TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead;
     81    for (; b; b = b->pListNext) {
     82        int keysize, keyLength;
     83
     84        ALLOC_INIT_ZVAL(zv);
     85        array_init(zv);
     86        xc_dasm_zend_class_entry(zv, CestToCePtr(*(xc_cest_t *)b->pData) TSRMLS_CC);
     87
     88        keysize = BUCKET_KEY_SIZE(b) + 2;
     89        if (keysize > bufsize) {
     90            do {
     91                bufsize *= 2;
     92            } while (keysize > bufsize);
     93            buf = erealloc(buf, bufsize);
     94        }
     95        memcpy(buf, BUCKET_KEY_S(b), keysize);
     96        buf[keysize - 2] = buf[keysize - 1] = ""[0];
     97        keyLength = b->nKeyLength;
     98#ifdef IS_UNICODE
     99        if (BUCKET_KEY_TYPE(b) == IS_UNICODE) {
     100            if (buf[0] == ""[0] && buf[1] == ""[0]) {
     101                keyLength ++;
     102            }
     103        } else
     104#endif
     105        {
     106            if (buf[0] == ""[0]) {
     107                keyLength ++;
     108            }
     109        }
    84110        add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), keyLength, zv);
    85111    }
  • branches/1.3/phpdop.phpr

    r739 r766  
    110110}
    111111var_dump($pk);
    112 if (isset($op_array)) {
    113     dump_opcodes($op_array['opcodes']);
     112if (isset($classes)) {
     113    foreach ($classes as $name => $class) {
     114        dump_class($name, $class);
     115    }
    114116}
    115117if (isset($funcs)) {
     
    118120    }
    119121}
    120 if (isset($classes)) {
    121     foreach ($classes as $name => $class) {
    122         dump_class($name, $class);
    123     }
     122if (isset($op_array)) {
     123    dump_opcodes($op_array['opcodes']);
    124124}
    125125
  • branches/1.3/processor/struct.m4

    r726 r766  
    3333            /* {{{ init assert */
    3434            ifdef(`SIZEOF_$1', , `m4_errprint(`missing SIZEOF_$1, safe to ignore')')
    35             ifdef(`COUNTOF_$1', , `m4_errprint(`missing COUNTOF_$1, safe to ignore'))')
     35            ifdef(`COUNTOF_$1', , `m4_errprint(`missing COUNTOF_$1, safe to ignore')')
    3636            dnl SIZEOF_x COUNTOF_x can be both defined or both not
    3737            ifdef(`SIZEOF_$1', `
  • branches/1.3/utils.c

    r726 r766  
    244244            case IS_TMP_VAR:
    245245                break;
     246
     247            case IS_CONST:
     248                if (spec == OPSPEC_UCLASS) {
     249                    break;
     250                }
     251                /* fall */
    246252
    247253            default:
  • branches/1.3/xcache.c

    r726 r766  
    10011001    /* {{{ restore */
    10021002    /* stale precheck */
    1003     if (cache->compiling) {
     1003    if (XG(request_time) - cache->compiling < 30) {
    10041004        cache->clogs ++; /* is it safe here? */
    10051005        return old_compile_file(h, type TSRMLS_CC);
     
    10101010    ENTER_LOCK_EX(cache) {
    10111011        /* clogged */
    1012         if (cache->compiling) {
     1012        if (XG(request_time) - cache->compiling < 30) {
    10131013            cache->clogs ++;
    10141014            op_array = NULL;
Note: See TracChangeset for help on using the changeset viewer.