source: trunk/Decompiler.class.php @ 790

Last change on this file since 790 was 790, checked in by moo, 4 years ago

Decompiler: decompile switch

  • Property svn:eol-style set to native
File size: 64.3 KB
RevLine 
[1]1<?php
2
3define('INDENT', "\t");
4ini_set('error_reporting', E_ALL);
5
6function color($str, $color = 33)
7{
8    return "\x1B[{$color}m$str\x1B[0m";
9}
10
[737]11function str($code, $indent = '') // {{{
12{
[744]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    }
[737]20    if (is_object($code)) {
[744]21        $code = foldToCode($code, $indent);
22        return $code->toCode($indent);
[737]23    }
24
25    return (string) $code;
26}
27// }}}
[744]28function foldToCode($src, $indent = '') // {{{ wrap or rewrap anything to Decompiler_Code
[1]29{
30    if (is_array($indent)) {
31        $indent = $indent['indent'];
32    }
33
[741]34    if (!is_object($src)) {
35        return new Decompiler_Code($src);
[1]36    }
37
[741]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;
[1]48}
49// }}}
50function value($value) // {{{
51{
52    $spec = xcache_get_special_value($value);
53    if (isset($spec)) {
54        $value = $spec;
55        if (!is_array($value)) {
56            // constant
57            return $value;
58        }
59    }
60
[737]61    if (is_a($value, 'Decompiler_Object')) {
[723]62        // use as is
63    }
64    else if (is_array($value)) {
[737]65        $value = new Decompiler_ConstArray($value);
[1]66    }
67    else {
[713]68        $value = new Decompiler_Value($value);
[1]69    }
70    return $value;
71}
72// }}}
[761]73function unquoteName_($str, $asVariableName, $indent = '') // {{{
[749]74{
75    $str = str($str, $indent);
[753]76    if (preg_match("!^'[\\w_][\\w\\d_\\\\]*'\$!", $str)) {
77        return str_replace('\\\\', '\\', substr($str, 1, -1));
[749]78    }
[761]79    else if ($asVariableName) {
[749]80        return "{" . $str . "}";
81    }
[753]82    else {
83        return $str;
84    }
[749]85}
86// }}}
[761]87function unquoteVariableName($str, $indent = '') // {{{
[753]88{
89    return unquoteName_($str, true, $indent);
90}
91// }}}
[749]92function unquoteName($str, $indent = '') // {{{
93{
[753]94    return unquoteName_($str, false, $indent);
[749]95}
96// }}}
[1]97class Decompiler_Object // {{{
98{
99}
100// }}}
101class Decompiler_Value extends Decompiler_Object // {{{
102{
103    var $value;
104
105    function Decompiler_Value($value = null)
106    {
107        $this->value = $value;
108    }
109
[732]110    function toCode($indent)
[1]111    {
[750]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;
[1]127    }
128}
129// }}}
130class Decompiler_Code extends Decompiler_Object // {{{
131{
132    var $src;
133
134    function Decompiler_Code($src)
135    {
[743]136        assert('isset($src)');
[1]137        $this->src = $src;
138    }
139
[732]140    function toCode($indent)
[1]141    {
[741]142        return $this->src;
[737]143    }
[1]144}
145// }}}
146class Decompiler_Binop extends Decompiler_Code // {{{
147{
148    var $opc;
149    var $op1;
150    var $op2;
151    var $parent;
[732]152    var $indent;
[1]153
154    function Decompiler_Binop($parent, $op1, $opc, $op2)
155    {
156        $this->parent = &$parent;
157        $this->opc = $opc;
158        $this->op1 = $op1;
159        $this->op2 = $op2;
160    }
161
[732]162    function toCode($indent)
[1]163    {
[757]164        $opstr = $this->parent->binops[$this->opc];
165
[744]166        $op1 = foldToCode($this->op1, $indent);
[1]167        if (is_a($this->op1, 'Decompiler_Binop') && $this->op1->opc != $this->opc) {
[757]168            $op1 = "(" . str($op1, $indent) . ")";
[1]169        }
[757]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) . ")";
[1]173        }
[757]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);
[1]180    }
181}
182// }}}
183class Decompiler_Fetch extends Decompiler_Code // {{{
184{
185    var $src;
186    var $fetchType;
187
188    function Decompiler_Fetch($src, $type, $globalsrc)
189    {
190        $this->src = $src;
191        $this->fetchType = $type;
192        $this->globalsrc = $globalsrc;
193    }
194
[732]195    function toCode($indent)
[1]196    {
197        switch ($this->fetchType) {
198        case ZEND_FETCH_LOCAL:
199            return '$' . substr($this->src, 1, -1);
200        case ZEND_FETCH_STATIC:
[749]201            if (ZEND_ENGINE_2_3) {
202                // closure local variable?
203                return str($this->src);
204            }
[1]205            die('static fetch cant to string');
206        case ZEND_FETCH_GLOBAL:
207        case ZEND_FETCH_GLOBAL_LOCK:
208            return $this->globalsrc;
209        default:
210            var_dump($this->fetchType);
211            assert(0);
212        }
213    }
214}
215// }}}
216class Decompiler_Box // {{{
217{
218    var $obj;
219
220    function Decompiler_Box(&$obj)
221    {
222        $this->obj = &$obj;
223    }
224
[732]225    function toCode($indent)
[1]226    {
[732]227        return $this->obj->toCode($indent);
[1]228    }
229}
230// }}}
231class Decompiler_Dim extends Decompiler_Value // {{{
232{
233    var $offsets = array();
234    var $isLast = false;
[749]235    var $isObject = false;
[1]236    var $assign = null;
237
[732]238    function toCode($indent)
[1]239    {
240        if (is_a($this->value, 'Decompiler_ListBox')) {
[749]241            $exp = str($this->value->obj->src, $indent);
[1]242        }
243        else {
[749]244            $exp = str($this->value, $indent);
[1]245        }
[749]246        $last = count($this->offsets) - 1;
247        foreach ($this->offsets as $i => $dim) {
248            if ($this->isObject && $i == $last) {
[761]249                $exp .= '->' . unquoteVariableName($dim, $indent);
[749]250            }
251            else {
252                $exp .= '[' . str($dim, $indent) . ']';
253            }
[1]254        }
255        return $exp;
256    }
257}
258// }}}
259class Decompiler_DimBox extends Decompiler_Box // {{{
260{
261}
262// }}}
263class Decompiler_List extends Decompiler_Code // {{{
264{
265    var $src;
266    var $dims = array();
267    var $everLocked = false;
268
[732]269    function toCode($indent)
[1]270    {
271        if (count($this->dims) == 1 && !$this->everLocked) {
272            $dim = $this->dims[0];
273            unset($dim->value);
274            $dim->value = $this->src;
275            if (!isset($dim->assign)) {
[754]276                return str($dim, $indent);
[1]277            }
[754]278            return str($this->dims[0]->assign, $indent) . ' = ' . str($dim, $indent);
[1]279        }
280        /* flatten dims */
281        $assigns = array();
282        foreach ($this->dims as $dim) {
283            $assign = &$assigns;
284            foreach ($dim->offsets as $offset) {
285                $assign = &$assign[$offset];
286            }
[744]287            $assign = foldToCode($dim->assign, $indent);
[1]288        }
[754]289        return str($this->toList($assigns)) . ' = ' . str($this->src, $indent);
[1]290    }
291
292    function toList($assigns)
293    {
294        $keys = array_keys($assigns);
295        if (count($keys) < 2) {
296            $keys[] = 0;
297        }
298        $max = call_user_func_array('max', $keys);
299        $list = 'list(';
300        for ($i = 0; $i <= $max; $i ++) {
301            if ($i) {
302                $list .= ', ';
303            }
304            if (!isset($assigns[$i])) {
305                continue;
306            }
307            if (is_array($assigns[$i])) {
308                $list .= $this->toList($assigns[$i]);
309            }
310            else {
311                $list .= $assigns[$i];
312            }
313        }
314        return $list . ')';
315    }
316}
317// }}}
318class Decompiler_ListBox extends Decompiler_Box // {{{
319{
320}
321// }}}
322class Decompiler_Array extends Decompiler_Value // {{{
323{
[737]324    // emenets
325    function Decompiler_Array()
[1]326    {
[737]327        $this->value = array();
[1]328    }
329
[732]330    function toCode($indent)
[1]331    {
[737]332        $subindent = $indent . INDENT;
333
334        $elementsCode = array();
335        $index = 0;
336        foreach ($this->value as $element) {
337            list($key, $value) = $element;
338            if (!isset($key)) {
339                $key = $index++;
340            }
341            $elementsCode[] = array(str($key, $subindent), str($value, $subindent), $key, $value);
342        }
343
[1]344        $exp = "array(";
[732]345        $indent = $indent . INDENT;
[735]346        $assocWidth = 0;
[1]347        $multiline = 0;
348        $i = 0;
[737]349        foreach ($elementsCode as $element) {
350            list($keyCode, $valueCode) = $element;
351            if ((string) $i !== $keyCode) {
[735]352                $assocWidth = 1;
[737]353                break;
[735]354            }
355            ++$i;
356        }
[737]357        foreach ($elementsCode as $element) {
358            list($keyCode, $valueCode, $key, $value) = $element;
[735]359            if ($assocWidth) {
[737]360                $len = strlen($keyCode);
[735]361                if ($assocWidth < $len) {
362                    $assocWidth = $len;
[1]363                }
364            }
[737]365            if (is_array($value) || is_a($value, 'Decompiler_Array')) {
[1]366                $multiline ++;
367            }
368        }
369
370        $i = 0;
[737]371        foreach ($elementsCode as $element) {
372            list($keyCode, $value) = $element;
[1]373            if ($multiline) {
374                if ($i) {
375                    $exp .= ",";
376                }
377                $exp .= "\n";
378                $exp .= $indent;
379            }
380            else {
381                if ($i) {
382                    $exp .= ", ";
383                }
384            }
385
[735]386            if ($assocWidth) {
387                if ($multiline) {
[737]388                    $exp .= sprintf("%-{$assocWidth}s => ", $keyCode);
[735]389                }
390                else {
[737]391                    $exp .= $keyCode . ' => ';
[735]392                }
[1]393            }
394
[737]395            $exp .= $value;
[1]396
397            $i ++;
398        }
399        if ($multiline) {
[732]400            $exp .= "\n$indent)";
[1]401        }
402        else {
403            $exp .= ")";
404        }
405        return $exp;
406    }
407}
408// }}}
[737]409class Decompiler_ConstArray extends Decompiler_Array // {{{
410{
411    function Decompiler_ConstArray($array)
412    {
413        $elements = array();
414        foreach ($array as $key => $value) {
415            $elements[] = array(value($key), value($value));
416        }
417        $this->value = $elements;
418    }
419}
420// }}}
[1]421class Decompiler_ForeachBox extends Decompiler_Box // {{{
422{
423    var $iskey;
424
[732]425    function toCode($indent)
[1]426    {
427        return 'foreach (' . '';
428    }
429}
430// }}}
431
432class Decompiler
433{
[753]434    var $namespace;
435    var $namespaceDecided;
[1]436
437    function Decompiler()
438    {
[761]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        // }}}
[1]453        // {{{ opinfo
454        $this->unaryops = array(
455                XC_BW_NOT   => '~',
456                XC_BOOL_NOT => '!',
457                );
458        $this->binops = array(
459                XC_ADD                 => "+",
460                XC_ASSIGN_ADD          => "+=",
461                XC_SUB                 => "-",
462                XC_ASSIGN_SUB          => "-=",
463                XC_MUL                 => "*",
464                XC_ASSIGN_MUL          => "*=",
465                XC_DIV                 => "/",
466                XC_ASSIGN_DIV          => "/=",
467                XC_MOD                 => "%",
468                XC_ASSIGN_MOD          => "%=",
469                XC_SL                  => "<<",
470                XC_ASSIGN_SL           => "<<=",
471                XC_SR                  => ">>",
472                XC_ASSIGN_SR           => ">>=",
473                XC_CONCAT              => ".",
474                XC_ASSIGN_CONCAT       => ".=",
475                XC_IS_IDENTICAL        => "===",
476                XC_IS_NOT_IDENTICAL    => "!==",
477                XC_IS_EQUAL            => "==",
478                XC_IS_NOT_EQUAL        => "!=",
479                XC_IS_SMALLER          => "<",
480                XC_IS_SMALLER_OR_EQUAL => "<=",
481                XC_BW_OR               => "|",
482                XC_ASSIGN_BW_OR        => "|=",
483                XC_BW_AND              => "&",
484                XC_ASSIGN_BW_AND       => "&=",
485                XC_BW_XOR              => "^",
486                XC_ASSIGN_BW_XOR       => "^=",
487                XC_BOOL_XOR            => "xor",
488                );
489        // }}}
490        $this->includeTypes = array( // {{{
491                ZEND_EVAL         => 'eval',
492                ZEND_INCLUDE      => 'include',
493                ZEND_INCLUDE_ONCE => 'include_once',
494                ZEND_REQUIRE      => 'require',
495                ZEND_REQUIRE_ONCE => 'require_once',
496                );
497                // }}}
498    }
[753]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    // }}}
[787]524    function outputPhp(&$EX, $opline, $last, $indent) // {{{
[1]525    {
[789]526        $needBlankline = isset($EX['lastBlock']);
[1]527        $origindent = $indent;
528        $curticks = 0;
529        for ($i = $opline; $i <= $last; $i ++) {
[787]530            $op = $EX['opcodes'][$i];
531            if (isset($op['gofrom'])) {
[789]532                if ($needBlankline) {
533                    $needBlankline = false;
534                    echo PHP_EOL;
535                }
[787]536                echo 'label' . $i, ":\n";
537            }
[1]538            if (isset($op['php'])) {
[746]539                $toticks = isset($op['ticks']) ? (int) str($op['ticks']) : 0;
[1]540                if ($curticks != $toticks) {
[746]541                    $oldticks = $curticks;
542                    $curticks = $toticks;
543                    if (!$curticks) {
[749]544                        echo $origindent, "}\n\n";
[1]545                        $indent = $origindent;
546                    }
547                    else {
[746]548                        if ($oldticks) {
[749]549                            echo $origindent, "}\n\n";
[1]550                        }
[746]551                        else if (!$oldticks) {
[1]552                            $indent .= INDENT;
553                        }
[789]554                        if ($needBlankline) {
555                            $needBlankline = false;
556                            echo PHP_EOL;
557                        }
[746]558                        echo $origindent, "declare (ticks=$curticks) {\n";
[1]559                    }
560                }
[789]561                if ($needBlankline) {
562                    $needBlankline = false;
563                    echo PHP_EOL;
564                }
[744]565                echo $indent, str($op['php'], $indent), ";\n";
[790]566                $EX['lastBlock'] = 'basic';
[1]567            }
568        }
569        if ($curticks) {
570            echo $origindent, "}\n";
571        }
572    }
573    // }}}
574    function getOpVal($op, &$EX, $tostr = true, $free = false) // {{{
575    {
576        switch ($op['op_type']) {
577        case XC_IS_CONST:
[744]578            return foldToCode(value($op['constant']), $EX);
[1]579
580        case XC_IS_VAR:
581        case XC_IS_TMP_VAR:
582            $T = &$EX['Ts'];
[716]583            $ret = $T[$op['var']];
[1]584            if ($tostr) {
[744]585                $ret = foldToCode($ret, $EX);
[1]586            }
587            if ($free) {
[716]588                unset($T[$op['var']]);
[1]589            }
590            return $ret;
591
592        case XC_IS_CV:
[716]593            $var = $op['var'];
[1]594            $var = $EX['op_array']['vars'][$var];
595            return '$' . $var['name'];
596
597        case XC_IS_UNUSED:
598            return null;
599        }
600    }
601    // }}}
[716]602    function removeKeyPrefix($array, $prefix) // {{{
603    {
604        $prefixLen = strlen($prefix);
605        $ret = array();
606        foreach ($array as $key => $value) {
607            if (substr($key, 0, $prefixLen) == $prefix) {
608                $key = substr($key, $prefixLen);
609            }
610            $ret[$key] = $value;
611        }
612        return $ret;
613    }
614    // }}}
[735]615    function &fixOpcode($opcodes, $removeTailing = false, $defaultReturnValue = null) // {{{
[1]616    {
[716]617        for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
618            if (function_exists('xcache_get_fixed_opcode')) {
619                $opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i);
620            }
621            if (isset($opcodes[$i]['op1'])) {
622                $opcodes[$i]['op1'] = $this->removeKeyPrefix($opcodes[$i]['op1'], 'u.');
623                $opcodes[$i]['op2'] = $this->removeKeyPrefix($opcodes[$i]['op2'], 'u.');
624                $opcodes[$i]['result'] = $this->removeKeyPrefix($opcodes[$i]['result'], 'u.');
625            }
626            else {
627                $op = array(
628                    'op1' => array(),
629                    'op2' => array(),
630                    'op3' => array(),
631                );
632                foreach ($opcodes[$i] as $name => $value) {
633                    if (preg_match('!^(op1|op2|result)\\.(.*)!', $name, $m)) {
634                        list(, $which, $field) = $m;
635                        $op[$which][$field] = $value;
636                    }
637                    else if (preg_match('!^(op1|op2|result)_type$!', $name, $m)) {
638                        list(, $which) = $m;
639                        $op[$which]['op_type'] = $value;
640                    }
641                    else {
642                        $op[$name] = $value;
643                    }
644                }
645                $opcodes[$i] = $op;
646            }
647        }
[735]648
649        if ($removeTailing) {
650            $last = count($opcodes) - 1;
651            if ($opcodes[$last]['opcode'] == XC_HANDLE_EXCEPTION) {
[761]652                $this->usedOps[XC_HANDLE_EXCEPTION] = true;
[762]653                $opcodes[$last]['opcode'] = XC_NOP;
[735]654                --$last;
655            }
656            if ($opcodes[$last]['opcode'] == XC_RETURN) {
657                $op1 = $opcodes[$last]['op1'];
658                if ($op1['op_type'] == XC_IS_CONST && array_key_exists('constant', $op1) && $op1['constant'] === $defaultReturnValue) {
[762]659                    $opcodes[$last]['opcode'] = XC_NOP;
[735]660                    --$last;
661                }
662            }
663        }
[731]664        return $opcodes;
665    }
666    // }}}
[787]667    function decompileBasicBlock(&$EX, $first, $last, $indent) // {{{
668    {
669        $this->dasmBasicBlock($EX, $first, $last);
[790]670        // $this->dumpRange($EX, $first, $last, $indent);
[787]671        $this->outputPhp($EX, $first, $last, $indent);
672    }
673    // }}}
674    function removeJmpInfo(&$EX, $line) // {{{
675    {
676        $opcodes = &$EX['opcodes'];
677        foreach ($opcodes[$line]['jmpouts'] as $jmpTo) {
678            $jmpins = &$opcodes[$jmpTo]['jmpins'];
679            $jmpins = array_flip($jmpins);
680            unset($jmpins[$line]);
681            $jmpins = array_keys($jmpins);
682        }
[789]683        // $opcodes[$line]['opcode'] = XC_NOP;
[787]684        unset($opcodes[$line]['jmpouts']);
685    }
686    // }}}
[788]687    function beginComplexBlock(&$EX) // {{{
688    {
689        if (isset($EX['lastBlock'])) {
690            echo PHP_EOL;
691            $EX['lastBlock'] = null;
692        }
693    }
694    // }}}
695    function endComplexBlock(&$EX) // {{{
696    {
697        $EX['lastBlock'] = 'complex';
698    }
699    // }}}
[787]700    function decompileComplexBlock(&$EX, $first, $last, $indent) // {{{
701    {
[790]702        $T = &$EX['Ts'];
[787]703        $opcodes = &$EX['opcodes'];
704
705        $firstOp = &$opcodes[$first];
706        $lastOp = &$opcodes[$last];
707
[790]708        if ($firstOp['opcode'] == XC_SWITCH_FREE && isset($T[$firstOp['op1']['var']])) {
709            // TODO: merge this code to CASE code. use SWITCH_FREE to detect begin of switch by using $Ts if possible
710            $this->beginComplexBlock($EX);
711            echo $indent, 'switch (' . str($this->getOpVal($firstOp['op1'], $EX)) . ') {', PHP_EOL;
712            echo $indent, '}', PHP_EOL;
713            $this->endComplexBlock($EX);
714            return;
715        }
716
717        if (
718            ($firstOp['opcode'] == XC_CASE
719            || $firstOp['opcode'] == XC_JMP && !empty($firstOp['jmpouts']) && $opcodes[$firstOp['jmpouts'][0]]['opcode'] == XC_CASE
720            )
721             && !empty($lastOp['jmpouts'])
722        ) {
723            $cases = array();
724            $caseNext = null;
725            $caseDefault = null;
726            $caseOp = null;
727            for ($i = $first; $i <= $last; ++$i) {
728                $op = $opcodes[$i];
729                if ($op['opcode'] == XC_CASE) {
730                    if (!isset($caseOp)) {
731                        $caseOp = $op;
732                    }
733                    $jmpz = $opcodes[$i + 1];
734                    assert('$jmpz["opcode"] == XC_JMPZ');
735                    $caseNext = $jmpz['jmpouts'][0];
736                    $i = $cases[$i] = $caseNext - 1;
737                }
738                else if ($op['opcode'] == XC_JMP) {
739                    // default
740                    if ($op['jmpouts'][0] >= $i) {
741                        $caseNext = $op['jmpouts'][0];
742                        $caseDefault = $i;
743                        $i = $cases[$i] = $caseNext - 1;
744                    }
745                }
746            }
747
748            $this->beginComplexBlock($EX);
749
750            echo $indent, 'switch (', str($this->getOpVal($caseOp['op1'], $EX, true, true), $EX), ') {', PHP_EOL;
751            $caseIsOut = false;
752            foreach ($cases as $caseFirst => $caseLast) {
753                if ($caseIsOut && !empty($EX['lastBlock']) && empty($lastCaseFall)) {
754                    echo PHP_EOL;
755                }
756                unset($EX['lastBlock']);
757
758                $caseOp = $opcodes[$caseFirst];
759
760                echo $indent;
761                if ($caseOp['opcode'] == XC_CASE) {
762                    echo 'case ';
763                    echo str($this->getOpVal($caseOp['op2'], $EX), $EX);
764                    echo ':', PHP_EOL;
765
766                    $this->removeJmpInfo($EX, $caseFirst);
767                    ++$caseFirst;
768
769                    assert('$opcodes[$caseFirst]["opcode"] == XC_JMPZ');
770                    $this->removeJmpInfo($EX, $caseFirst);
771                    ++$caseFirst;
772                }
773                else {
774                    echo 'default';
775                    echo ':', PHP_EOL;
776
777                    assert('$opcodes[$caseFirst]["opcode"] == XC_JMP');
778                    $this->removeJmpInfo($EX, $caseFirst);
779                    ++$caseFirst;
780                }
781
782                assert('$opcodes[$caseLast]["opcode"] == XC_JMP');
783                $this->removeJmpInfo($EX, $caseLast);
784                --$caseLast;
785                switch ($opcodes[$caseLast]['opcode']) {
786                case XC_BRK:
787                case XC_CONT:
788                case XC_GOTO:
789                    $lastCaseFall = false;
790                    break;
791
792                default:
793                    $lastCaseFall = true;
794                }
795
796                $this->recognizeAndDecompileClosedBlocks($EX, $caseFirst, $caseLast, $indent . INDENT);
797                $caseIsOut = true;
798            }
799            echo $indent, '}', PHP_EOL;
800
801            $this->endComplexBlock($EX);
802            return;
803        }
804
[789]805        if ($lastOp['opcode'] == XC_JMPNZ && !empty($lastOp['jmpouts'])
[787]806         && $lastOp['jmpouts'][0] == $first) {
807            $this->removeJmpInfo($EX, $last);
[788]808            $this->beginComplexBlock($EX);
[789]809
[787]810            echo $indent, 'do {', PHP_EOL;
811            $this->recognizeAndDecompileClosedBlocks($EX, $first, $last, $indent . INDENT);
812            echo $indent, '} while (', str($this->getOpVal($lastOp['op1'], $EX)), ');', PHP_EOL;
[789]813
[788]814            $this->endComplexBlock($EX);
[787]815            return;
816        }
817
818        $firstJmp = null;
819        $firstJmpOp = null;
820        for ($i = $first; $i <= $last; ++$i) {
821            if (!empty($opcodes[$i]['jmpouts'])) {
822                $firstJmp = $i;
823                $firstJmpOp = &$opcodes[$firstJmp];
824                break;
825            }
826        }
827
828        if (isset($firstJmpOp)
829         && $firstJmpOp['opcode'] == XC_JMPZ
[789]830         && $firstJmpOp['jmpouts'][0] > $last
831         && $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts'])
[787]832         && $lastOp['jmpouts'][0] == $first) {
833            $this->removeJmpInfo($EX, $firstJmp);
834            $this->removeJmpInfo($EX, $last);
[789]835            $this->beginComplexBlock($EX);
[787]836
837            ob_start();
838            $this->recognizeAndDecompileClosedBlocks($EX, $first, $last, $indent . INDENT);
[789]839            $body = ob_get_clean();
840
[787]841            echo $indent, 'while (', str($this->getOpVal($firstJmpOp['op1'], $EX)), ') {', PHP_EOL;
[789]842            echo $body;
[787]843            echo $indent, '}', PHP_EOL;
[789]844
[788]845            $this->endComplexBlock($EX);
[787]846            return;
847        }
848
[789]849        if (isset($firstJmpOp)
850         && $firstJmpOp['opcode'] == XC_FE_FETCH
851         && $firstJmpOp['jmpouts'][0] > $last
852         && $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts'])
853         && $lastOp['jmpouts'][0] == $firstJmp) {
854            $this->removeJmpInfo($EX, $firstJmp);
855            $this->removeJmpInfo($EX, $last);
856            $this->beginComplexBlock($EX);
857
858            ob_start();
859            $this->recognizeAndDecompileClosedBlocks($EX, $first, $last, $indent . INDENT);
860            $body = ob_get_clean();
861
862            $as = foldToCode($firstJmpOp['fe_as'], $EX);
863            if (isset($firstJmpOp['fe_key'])) {
864                $as = str($firstJmpOp['fe_key'], $EX) . ' => ' . str($as);
865            }
866
867            echo $indent, 'foreach (', str($firstJmpOp['fe_src'], $EX), " as $as) {", PHP_EOL;
868            echo $body;
869            echo $indent, '}', PHP_EOL;
870
871            $this->endComplexBlock($EX);
872            return;
873        }
874
[787]875        $this->decompileBasicBlock($EX, $first, $last, $indent);
876    }
877    // }}}
878    function recognizeAndDecompileClosedBlocks(&$EX, $first, $last, $indent) // {{{ decompile in a tree way
879    {
880        $opcodes = &$EX['opcodes'];
881
882        $i = $starti = $first;
883        while ($i <= $last) {
884            $op = $opcodes[$i];
885            if (!empty($op['jmpins']) || !empty($op['jmpouts'])) {
886                $blockFirst = $i;
887                $blockLast = -1;
888                $i = $blockFirst;
[790]889                // $this->dumpRange($EX, $i, $last, $indent);
[787]890                do {
[790]891                    $op = $opcodes[$i];
[787]892                    if (!empty($op['jmpins'])) {
893                        // care about jumping from blocks behind, not before
894                        foreach ($op['jmpins'] as $oplineNumber) {
895                            if ($oplineNumber <= $last && $blockLast < $oplineNumber) {
896                                $blockLast = $oplineNumber;
897                            }
898                        }
899                    }
900                    if (!empty($op['jmpouts'])) {
901                        $blockLast = max($blockLast, max($op['jmpouts']) - 1);
902                    }
903                    ++$i;
904                } while ($i <= $blockLast);
905                assert('$blockLast <= $last');
906
907                if ($blockLast >= $blockFirst) {
908                    if ($blockFirst > $starti) {
909                        $this->decompileBasicBlock($EX, $starti, $blockFirst - 1, $indent);
910                    }
911                    $this->decompileComplexBlock($EX, $blockFirst, $blockLast, $indent);
912                    $i = $starti = $blockLast + 1;
[790]913                    continue;
[787]914                }
915            }
916            ++$i;
917        }
918        if ($starti <= $last) {
919            $this->decompileBasicBlock($EX, $starti, $last, $indent);
920        }
921    }
922    // }}}
[731]923    function &dop_array($op_array, $indent = '') // {{{
924    {
[735]925        $op_array['opcodes'] = $this->fixOpcode($op_array['opcodes'], true, $indent == '' ? 1 : null);
[731]926        $opcodes = &$op_array['opcodes'];
[787]927        // {{{ build jmpins/jmpouts to op_array
[1]928        for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
929            $op = &$opcodes[$i];
930            $op['line'] = $i;
931            switch ($op['opcode']) {
[758]932            case XC_CONT:
933            case XC_BRK:
934                $op['jmpouts'] = array();
935                break;
936
[749]937            case XC_GOTO:
[787]938                $target = $op['op1']['var'];
939                $op['goto'] = $target;
940                $opcodes[$target]['gofrom'][] = $i;
941                break;
942
[1]943            case XC_JMP:
[716]944                $target = $op['op1']['var'];
[1]945                $op['jmpouts'] = array($target);
946                $opcodes[$target]['jmpins'][] = $i;
947                break;
948
949            case XC_JMPZNZ:
[716]950                $jmpz = $op['op2']['opline_num'];
[1]951                $jmpnz = $op['extended_value'];
952                $op['jmpouts'] = array($jmpz, $jmpnz);
953                $opcodes[$jmpz]['jmpins'][] = $i;
954                $opcodes[$jmpnz]['jmpins'][] = $i;
955                break;
956
957            case XC_JMPZ:
958            case XC_JMPNZ:
959            case XC_JMPZ_EX:
960            case XC_JMPNZ_EX:
[749]961            case XC_JMP_SET:
[1]962            // case XC_FE_RESET:
963            case XC_FE_FETCH:
964            // case XC_JMP_NO_CTOR:
[716]965                $target = $op['op2']['opline_num'];
[1]966                //if (!isset($target)) {
967                //  $this->dumpop($op, $EX);
968                //  var_dump($op); exit;
969                //}
970                $op['jmpouts'] = array($target);
971                $opcodes[$target]['jmpins'][] = $i;
972                break;
973
974            /*
975            case XC_RETURN:
976                $op['jmpouts'] = array();
977                break;
978            */
[790]979
980            case XC_SWITCH_FREE:
981                $op['jmpouts'] = array($i + 1);
982                $opcodes[$i + 1]['jmpins'][] = $i;
983                break;
984
985            case XC_CASE:
986                // just to link together
987                $op['jmpouts'] = array($i + 2);
988                $opcodes[$i + 2]['jmpins'][] = $i;
989                break;
[1]990            }
[787]991            /*
992            if (!empty($op['jmpouts']) || !empty($op['jmpins'])) {
993                echo $i, "\t", xcache_get_opcode($op['opcode']), PHP_EOL;
994            }
995            // */
[1]996        }
997        unset($op);
998        // }}}
999        // build semi-basic blocks
1000        $nextbbs = array();
1001        $starti = 0;
1002        for ($i = 1, $cnt = count($opcodes); $i < $cnt; $i ++) {
1003            if (isset($opcodes[$i]['jmpins'])
1004             || isset($opcodes[$i - 1]['jmpouts'])) {
1005                $nextbbs[$starti] = $i;
1006                $starti = $i;
1007            }
1008        }
1009        $nextbbs[$starti] = $cnt;
1010
1011        $EX = array();
1012        $EX['Ts'] = array();
1013        $EX['indent'] = $indent;
1014        $EX['nextbbs'] = $nextbbs;
1015        $EX['op_array'] = &$op_array;
1016        $EX['opcodes'] = &$opcodes;
1017        // func call
1018        $EX['object'] = null;
[720]1019        $EX['called_scope'] = null;
[1]1020        $EX['fbc'] = null;
1021        $EX['argstack'] = array();
1022        $EX['arg_types_stack'] = array();
1023        $EX['last'] = count($opcodes) - 1;
1024        $EX['silence'] = 0;
[780]1025        $EX['recvs'] = array();
1026        $EX['uses'] = array();
[1]1027
[790]1028        $first = 0;
1029        $last = count($opcodes) - 1;
1030
1031        /* dump whole array
1032        $this->dasmBasicBlock($EX, $first, $last);
1033        for ($i = $first; $i <= $last; ++$i) {
1034            echo $i, "\t", $this->dumpop($opcodes[$i], $EX);
1035        }
1036        // */
[787]1037        // decompile in a tree way
[790]1038        $this->recognizeAndDecompileClosedBlocks($EX, $first, $last, $EX['indent']);
[1]1039        return $EX;
1040    }
1041    // }}}
1042    function outputCode(&$EX, $opline, $last, $indent, $loop = false) // {{{
1043    {
1044        $op = &$EX['opcodes'][$opline];
1045        $next = $EX['nextbbs'][$opline];
1046
1047        $end = $next - 1;
1048        if ($end > $last) {
1049            $end = $last;
1050        }
1051
1052        if (isset($op['jmpins'])) {
1053            echo "\nline", $op['line'], ":\n";
1054        }
1055        else {
1056            // echo ";;;\n";
1057        }
1058        $this->dasmBasicBlock($EX, $opline, $end);
[787]1059        $this->outputPhp($EX, $opline, $end, $indent);
[1]1060        // jmpout op
1061        $op = &$EX['opcodes'][$end];
1062        $op1 = $op['op1'];
1063        $op2 = $op['op2'];
1064        $ext = $op['extended_value'];
1065        $line = $op['line'];
1066
1067        if (isset($EX['opcodes'][$next])) {
1068            if (isset($last) && $next > $last) {
1069                $next = null;
1070            }
1071        }
1072        else {
1073            $next = null;
1074        }
1075        /*
1076        if ($op['opcode'] == XC_JMPZ) {
[716]1077            $target = $op2['opline_num'];
[1]1078            if ($line + 1) {
1079                $nextblock = $EX['nextbbs'][$next];
1080                $jmpop = end($nextblock);
1081                if ($jmpop['opcode'] == XC_JMP) {
[716]1082                    $ifendline = $op2['opline_num'];
[1]1083                    if ($ifendline >= $line) {
1084                        $cond = $op['cond'];
1085                        echo "{$indent}if ($cond) {\n";
1086                        $this->outputCode($EX, $next, $last, INDENT . $indent);
1087                        echo "$indent}\n";
1088                        $this->outputCode($EX, $target, $last, $indent);
1089                        return;
1090                    }
1091                }
1092            }
1093        }
1094        */
1095        if (!isset($next)) {
1096            return;
1097        }
[758]1098        if (isset($op['jmpouts']) && isset($op['isjmp'])) {
[1]1099            if (isset($op['cond'])) {
[746]1100                echo "{$indent}check (" . str($op["cond"]) . ") {\n";
[1]1101                echo INDENT;
1102            }
[758]1103            switch ($op['opcode']) {
1104            case XC_CONT:
1105            case XC_BRK:
1106                break;
1107
1108            default:
1109                echo $indent;
1110                echo xcache_get_opcode($op['opcode']), ' line', $op['jmpouts'][0];
1111                if (isset($op['jmpouts'][1])) {
1112                    echo ', line', $op['jmpouts'][1];
1113                }
1114                echo ";";
1115                // echo ' // <- line', $op['line'];
1116                echo "\n";
[1]1117            }
1118            if (isset($op['cond'])) echo "$indent}\n";
1119        }
1120
1121        // proces JMPZ_EX/JMPNZ_EX for AND,OR
1122        $op = &$EX['opcodes'][$next];
1123        /*
1124        if (isset($op['jmpins'])) {
1125            foreach (array_reverse($op['jmpins']) as $fromline) {
1126                $fromop = $EX['opcodes'][$fromline];
1127                switch ($fromop['opcode']) {
1128                case XC_JMPZ_EX: $opstr = 'and'; break;
1129                case XC_JMPNZ_EX: $opstr = 'or'; break;
1130                case XC_JMPZNZ: var_dump($fromop); exit;
1131                default: continue 2;
1132                }
1133
[716]1134                $var = $fromop['result']['var'];
[1]1135                var_dump($EX['Ts'][$var]);
1136                $EX['Ts'][$var] = '(' . $fromop['and_or'] . " $opstr " . $EX['Ts'][$var] . ')';
1137            }
1138            #$this->outputCode($EX, $next, $last, $indent);
1139            #return;
1140        }
1141        */
1142        if (isset($op['cond_false'])) {
1143            // $this->dumpop($op, $EX);
1144            // any true comes here, so it's a "or"
[744]1145            $cond = implode(' and ', str($op['cond_false']));
[1]1146            // var_dump($op['cond'] = $cond);
1147            /*
1148            $rvalue = implode(' or ', $op['cond_true']) . ' or ' . $rvalue;
1149            unset($op['cond_true']);
1150            */
1151        }
1152
1153        if ($loop) {
1154            return array($next, $last);
1155        }
1156        $this->outputCode($EX, $next, $last, $indent);
1157    }
1158    // }}}
1159    function dasmBasicBlock(&$EX, $opline, $last) // {{{
1160    {
1161        $T = &$EX['Ts'];
1162        $opcodes = &$EX['opcodes'];
1163        $lastphpop = null;
1164
[787]1165        for ($i = $opline; $i <= $last; $i ++) {
[1]1166            // {{{ prepair
1167            $op = &$opcodes[$i];
1168            $opc = $op['opcode'];
1169            if ($opc == XC_NOP) {
[761]1170                $this->usedOps[$opc] = true;
[1]1171                continue;
1172            }
1173
1174            $op1 = $op['op1'];
1175            $op2 = $op['op2'];
1176            $res = $op['result'];
1177            $ext = $op['extended_value'];
1178
1179            $opname = xcache_get_opcode($opc);
1180
1181            if ($opname == 'UNDEF' || !isset($opname)) {
1182                echo 'UNDEF OP:';
1183                $this->dumpop($op, $EX);
1184                continue;
1185            }
[762]1186            // echo $i, ' '; $this->dumpop($op, $EX); //var_dump($op);
[1]1187
1188            $resvar = null;
[731]1189            if ((ZEND_ENGINE_2_4 ? ($res['op_type'] & EXT_TYPE_UNUSED) : ($res['EA.type'] & EXT_TYPE_UNUSED)) || $res['op_type'] == XC_IS_UNUSED) {
[1]1190                $istmpres = false;
1191            }
1192            else {
1193                $istmpres = true;
1194            }
1195            // }}}
1196            // echo $opname, "\n";
1197
1198            $call = array(&$this, $opname);
1199            if (is_callable($call)) {
[761]1200                $this->usedOps[$opc] = true;
[1]1201                $this->{$opname}($op, $EX);
1202            }
1203            else if (isset($this->binops[$opc])) { // {{{
[761]1204                $this->usedOps[$opc] = true;
[1]1205                $op1val = $this->getOpVal($op1, $EX, false);
1206                $op2val = $this->getOpVal($op2, $EX, false);
1207                $rvalue = new Decompiler_Binop($this, $op1val, $opc, $op2val);
1208                $resvar = $rvalue;
1209                // }}}
1210            }
1211            else if (isset($this->unaryops[$opc])) { // {{{
[761]1212                $this->usedOps[$opc] = true;
[1]1213                $op1val = $this->getOpVal($op1, $EX);
1214                $myop = $this->unaryops[$opc];
[757]1215                $rvalue = $myop . str($op1val);
[1]1216                $resvar = $rvalue;
1217                // }}}
1218            }
1219            else {
[761]1220                $covered = true;
[1]1221                switch ($opc) {
1222                case XC_NEW: // {{{
[720]1223                    array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
[716]1224                    $EX['object'] = (int) $res['var'];
[720]1225                    $EX['called_scope'] = null;
[749]1226                    $EX['fbc'] = 'new ' . unquoteName($this->getOpVal($op1, $EX), $EX);
[731]1227                    if (!ZEND_ENGINE_2) {
[1]1228                        $resvar = '$new object$';
1229                    }
1230                    break;
1231                    // }}}
[749]1232                case XC_THROW: // {{{
1233                    $resvar = 'throw ' . str($this->getOpVal($op1, $EX));
1234                    break;
1235                    // }}}
1236                case XC_CLONE: // {{{
1237                    $resvar = 'clone ' . str($this->getOpVal($op1, $EX));
1238                    break;
1239                    // }}}
1240                case XC_CATCH: // {{{
1241                    $resvar = 'catch (' . str($this->getOpVal($op1, $EX)) . ' ' . str($this->getOpVal($op2, $EX)) . ')';
1242                    break;
1243                    // }}}
1244                case XC_INSTANCEOF: // {{{
1245                    $resvar = str($this->getOpVal($op1, $EX)) . ' instanceof ' . str($this->getOpVal($op2, $EX));
1246                    break;
1247                    // }}}
[1]1248                case XC_FETCH_CLASS: // {{{
1249                    if ($op2['op_type'] == XC_IS_UNUSED) {
[731]1250                        switch (($ext & (defined('ZEND_FETCH_CLASS_MASK') ? ZEND_FETCH_CLASS_MASK : 0xFF))) {
[1]1251                        case ZEND_FETCH_CLASS_SELF:
1252                            $class = 'self';
1253                            break;
1254                        case ZEND_FETCH_CLASS_PARENT:
1255                            $class = 'parent';
[722]1256                            break;
1257                        case ZEND_FETCH_CLASS_STATIC:
1258                            $class = 'static';
1259                            break;
[1]1260                        }
[722]1261                        $istmpres = true;
[1]1262                    }
1263                    else {
[749]1264                        $class = $this->getOpVal($op2, $EX);
1265                        if (isset($op2['constant'])) {
[753]1266                            $class = $this->stripNamespace(unquoteName($class));
[1]1267                        }
1268                    }
1269                    $resvar = $class;
1270                    break;
1271                    // }}}
1272                case XC_FETCH_CONSTANT: // {{{
[749]1273                    if ($op1['op_type'] == XC_IS_UNUSED) {
[753]1274                        $resvar = $this->stripNamespace($op2['constant']);
[749]1275                        break;
1276                    }
1277
[1]1278                    if ($op1['op_type'] == XC_IS_CONST) {
[753]1279                        $resvar = $this->stripNamespace($op1['constant']);
[1]1280                    }
1281                    else {
[749]1282                        $resvar = $this->getOpVal($op1, $EX);
[1]1283                    }
[749]1284
1285                    $resvar = str($resvar) . '::' . unquoteName($this->getOpVal($op2, $EX));
[1]1286                    break;
1287                    // }}}
1288                    // {{{ case XC_FETCH_*
1289                case XC_FETCH_R:
1290                case XC_FETCH_W:
1291                case XC_FETCH_RW:
1292                case XC_FETCH_FUNC_ARG:
1293                case XC_FETCH_UNSET:
1294                case XC_FETCH_IS:
1295                case XC_UNSET_VAR:
1296                    $rvalue = $this->getOpVal($op1, $EX);
[731]1297                    if (defined('ZEND_FETCH_TYPE_MASK')) {
1298                        $fetchtype = ($ext & ZEND_FETCH_TYPE_MASK);
1299                    }
1300                    else {
1301                        $fetchtype = $op2[!ZEND_ENGINE_2 ? 'fetch_type' : 'EA.type'];
1302                    }
[1]1303                    switch ($fetchtype) {
1304                    case ZEND_FETCH_STATIC_MEMBER:
1305                        $class = $this->getOpVal($op2, $EX);
[749]1306                        $rvalue = str($class) . '::$' . unquoteName($rvalue, $EX);
[1]1307                        break;
1308                    default:
[749]1309                        $name = unquoteName($rvalue, $EX);
1310                        $globalname = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[" . str($rvalue) . "]";
[1]1311                        $rvalue = new Decompiler_Fetch($rvalue, $fetchtype, $globalname);
1312                        break;
1313                    }
1314                    if ($opc == XC_UNSET_VAR) {
[744]1315                        $op['php'] = "unset(" . str($rvalue, $EX) . ")";
[1]1316                        $lastphpop = &$op;
1317                    }
1318                    else if ($res['op_type'] != XC_IS_UNUSED) {
1319                        $resvar = $rvalue;
1320                    }
1321                    break;
1322                    // }}}
1323                    // {{{ case XC_FETCH_DIM_*
1324                case XC_FETCH_DIM_TMP_VAR:
1325                case XC_FETCH_DIM_R:
1326                case XC_FETCH_DIM_W:
1327                case XC_FETCH_DIM_RW:
1328                case XC_FETCH_DIM_FUNC_ARG:
1329                case XC_FETCH_DIM_UNSET:
1330                case XC_FETCH_DIM_IS:
1331                case XC_ASSIGN_DIM:
[749]1332                case XC_UNSET_DIM_OBJ: // PHP 4 only
[1]1333                case XC_UNSET_DIM:
[749]1334                case XC_UNSET_OBJ:
[1]1335                    $src = $this->getOpVal($op1, $EX, false);
1336                    if (is_a($src, "Decompiler_ForeachBox")) {
1337                        $src->iskey = $this->getOpVal($op2, $EX);
1338                        $resvar = $src;
1339                        break;
1340                    }
[749]1341
1342                    if (is_a($src, "Decompiler_DimBox")) {
[1]1343                        $dimbox = $src;
1344                    }
1345                    else {
1346                        if (!is_a($src, "Decompiler_ListBox")) {
[749]1347                            $op1val = $this->getOpVal($op1, $EX, false);
1348                            $list = new Decompiler_List(isset($op1val) ? $op1val : '$this');
[1]1349
1350                            $src = new Decompiler_ListBox($list);
[716]1351                            if (!isset($op1['var'])) {
[1]1352                                $this->dumpop($op, $EX);
1353                                var_dump($op);
[716]1354                                die('missing var');
[1]1355                            }
[716]1356                            $T[$op1['var']] = $src;
[1]1357                            unset($list);
1358                        }
1359                        $dim = new Decompiler_Dim($src);
1360                        $src->obj->dims[] = &$dim;
1361
1362                        $dimbox = new Decompiler_DimBox($dim);
1363                    }
1364                    $dim = &$dimbox->obj;
1365                    $dim->offsets[] = $this->getOpVal($op2, $EX);
1366                    if ($ext == ZEND_FETCH_ADD_LOCK) {
1367                        $src->obj->everLocked = true;
1368                    }
1369                    else if ($ext == ZEND_FETCH_STANDARD) {
1370                        $dim->isLast = true;
1371                    }
[749]1372                    if ($opc == XC_UNSET_OBJ) {
1373                        $dim->isObject = true;
1374                    }
[1]1375                    unset($dim);
1376                    $rvalue = $dimbox;
[749]1377                    unset($dimbox);
[1]1378
1379                    if ($opc == XC_ASSIGN_DIM) {
1380                        $lvalue = $rvalue;
1381                        ++ $i;
1382                        $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX);
[749]1383                        $resvar = str($lvalue, $EX) . ' = ' . str($rvalue);
[1]1384                    }
[749]1385                    else if ($opc == XC_UNSET_DIM || $opc == XC_UNSET_OBJ) {
[744]1386                        $op['php'] = "unset(" . str($rvalue, $EX) . ")";
[1]1387                        $lastphpop = &$op;
1388                    }
1389                    else if ($res['op_type'] != XC_IS_UNUSED) {
1390                        $resvar = $rvalue;
1391                    }
1392                    break;
1393                    // }}}
1394                case XC_ASSIGN: // {{{
1395                    $lvalue = $this->getOpVal($op1, $EX);
1396                    $rvalue = $this->getOpVal($op2, $EX, false);
1397                    if (is_a($rvalue, 'Decompiler_ForeachBox')) {
1398                        $type = $rvalue->iskey ? 'fe_key' : 'fe_as';
1399                        $rvalue->obj[$type] = $lvalue;
[716]1400                        unset($T[$op2['var']]);
[1]1401                        break;
1402                    }
1403                    if (is_a($rvalue, "Decompiler_DimBox")) {
1404                        $dim = &$rvalue->obj;
1405                        $dim->assign = $lvalue;
1406                        if ($dim->isLast) {
[744]1407                            $resvar = foldToCode($dim->value, $EX);
[1]1408                        }
1409                        unset($dim);
1410                        break;
1411                    }
[781]1412                    if (is_a($rvalue, 'Decompiler_Fetch')) {
1413                        $src = str($rvalue->src, $EX);
1414                        if ('$' . unquoteName($src) == $lvalue) {
1415                            switch ($rvalue->fetchType) {
1416                            case ZEND_FETCH_STATIC:
1417                                $statics = &$EX['op_array']['static_variables'];
1418                                if ((xcache_get_type($statics[$name]) & IS_LEXICAL_VAR)) {
1419                                    $EX['uses'][] = str($lvalue);
1420                                    unset($statics);
1421                                    break 2;
1422                                }
1423                                unset($statics);
1424                            }
1425                        }
1426                    }
[744]1427                    $resvar = "$lvalue = " . str($rvalue, $EX);
[1]1428                    break;
1429                    // }}}
1430                case XC_ASSIGN_REF: // {{{
1431                    $lvalue = $this->getOpVal($op1, $EX);
1432                    $rvalue = $this->getOpVal($op2, $EX, false);
1433                    if (is_a($rvalue, 'Decompiler_Fetch')) {
[749]1434                        $src = str($rvalue->src, $EX);
[754]1435                        if ('$' . unquoteName($src) == $lvalue) {
[1]1436                            switch ($rvalue->fetchType) {
1437                            case ZEND_FETCH_GLOBAL:
[731]1438                            case ZEND_FETCH_GLOBAL_LOCK:
[1]1439                                $resvar = 'global ' . $lvalue;
1440                                break 2;
1441                            case ZEND_FETCH_STATIC:
1442                                $statics = &$EX['op_array']['static_variables'];
[781]1443                                if ((xcache_get_type($statics[$name]) & IS_LEXICAL_REF)) {
1444                                    $EX['uses'][] = '&' . str($lvalue);
1445                                    unset($statics);
1446                                    break 2;
1447                                }
1448
[1]1449                                $resvar = 'static ' . $lvalue;
[754]1450                                $name = unquoteName($src);
[1]1451                                if (isset($statics[$name])) {
1452                                    $var = $statics[$name];
1453                                    $resvar .= ' = ';
[744]1454                                    $resvar .= str(value($var), $EX);
[1]1455                                }
1456                                unset($statics);
1457                                break 2;
[731]1458                            default:
[1]1459                            }
1460                        }
1461                    }
[731]1462                    // TODO: PHP_6 global
[754]1463                    $rvalue = str($rvalue, $EX);
[1]1464                    $resvar = "$lvalue = &$rvalue";
1465                    break;
1466                    // }}}
1467                // {{{ case XC_FETCH_OBJ_*
1468                case XC_FETCH_OBJ_R:
1469                case XC_FETCH_OBJ_W:
1470                case XC_FETCH_OBJ_RW:
1471                case XC_FETCH_OBJ_FUNC_ARG:
1472                case XC_FETCH_OBJ_UNSET:
1473                case XC_FETCH_OBJ_IS:
1474                case XC_ASSIGN_OBJ:
1475                    $obj = $this->getOpVal($op1, $EX);
1476                    if (!isset($obj)) {
1477                        $obj = '$this';
1478                    }
[761]1479                    $rvalue = str($obj) . "->" . unquoteVariableName($this->getOpVal($op2, $EX), $EX);
[1]1480                    if ($res['op_type'] != XC_IS_UNUSED) {
1481                        $resvar = $rvalue;
1482                    }
1483                    if ($opc == XC_ASSIGN_OBJ) {
1484                        ++ $i;
1485                        $lvalue = $rvalue;
1486                        $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX);
[749]1487                        $resvar = "$lvalue = " . str($rvalue);
[1]1488                    }
1489                    break;
1490                    // }}}
1491                case XC_ISSET_ISEMPTY_DIM_OBJ:
1492                case XC_ISSET_ISEMPTY_PROP_OBJ:
1493                case XC_ISSET_ISEMPTY:
1494                case XC_ISSET_ISEMPTY_VAR: // {{{
1495                    if ($opc == XC_ISSET_ISEMPTY_VAR) {
[777]1496                        $rvalue = $this->getOpVal($op1, $EX);
1497                        // for < PHP_5_3
1498                        if ($op1['op_type'] == XC_IS_CONST) {
1499                            $rvalue = '$' . unquoteVariableName($this->getOpVal($op1, $EX));
1500                        }
[716]1501                        if ($op2['EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
[1]1502                            $class = $this->getOpVal($op2, $EX);
1503                            $rvalue = $class . '::' . $rvalue;
1504                        }
1505                    }
1506                    else if ($opc == XC_ISSET_ISEMPTY) {
1507                        $rvalue = $this->getOpVal($op1, $EX);
1508                    }
1509                    else {
1510                        $container = $this->getOpVal($op1, $EX);
1511                        $dim = $this->getOpVal($op2, $EX);
[717]1512                        if ($opc == XC_ISSET_ISEMPTY_PROP_OBJ) {
[761]1513                            if (!isset($container)) {
1514                                $container = '$this';
[717]1515                            }
[761]1516                            $rvalue = $container . "->" . unquoteVariableName($dim);
[717]1517                        }
1518                        else {
[761]1519                            $rvalue = $container . '[' . str($dim) .']';
[717]1520                        }
[1]1521                    }
1522
[731]1523                    switch ((!ZEND_ENGINE_2 ? $op['op2']['var'] /* constant */ : $ext) & (ZEND_ISSET|ZEND_ISEMPTY)) {
[1]1524                    case ZEND_ISSET:
[775]1525                        $rvalue = "isset(" . str($rvalue) . ")";
[1]1526                        break;
1527                    case ZEND_ISEMPTY:
[775]1528                        $rvalue = "empty(" . str($rvalue) . ")";
[1]1529                        break;
1530                    }
1531                    $resvar = $rvalue;
1532                    break;
1533                    // }}}
1534                case XC_SEND_VAR_NO_REF:
1535                case XC_SEND_VAL:
1536                case XC_SEND_REF:
1537                case XC_SEND_VAR: // {{{
1538                    $ref = ($opc == XC_SEND_REF ? '&' : '');
[744]1539                    $EX['argstack'][] = $ref . str($this->getOpVal($op1, $EX));
[1]1540                    break;
1541                    // }}}
[720]1542                case XC_INIT_STATIC_METHOD_CALL:
[749]1543                case XC_INIT_METHOD_CALL: // {{{
[720]1544                    array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
[722]1545                    if ($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL || $op1['op_type'] != XC_IS_UNUSED) {
[1]1546                        $obj = $this->getOpVal($op1, $EX);
1547                        if (!isset($obj)) {
1548                            $obj = '$this';
1549                        }
[722]1550                        if ($opc == XC_INIT_STATIC_METHOD_CALL || /* PHP4 */ isset($op1['constant'])) {
[720]1551                            $EX['object'] = null;
[753]1552                            $EX['called_scope'] = $this->stripNamespace(unquoteName($obj, $EX));
[720]1553                        }
1554                        else {
1555                            $EX['object'] = $obj;
1556                            $EX['called_scope'] = null;
1557                        }
[1]1558                        if ($res['op_type'] != XC_IS_UNUSED) {
1559                            $resvar = '$obj call$';
1560                        }
1561                    }
1562                    else {
1563                        $EX['object'] = null;
[720]1564                        $EX['called_scope'] = null;
[1]1565                    }
1566
[749]1567                    $EX['fbc'] = $this->getOpVal($op2, $EX, false);
1568                    if (($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL) && !isset($EX['fbc'])) {
1569                        $EX['fbc'] = '__construct';
[1]1570                    }
[749]1571                    break;
1572                    // }}}
[753]1573                case XC_INIT_NS_FCALL_BY_NAME:
[749]1574                case XC_INIT_FCALL_BY_NAME: // {{{
[755]1575                    array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
[749]1576                    if (!ZEND_ENGINE_2 && ($ext & ZEND_CTOR_CALL)) {
1577                        break;
[1]1578                    }
[749]1579                    $EX['object'] = null;
1580                    $EX['called_scope'] = null;
1581                    $EX['fbc'] = $this->getOpVal($op2, $EX);
[1]1582                    break;
1583                    // }}}
[749]1584                case XC_INIT_FCALL_BY_FUNC: // {{{ deprecated even in PHP 4?
1585                    $EX['object'] = null;
1586                    $EX['called_scope'] = null;
1587                    $which = $op1['var'];
1588                    $EX['fbc'] = $EX['op_array']['funcs'][$which]['name'];
1589                    break;
1590                    // }}}
[1]1591                case XC_DO_FCALL_BY_FUNC:
[716]1592                    $which = $op1['var'];
[1]1593                    $fname = $EX['op_array']['funcs'][$which]['name'];
1594                    $args = $this->popargs($EX, $ext);
1595                    $resvar = $fname . "($args)";
1596                    break;
1597                case XC_DO_FCALL:
[749]1598                    $fname = unquoteName($this->getOpVal($op1, $EX, false), $EX);
[1]1599                    $args = $this->popargs($EX, $ext);
1600                    $resvar = $fname . "($args)";
1601                    break;
1602                case XC_DO_FCALL_BY_NAME: // {{{
1603                    $object = null;
1604
[749]1605                    $fname = unquoteName($EX['fbc'], $EX);
[1]1606                    if (!is_int($EX['object'])) {
1607                        $object = $EX['object'];
1608                    }
1609
1610                    $args = $this->popargs($EX, $ext);
1611
[753]1612                    $prefix = (isset($object) ? $object . '->' : '' )
1613                        . (isset($EX['called_scope']) ? $EX['called_scope'] . '::' : '' );
1614                    $resvar = $prefix
1615                        . (!$prefix ? $this->stripNamespace($fname) : $fname)
1616                        . "($args)";
[1]1617                    unset($args);
1618
1619                    if (is_int($EX['object'])) {
1620                        $T[$EX['object']] = $resvar;
1621                        $resvar = null;
1622                    }
[720]1623                    list($EX['fbc'], $EX['object'], $EX['called_scope']) = array_pop($EX['arg_types_stack']);
[1]1624                    break;
1625                    // }}}
1626                case XC_VERIFY_ABSTRACT_CLASS: // {{{
[716]1627                    //unset($T[$op1['var']]);
[1]1628                    break;
1629                    // }}}
1630                case XC_DECLARE_CLASS: 
[714]1631                case XC_DECLARE_INHERITED_CLASS:
1632                case XC_DECLARE_INHERITED_CLASS_DELAYED: // {{{
[716]1633                    $key = $op1['constant'];
[714]1634                    if (!isset($this->dc['class_table'][$key])) {
1635                        echo 'class not found: ', $key, 'existing classes are:', "\n";
1636                        var_dump(array_keys($this->dc['class_table']));
[1]1637                        exit;
1638                    }
[714]1639                    $class = &$this->dc['class_table'][$key];
[751]1640                    if (!isset($class['name'])) {
1641                        $class['name'] = unquoteName($this->getOpVal($op2, $EX), $EX);
1642                    }
[714]1643                    if ($opc == XC_DECLARE_INHERITED_CLASS || $opc == XC_DECLARE_INHERITED_CLASS_DELAYED) {
[1]1644                        $ext /= XC_SIZEOF_TEMP_VARIABLE;
1645                        $class['parent'] = $T[$ext];
1646                        unset($T[$ext]);
1647                    }
1648                    else {
1649                        $class['parent'] = null;
1650                    }
1651
[749]1652                    for (;;) {
[787]1653                        if ($i + 1 <= $last
[749]1654                         && $opcodes[$i + 1]['opcode'] == XC_ADD_INTERFACE
1655                         && $opcodes[$i + 1]['op1']['var'] == $res['var']) {
1656                            // continue
1657                        }
[787]1658                        else if ($i + 2 <= $last
[749]1659                         && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE
1660                         && $opcodes[$i + 2]['op1']['var'] == $res['var']
1661                         && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) {
1662                            // continue
1663                        }
1664                        else {
1665                            break;
1666                        }
[761]1667                        $this->usedOps[XC_ADD_INTERFACE] = true;
[749]1668
[1]1669                        $fetchop = &$opcodes[$i + 1];
[753]1670                        $interface = $this->stripNamespace(unquoteName($this->getOpVal($fetchop['op2'], $EX), $EX));
[1]1671                        $addop = &$opcodes[$i + 2];
[753]1672                        $class['interfaces'][$addop['extended_value']] = $interface;
[1]1673                        unset($fetchop, $addop);
1674                        $i += 2;
1675                    }
1676                    $this->dclass($class);
[749]1677                    echo "\n";
[1]1678                    unset($class);
1679                    break;
1680                    // }}}
1681                case XC_INIT_STRING: // {{{
1682                    $resvar = "''";
1683                    break;
1684                    // }}}
1685                case XC_ADD_CHAR:
1686                case XC_ADD_STRING:
1687                case XC_ADD_VAR: // {{{
1688                    $op1val = $this->getOpVal($op1, $EX);
1689                    $op2val = $this->getOpVal($op2, $EX);
1690                    switch ($opc) {
1691                    case XC_ADD_CHAR:
[749]1692                        $op2val = value(chr(str($op2val)));
[1]1693                        break;
1694                    case XC_ADD_STRING:
1695                        break;
1696                    case XC_ADD_VAR:
1697                        break;
1698                    }
[749]1699                    if (str($op1val) == "''") {
[1]1700                        $rvalue = $op2val;
1701                    }
[749]1702                    else if (str($op2val) == "''") {
[1]1703                        $rvalue = $op1val;
1704                    }
1705                    else {
[744]1706                        $rvalue = str($op1val) . ' . ' . str($op2val);
[1]1707                    }
1708                    $resvar = $rvalue;
1709                    // }}}
1710                    break;
1711                case XC_PRINT: // {{{
1712                    $op1val = $this->getOpVal($op1, $EX);
[761]1713                    $resvar = "print(" . str($op1val) . ")";
[1]1714                    break;
1715                    // }}}
1716                case XC_ECHO: // {{{
1717                    $op1val = $this->getOpVal($op1, $EX);
[744]1718                    $resvar = "echo " . str($op1val);
[1]1719                    break;
1720                    // }}}
1721                case XC_EXIT: // {{{
1722                    $op1val = $this->getOpVal($op1, $EX);
1723                    $resvar = "exit($op1val)";
1724                    break;
1725                    // }}}
1726                case XC_INIT_ARRAY:
1727                case XC_ADD_ARRAY_ELEMENT: // {{{
1728                    $rvalue = $this->getOpVal($op1, $EX, false, true);
1729
1730                    if ($opc == XC_ADD_ARRAY_ELEMENT) {
[737]1731                        $assoc = $this->getOpVal($op2, $EX);
1732                        if (isset($assoc)) {
1733                            $T[$res['var']]->value[] = array($assoc, $rvalue);
[1]1734                        }
1735                        else {
[737]1736                            $T[$res['var']]->value[] = array(null, $rvalue);
[1]1737                        }
1738                    }
1739                    else {
1740                        if ($opc == XC_INIT_ARRAY) {
1741                            $resvar = new Decompiler_Array();
1742                            if (!isset($rvalue)) {
1743                                continue;
1744                            }
1745                        }
1746
[737]1747                        $assoc = $this->getOpVal($op2, $EX);
1748                        if (isset($assoc)) {
1749                            $resvar->value[] = array($assoc, $rvalue);
[1]1750                        }
1751                        else {
[737]1752                            $resvar->value[] = array(null, $rvalue);
[1]1753                        }
1754                    }
1755                    break;
1756                    // }}}
1757                case XC_QM_ASSIGN: // {{{
1758                    $resvar = $this->getOpVal($op1, $EX);
1759                    break;
1760                    // }}}
1761                case XC_BOOL: // {{{
1762                    $resvar = /*'(bool) ' .*/ $this->getOpVal($op1, $EX);
1763                    break;
1764                    // }}}
1765                case XC_RETURN: // {{{
[744]1766                    $resvar = "return " . str($this->getOpVal($op1, $EX));
[1]1767                    break;
1768                    // }}}
1769                case XC_INCLUDE_OR_EVAL: // {{{
[716]1770                    $type = $op2['var']; // hack
[1]1771                    $keyword = $this->includeTypes[$type];
[749]1772                    $resvar = "$keyword " . str($this->getOpVal($op1, $EX));
[1]1773                    break;
1774                    // }}}
1775                case XC_FE_RESET: // {{{
1776                    $resvar = $this->getOpVal($op1, $EX);
1777                    break;
1778                    // }}}
1779                case XC_FE_FETCH: // {{{
1780                    $op['fe_src'] = $this->getOpVal($op1, $EX);
1781                    $fe = new Decompiler_ForeachBox($op);
1782                    $fe->iskey = false;
[716]1783                    $T[$res['var']] = $fe;
[1]1784
1785                    ++ $i;
1786                    if (($ext & ZEND_FE_FETCH_WITH_KEY)) {
1787                        $fe = new Decompiler_ForeachBox($op);
1788                        $fe->iskey = true;
1789
1790                        $res = $opcodes[$i]['result'];
[716]1791                        $T[$res['var']] = $fe;
[1]1792                    }
1793                    break;
1794                    // }}}
1795                case XC_SWITCH_FREE: // {{{
1796                    break;
1797                    // }}}
1798                case XC_FREE: // {{{
[716]1799                    $free = $T[$op1['var']];
[1]1800                    if (!is_a($free, 'Decompiler_Array') && !is_a($free, 'Decompiler_Box')) {
1801                        $op['php'] = is_object($free) ? $free : $this->unquote($free, '(', ')');
1802                        $lastphpop = &$op;
1803                    }
[716]1804                    unset($T[$op1['var']], $free);
[1]1805                    break;
1806                    // }}}
1807                case XC_JMP_NO_CTOR:
1808                    break;
[749]1809                case XC_JMP_SET: // ?:
[760]1810                    $resvar = $this->getOpVal($op1, $EX);
1811                    $op['cond'] = $resvar; 
1812                    $op['isjmp'] = true;
1813                    break;
[1]1814                case XC_JMPNZ: // while
1815                case XC_JMPZNZ: // for
1816                case XC_JMPZ_EX: // and
1817                case XC_JMPNZ_EX: // or
1818                case XC_JMPZ: // {{{
1819                    if ($opc == XC_JMP_NO_CTOR && $EX['object']) {
1820                        $rvalue = $EX['object'];
1821                    }
1822                    else {
1823                        $rvalue = $this->getOpVal($op1, $EX);
1824                    }
1825
1826                    if (isset($op['cond_true'])) {
1827                        // any true comes here, so it's a "or"
1828                        $rvalue = implode(' or ', $op['cond_true']) . ' or ' . $rvalue;
1829                        unset($op['cond_true']);
1830                    }
1831                    if (isset($op['cond_false'])) {
[723]1832                        echo "TODO(cond_false):\n";
[1]1833                        var_dump($op);// exit;
1834                    }
[760]1835                    if ($opc == XC_JMPZ_EX || $opc == XC_JMPNZ_EX) {
[716]1836                        $targetop = &$EX['opcodes'][$op2['opline_num']];
[1]1837                        if ($opc == XC_JMPNZ_EX) {
[744]1838                            $targetop['cond_true'][] = foldToCode($rvalue, $EX);
[1]1839                        }
1840                        else {
[744]1841                            $targetop['cond_false'][] = foldToCode($rvalue, $EX);
[1]1842                        }
1843                        unset($targetop);
1844                    }
1845                    else {
1846                        $op['cond'] = $rvalue; 
1847                        $op['isjmp'] = true;
1848                    }
1849                    break;
1850                    // }}}
[758]1851                case XC_CONT:
1852                case XC_BRK:
1853                    $op['cond'] = null;
1854                    $op['isjmp'] = true;
1855                    $resvar = $opc == XC_CONT ? 'continue' : 'break';
1856                    $count = str($this->getOpVal($op2, $EX));
1857                    if ($count != '1') {
1858                        $resvar .= ' ' . $count;
1859                    }
1860                    break;
[749]1861                case XC_GOTO:
[787]1862                    $resvar = 'goto label' . $op['op1']['var'];
1863                    $istmpres = false;
1864                    break;
1865
[1]1866                case XC_JMP: // {{{
1867                    $op['cond'] = null;
1868                    $op['isjmp'] = true;
1869                    break;
1870                    // }}}
1871                case XC_CASE:
[790]1872                    // $switchValue = $this->getOpVal($op1, $EX);
[743]1873                    $caseValue = $this->getOpVal($op2, $EX);
[790]1874                    $resvar = $caseValue;
[743]1875                    break;
[1]1876                case XC_RECV_INIT:
1877                case XC_RECV:
1878                    $offset = $this->getOpVal($op1, $EX);
1879                    $lvalue = $this->getOpVal($op['result'], $EX);
1880                    if ($opc == XC_RECV_INIT) {
[716]1881                        $default = value($op['op2']['constant']);
[1]1882                    }
1883                    else {
1884                        $default = null;
1885                    }
[737]1886                    $EX['recvs'][str($offset)] = array($lvalue, $default);
[1]1887                    break;
1888                case XC_POST_DEC:
1889                case XC_POST_INC:
1890                case XC_POST_DEC_OBJ:
1891                case XC_POST_INC_OBJ:
1892                case XC_PRE_DEC:
1893                case XC_PRE_INC:
1894                case XC_PRE_DEC_OBJ:
1895                case XC_PRE_INC_OBJ: // {{{
1896                    $flags = array_flip(explode('_', $opname));
1897                    if (isset($flags['OBJ'])) {
[761]1898                        $resvar = $this->getOpVal($op1, $EX) . '->' . unquoteVariableName($this->getOpVal($op2, $EX), $EX);
[1]1899                    }
1900                    else {
1901                        $resvar = $this->getOpVal($op1, $EX);
1902                    }
1903                    $opstr = isset($flags['DEC']) ? '--' : '++';
1904                    if (isset($flags['POST'])) {
[749]1905                        $resvar .= $opstr;
[1]1906                    }
1907                    else {
[749]1908                        $resvar = "$opstr$resvar";
[1]1909                    }
1910                    break;
1911                    // }}}
1912
1913                case XC_BEGIN_SILENCE: // {{{
1914                    $EX['silence'] ++;
1915                    break;
1916                    // }}}
1917                case XC_END_SILENCE: // {{{
1918                    $EX['silence'] --;
[744]1919                    $lastresvar = '@' . str($lastresvar, $EX);
[1]1920                    break;
1921                    // }}}
1922                case XC_CAST: // {{{
1923                    $type = $ext;
1924                    static $type2cast = array(
1925                            IS_LONG   => '(int)',
1926                            IS_DOUBLE => '(double)',
1927                            IS_STRING => '(string)',
1928                            IS_ARRAY  => '(array)',
1929                            IS_OBJECT => '(object)',
1930                            IS_BOOL   => '(bool)',
1931                            IS_NULL   => '(unset)',
1932                            );
1933                    assert(isset($type2cast[$type]));
1934                    $cast = $type2cast[$type];
1935                    $resvar = $cast . ' ' . $this->getOpVal($op1, $EX);
1936                    break;
1937                    // }}}
1938                case XC_EXT_STMT:
1939                case XC_EXT_FCALL_BEGIN:
1940                case XC_EXT_FCALL_END:
1941                case XC_EXT_NOP:
1942                    break;
[751]1943                case XC_DECLARE_FUNCTION:
1944                    $this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']);
1945                    break;
[752]1946                case XC_DECLARE_LAMBDA_FUNCTION: // {{{
[749]1947                    ob_start();
1948                    $this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']);
1949                    $resvar = ob_get_clean();
1950                    $istmpres = true;
1951                    break;
[752]1952                    // }}}
1953                case XC_DECLARE_CONST:
[753]1954                    $name = $this->stripNamespace(unquoteName($this->getOpVal($op1, $EX), $EX));
1955                    $value = str($this->getOpVal($op2, $EX));
1956                    $resvar = 'const ' . $name . ' = ' . $value;
[752]1957                    break;
[1]1958                case XC_DECLARE_FUNCTION_OR_CLASS:
1959                    /* always removed by compiler */
1960                    break;
1961                case XC_TICKS:
1962                    $lastphpop['ticks'] = $this->getOpVal($op1, $EX);
1963                    // $EX['tickschanged'] = true;
1964                    break;
[749]1965                case XC_RAISE_ABSTRACT_ERROR:
1966                    // abstract function body is empty, don't need this code
1967                    break;
1968                case XC_USER_OPCODE:
1969                    echo '// ZEND_USER_OPCODE, impossible to decompile';
1970                    break;
1971                case XC_OP_DATA:
1972                    break;
[1]1973                default: // {{{
1974                    echo "\x1B[31m * TODO ", $opname, "\x1B[0m\n";
[761]1975                    $covered = false;
[1]1976                    // }}}
1977                }
[761]1978                if ($covered) {
1979                    $this->usedOps[$opc] = true;
1980                }
[1]1981            }
1982            if (isset($resvar)) {
1983                if ($istmpres) {
[716]1984                    $T[$res['var']] = $resvar;
1985                    $lastresvar = &$T[$res['var']];
[1]1986                }
1987                else {
1988                    $op['php'] = $resvar;
1989                    $lastphpop = &$op;
1990                    $lastresvar = &$op['php'];
1991                }
1992            }
1993        }
1994        return $T;
1995    }
1996    // }}}
1997    function unquote($str, $st, $ed) // {{{
1998    {
1999        $l1 = strlen($st);
2000        $l2 = strlen($ed);
2001        if (substr($str, 0, $l1) === $st && substr($str, -$l2) === $ed) {
2002            $str = substr($str, $l1, -$l2);
2003        }
2004        return $str;
2005    }
2006    // }}}
2007    function popargs(&$EX, $n) // {{{
2008    {
2009        $args = array();
2010        for ($i = 0; $i < $n; $i ++) {
2011            $a = array_pop($EX['argstack']);
2012            if (is_array($a)) {
[744]2013                array_unshift($args, foldToCode($a, $EX));
[1]2014            }
2015            else {
2016                array_unshift($args, $a);
2017            }
2018        }
2019        return implode(', ', $args);
2020    }
2021    // }}}
2022    function dumpop($op, &$EX) // {{{
2023    {
2024        $op1 = $op['op1'];
2025        $op2 = $op['op2'];
[763]2026        $d = array(xcache_get_opcode($op['opcode']), $op['opcode']);
[1]2027
[762]2028        foreach (array('op1' => '1:', 'op2' => '2:', 'result' => '>') as $k => $kk) {
[1]2029            switch ($op[$k]['op_type']) {
2030            case XC_IS_UNUSED:
[762]2031                $d[$kk] = 'U:' . $op[$k]['opline_num'];
[1]2032                break;
2033
2034            case XC_IS_VAR:
[716]2035                $d[$kk] = '$' . $op[$k]['var'];
[762]2036                if ($k != 'result') {
[749]2037                    $d[$kk] .= ':' . str($this->getOpVal($op[$k], $EX));
[1]2038                }
2039                break;
2040
2041            case XC_IS_TMP_VAR:
[716]2042                $d[$kk] = '#' . $op[$k]['var'];
[762]2043                if ($k != 'result') {
[749]2044                    $d[$kk] .= ':' . str($this->getOpVal($op[$k], $EX));
[1]2045                }
2046                break;
2047
2048            case XC_IS_CV:
2049                $d[$kk] = $this->getOpVal($op[$k], $EX);
2050                break;
2051
2052            default:
[762]2053                if ($k == 'result') {
[731]2054                    var_dump($op);
2055                    exit;
[1]2056                    assert(0);
2057                }
2058                else {
2059                    $d[$kk] = $this->getOpVal($op[$k], $EX);
2060                }
2061            }
2062        }
[762]2063        $d[';'] = $op['extended_value'];
[1]2064
[762]2065        foreach ($d as $k => $v) {
[763]2066            echo is_int($k) ? '' : $k, str($v), "\t";
[762]2067        }
2068        echo PHP_EOL;
[1]2069    }
2070    // }}}
[790]2071    function dumpRange(&$EX, $first, $last, $indent = '') // {{{
[787]2072    {
2073        for ($i = $first; $i <= $last; ++$i) {
[790]2074            echo $indent, $i, "\t"; $this->dumpop($EX['opcodes'][$i], $EX);
[787]2075        }
[790]2076        echo $indent, "==", PHP_EOL;
[787]2077    }
2078    // }}}
[1]2079    function dargs(&$EX, $indent) // {{{
2080    {
2081        $op_array = &$EX['op_array'];
2082
2083        if (isset($op_array['num_args'])) {
2084            $c = $op_array['num_args'];
2085        }
2086        else if ($op_array['arg_types']) {
2087            $c = count($op_array['arg_types']);
2088        }
2089        else {
2090            // php4
2091            $c = count($EX['recvs']);
2092        }
2093
2094        $refrest = false;
2095        for ($i = 0; $i < $c; $i ++) {
2096            if ($i) {
2097                echo ', ';
2098            }
[736]2099            $arg = $EX['recvs'][$i + 1];
[1]2100            if (isset($op_array['arg_info'])) {
2101                $ai = $op_array['arg_info'][$i];
2102                if (!empty($ai['class_name'])) {
[753]2103                    echo $this->stripNamespace($ai['class_name']), ' ';
[736]2104                    if (!ZEND_ENGINE_2_2 && $ai['allow_null']) {
[1]2105                        echo 'or NULL ';
2106                    }
2107                }
2108                else if (!empty($ai['array_type_hint'])) {
2109                    echo 'array ';
[736]2110                    if (!ZEND_ENGINE_2_2 && $ai['allow_null']) {
[1]2111                        echo 'or NULL ';
2112                    }
2113                }
2114                if ($ai['pass_by_reference']) {
2115                    echo '&';
2116                }
2117                printf("\$%s", $ai['name']);
2118            }
2119            else {
2120                if ($refrest) {
2121                    echo '&';
2122                }
2123                else if (isset($op_array['arg_types'][$i])) {
2124                    switch ($op_array['arg_types'][$i]) {
2125                    case BYREF_FORCE_REST:
2126                        $refrest = true;
2127                        /* fall */
2128                    case BYREF_FORCE:
2129                        echo '&';
2130                        break;
2131
2132                    case BYREF_NONE:
2133                    case BYREF_ALLOW:
2134                        break;
2135                    default:
2136                        assert(0);
2137                    }
2138                }
[744]2139                echo str($arg[0], $indent);
[1]2140            }
[736]2141            if (isset($arg[1])) {
[744]2142                echo ' = ', str($arg[1], $indent);
[736]2143            }
[1]2144        }
2145    }
2146    // }}}
[780]2147    function duses(&$EX, $indent) // {{{
2148    {
[781]2149        if ($EX['uses']) {
2150            echo ' use(', implode(', ', $EX['uses']), ')';
[780]2151        }
2152    }
2153    // }}}
[1]2154    function dfunction($func, $indent = '', $nobody = false) // {{{
2155    {
[753]2156        $this->detectNamespace($func['op_array']['function_name']);
2157
[1]2158        if ($nobody) {
2159            $EX = array();
2160            $EX['op_array'] = &$func['op_array'];
2161            $EX['recvs'] = array();
[780]2162            $EX['uses'] = array();
[1]2163        }
2164        else {
2165            ob_start();
2166            $newindent = INDENT . $indent;
2167            $EX = &$this->dop_array($func['op_array'], $newindent);
2168            $body = ob_get_clean();
2169        }
2170
[753]2171        $functionName = $this->stripNamespace($func['op_array']['function_name']);
[749]2172        if ($functionName == '{closure}') {
2173            $functionName = '';
2174        }
[781]2175        echo 'function', $functionName ? ' ' . $functionName : '', '(';
[1]2176        $this->dargs($EX, $indent);
[749]2177        echo ")";
[780]2178        $this->duses($EX, $indent);
[749]2179        if ($nobody) {
2180            echo ";\n";
2181        }
2182        else {
2183            if ($functionName !== '') {
2184                echo "\n";
2185                echo $indent, "{\n";
2186            }
2187            else {
2188                echo " {\n";
2189            }
2190
2191            echo $body;
2192            echo "$indent}";
2193            if ($functionName !== '') {
2194                echo "\n";
2195            }
2196        }
[1]2197    }
2198    // }}}
2199    function dclass($class, $indent = '') // {{{
2200    {
[753]2201        $this->detectNamespace($class['name']);
2202
[1]2203        // {{{ class decl
2204        if (!empty($class['doc_comment'])) {
2205            echo $indent;
2206            echo $class['doc_comment'];
2207            echo "\n";
2208        }
2209        $isinterface = false;
2210        if (!empty($class['ce_flags'])) {
2211            if ($class['ce_flags'] & ZEND_ACC_INTERFACE) {
2212                $isinterface = true;
2213            }
2214            else {
[749]2215                if ($class['ce_flags'] & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
[1]2216                    echo "abstract ";
2217                }
[749]2218                if ($class['ce_flags'] & ZEND_ACC_FINAL_CLASS) {
[1]2219                    echo "final ";
2220                }
2221            }
2222        }
[753]2223        echo $isinterface ? 'interface ' : 'class ', $this->stripNamespace($class['name']);
[1]2224        if ($class['parent']) {
2225            echo ' extends ', $class['parent'];
2226        }
2227        /* TODO */
2228        if (!empty($class['interfaces'])) {
2229            echo ' implements ';
2230            echo implode(', ', $class['interfaces']);
2231        }
2232        echo "\n";
2233        echo $indent, "{";
2234        // }}}
2235        $newindent = INDENT . $indent;
2236        // {{{ const, static
2237        foreach (array('constants_table' => 'const '
2238                    , 'static_members' => 'static $') as $type => $prefix) {
2239            if (!empty($class[$type])) {
2240                echo "\n";
2241                // TODO: skip shadow?
2242                foreach ($class[$type] as $name => $v) {
2243                    echo $newindent;
2244                    echo $prefix, $name, ' = ';
[744]2245                    echo str(value($v), $newindent);
[1]2246                    echo ";\n";
2247                }
2248            }
2249        }
2250        // }}}
2251        // {{{ properties
[730]2252        $member_variables = isset($class['properties_info']) ? $class['properties_info'] : ($class['default_static_members'] + $class['default_properties']);
2253        if ($member_variables) {
[1]2254            echo "\n";
[713]2255            $infos = !empty($class['properties_info']) ? $class['properties_info'] : null;
[730]2256            foreach ($member_variables as $name => $dummy) {
[1]2257                $info = (isset($infos) && isset($infos[$name])) ? $infos[$name] : null;
2258                if (isset($info)) {
2259                    if (!empty($info['doc_comment'])) {
2260                        echo $newindent;
2261                        echo $info['doc_comment'];
2262                        echo "\n";
2263                    }
2264                }
2265
2266                echo $newindent;
[713]2267                $static = false;
2268                if (isset($info)) {
2269                    if ($info['flags'] & ZEND_ACC_STATIC) {
2270                        $static = true;
2271                    }
2272                }
2273                else if (isset($class['default_static_members'][$name])) {
2274                    $static = true;
2275                }
2276
2277                if ($static) {
2278                    echo "static ";
2279                }
2280
2281                $mangled = false;
[731]2282                if (!ZEND_ENGINE_2) {
[1]2283                    echo 'var ';
2284                }
2285                else if (!isset($info)) {
2286                    echo 'public ';
2287                }
2288                else {
2289                    if ($info['flags'] & ZEND_ACC_SHADOW) {
2290                        continue;
2291                    }
2292                    switch ($info['flags'] & ZEND_ACC_PPP_MASK) {
2293                    case ZEND_ACC_PUBLIC:
2294                        echo "public ";
2295                        break;
2296                    case ZEND_ACC_PRIVATE:
2297                        echo "private ";
[713]2298                        $mangled = true;
[1]2299                        break;
2300                    case ZEND_ACC_PROTECTED:
2301                        echo "protected ";
[713]2302                        $mangled = true;
[1]2303                        break;
2304                    }
2305                }
2306
2307                echo '$', $name;
[713]2308
[730]2309                if (isset($info['offset'])) {
2310                    $value = $class[$static ? 'default_static_members_table' : 'default_properties_table'][$info['offset']];
2311                }
2312                else {
2313                    $key = isset($info) ? $info['name'] . ($mangled ? "\000" : "") : $name;
[713]2314
[730]2315                    $value = $class[$static ? 'default_static_members' : 'default_properties'][$key];
2316                }
[713]2317                if (isset($value)) {
[1]2318                    echo ' = ';
[744]2319                    echo str(value($value), $newindent);
[1]2320                }
2321                echo ";\n";
2322            }
2323        }
2324        // }}}
2325        // {{{ function_table
2326        if (isset($class['function_table'])) {
2327            foreach ($class['function_table'] as $func) {
2328                if (!isset($func['scope']) || $func['scope'] == $class['name']) {
2329                    // TODO: skip shadow here
2330                    echo "\n";
2331                    $opa = $func['op_array'];
2332                    if (!empty($opa['doc_comment'])) {
2333                        echo $newindent;
2334                        echo $opa['doc_comment'];
2335                        echo "\n";
2336                    }
2337                    echo $newindent;
[749]2338                    $isAbstractMethod = false;
[1]2339                    if (isset($opa['fn_flags'])) {
[749]2340                        if (($opa['fn_flags'] & ZEND_ACC_ABSTRACT) && !$isinterface) {
[1]2341                            echo "abstract ";
[749]2342                            $isAbstractMethod = true;
[1]2343                        }
2344                        if ($opa['fn_flags'] & ZEND_ACC_FINAL) {
2345                            echo "final ";
2346                        }
2347                        if ($opa['fn_flags'] & ZEND_ACC_STATIC) {
2348                            echo "static ";
2349                        }
2350
2351                        switch ($opa['fn_flags'] & ZEND_ACC_PPP_MASK) {
2352                            case ZEND_ACC_PUBLIC:
2353                                echo "public ";
2354                                break;
2355                            case ZEND_ACC_PRIVATE:
2356                                echo "private ";
2357                                break;
2358                            case ZEND_ACC_PROTECTED:
2359                                echo "protected ";
2360                                break;
2361                            default:
2362                                echo "<visibility error> ";
2363                                break;
2364                        }
2365                    }
[749]2366                    $this->dfunction($func, $newindent, $isinterface || $isAbstractMethod);
[1]2367                    if ($opa['function_name'] == 'Decompiler') {
2368                        //exit;
2369                    }
2370                }
2371            }
2372        }
2373        // }}}
2374        echo $indent, "}\n";
2375    }
2376    // }}}
2377    function decompileString($string) // {{{
2378    {
2379        $this->dc = xcache_dasm_string($string);
2380        if ($this->dc === false) {
2381            echo "error compling string\n";
2382            return false;
2383        }
2384    }
2385    // }}}
2386    function decompileFile($file) // {{{
2387    {
2388        $this->dc = xcache_dasm_file($file);
2389        if ($this->dc === false) {
2390            echo "error compling $file\n";
2391            return false;
2392        }
2393    }
2394    // }}}
2395    function output() // {{{
2396    {
[749]2397        echo "<?". "php\n\n";
[1]2398        foreach ($this->dc['class_table'] as $key => $class) {
2399            if ($key{0} != "\0") {
[749]2400                $this->dclass($class);
[1]2401                echo "\n";
2402            }
2403        }
2404
2405        foreach ($this->dc['function_table'] as $key => $func) {
2406            if ($key{0} != "\0") {
[749]2407                $this->dfunction($func);
[1]2408                echo "\n";
2409            }
2410        }
2411
2412        $this->dop_array($this->dc['op_array']);
2413        echo "\n?" . ">\n";
[761]2414
2415        if (!empty($this->test)) {
2416            $this->outputUnusedOp();
2417        }
[1]2418        return true;
2419    }
2420    // }}}
[761]2421    function outputUnusedOp() // {{{
2422    {
2423        for ($i = 0; $opname = xcache_get_opcode($i); $i ++) {
2424            if ($opname == 'UNDEF')  {
2425                continue;
2426            }
2427
2428            if (!isset($this->usedOps[$i])) {
2429                echo "not covered opcode ", $opname, "\n";
2430            }
2431        }
2432    }
2433    // }}}
[1]2434}
2435
2436// {{{ defines
[749]2437define('ZEND_ENGINE_2_4', PHP_VERSION >= "5.3.99");
2438define('ZEND_ENGINE_2_3', ZEND_ENGINE_2_4 || PHP_VERSION >= "5.3.");
2439define('ZEND_ENGINE_2_2', ZEND_ENGINE_2_3 || PHP_VERSION >= "5.2.");
2440define('ZEND_ENGINE_2_1', ZEND_ENGINE_2_2 || PHP_VERSION >= "5.1.");
2441define('ZEND_ENGINE_2',   ZEND_ENGINE_2_1 || PHP_VERSION >= "5.0.");
2442
[1]2443define('ZEND_ACC_STATIC',         0x01);
2444define('ZEND_ACC_ABSTRACT',       0x02);
2445define('ZEND_ACC_FINAL',          0x04);
2446define('ZEND_ACC_IMPLEMENTED_ABSTRACT',       0x08);
2447
2448define('ZEND_ACC_IMPLICIT_ABSTRACT_CLASS',    0x10);
2449define('ZEND_ACC_EXPLICIT_ABSTRACT_CLASS',    0x20);
2450define('ZEND_ACC_FINAL_CLASS',                0x40);
2451define('ZEND_ACC_INTERFACE',                  0x80);
[749]2452if (ZEND_ENGINE_2_4) {
2453    define('ZEND_ACC_TRAIT',                  0x120);
2454}
[1]2455define('ZEND_ACC_PUBLIC',     0x100);
2456define('ZEND_ACC_PROTECTED',  0x200);
2457define('ZEND_ACC_PRIVATE',    0x400);
2458define('ZEND_ACC_PPP_MASK',  (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE));
2459
2460define('ZEND_ACC_CHANGED',    0x800);
2461define('ZEND_ACC_IMPLICIT_PUBLIC',    0x1000);
2462
2463define('ZEND_ACC_CTOR',       0x2000);
2464define('ZEND_ACC_DTOR',       0x4000);
2465define('ZEND_ACC_CLONE',      0x8000);
2466
2467define('ZEND_ACC_ALLOW_STATIC',   0x10000);
2468
2469define('ZEND_ACC_SHADOW', 0x2000);
2470
[731]2471if (ZEND_ENGINE_2_4) {
2472    define('ZEND_FETCH_GLOBAL',           0x00000000);
2473    define('ZEND_FETCH_LOCAL',            0x10000000);
2474    define('ZEND_FETCH_STATIC',           0x20000000);
2475    define('ZEND_FETCH_STATIC_MEMBER',    0x30000000);
2476    define('ZEND_FETCH_GLOBAL_LOCK',      0x40000000);
2477    define('ZEND_FETCH_LEXICAL',          0x50000000);
2478
2479    define('ZEND_FETCH_TYPE_MASK',        0x70000000);
2480}
2481else {
2482    define('ZEND_FETCH_GLOBAL',           0);
2483    define('ZEND_FETCH_LOCAL',            1);
2484    define('ZEND_FETCH_STATIC',           2);
2485    define('ZEND_FETCH_STATIC_MEMBER',    3);
2486    define('ZEND_FETCH_GLOBAL_LOCK',      4);
2487}
2488
[1]2489define('ZEND_FETCH_CLASS_DEFAULT',    0);
2490define('ZEND_FETCH_CLASS_SELF',       1);
2491define('ZEND_FETCH_CLASS_PARENT',     2);
2492define('ZEND_FETCH_CLASS_MAIN',       3);
2493define('ZEND_FETCH_CLASS_GLOBAL',     4);
2494define('ZEND_FETCH_CLASS_AUTO',       5);
2495define('ZEND_FETCH_CLASS_INTERFACE',  6);
[722]2496define('ZEND_FETCH_CLASS_STATIC',     7);
[731]2497if (ZEND_ENGINE_2_4) {
2498    define('ZEND_FETCH_CLASS_TRAIT',     14);
2499}
2500if (ZEND_ENGINE_2_3) {
2501    define('ZEND_FETCH_CLASS_MASK',     0xF);
2502}
[1]2503
2504define('ZEND_EVAL',               (1<<0));
2505define('ZEND_INCLUDE',            (1<<1));
2506define('ZEND_INCLUDE_ONCE',       (1<<2));
2507define('ZEND_REQUIRE',            (1<<3));
2508define('ZEND_REQUIRE_ONCE',       (1<<4));
2509
2510define('ZEND_ISSET',              (1<<0));
2511define('ZEND_ISEMPTY',            (1<<1));
[731]2512if (ZEND_ENGINE_2_4) {
2513    define('EXT_TYPE_UNUSED',     (1<<5));
2514}
2515else {
2516    define('EXT_TYPE_UNUSED',     (1<<0));
2517}
[1]2518
2519define('ZEND_FETCH_STANDARD',     0);
2520define('ZEND_FETCH_ADD_LOCK',     1);
2521
2522define('ZEND_FE_FETCH_BYREF',     1);
2523define('ZEND_FE_FETCH_WITH_KEY',  2);
2524
2525define('ZEND_MEMBER_FUNC_CALL',   1<<0);
2526define('ZEND_CTOR_CALL',          1<<1);
2527
2528define('ZEND_ARG_SEND_BY_REF',        (1<<0));
2529define('ZEND_ARG_COMPILE_TIME_BOUND', (1<<1));
2530define('ZEND_ARG_SEND_FUNCTION',      (1<<2));
2531
2532define('BYREF_NONE',       0);
2533define('BYREF_FORCE',      1);
2534define('BYREF_ALLOW',      2);
2535define('BYREF_FORCE_REST', 3);
2536define('IS_NULL',     0);
2537define('IS_LONG',     1);
2538define('IS_DOUBLE',   2);
[761]2539define('IS_BOOL',     ZEND_ENGINE_2 ? 3 : 6);
[1]2540define('IS_ARRAY',    4);
2541define('IS_OBJECT',   5);
[761]2542define('IS_STRING',   ZEND_ENGINE_2 ? 6 : 3);
[1]2543define('IS_RESOURCE', 7);
2544define('IS_CONSTANT', 8);
2545define('IS_CONSTANT_ARRAY',   9);
[781]2546/* Ugly hack to support constants as static array indices */
2547define('IS_CONSTANT_TYPE_MASK',   0x0f);
2548define('IS_CONSTANT_UNQUALIFIED', 0x10);
2549define('IS_CONSTANT_INDEX',       0x80);
2550define('IS_LEXICAL_VAR',          0x20);
2551define('IS_LEXICAL_REF',          0x40);
[1]2552
2553@define('XC_IS_CV', 16);
2554
2555/*
2556if (preg_match_all('!XC_[A-Z_]+!', file_get_contents(__FILE__), $ms)) {
2557    $verdiff = array();
2558    foreach ($ms[0] as $k) {
2559        if (!defined($k)) {
2560            $verdiff[$k] = -1;
2561            define($k, -1);
2562        }
2563    }
2564    var_export($verdiff);
2565}
2566/*/
2567foreach (array (
2568    'XC_HANDLE_EXCEPTION' => -1,
2569    'XC_FETCH_CLASS' => -1,
2570    'XC_FETCH_' => -1,
2571    'XC_FETCH_DIM_' => -1,
2572    'XC_ASSIGN_DIM' => -1,
2573    'XC_UNSET_DIM' => -1,
[749]2574    'XC_UNSET_OBJ' => -1,
[1]2575    'XC_ASSIGN_OBJ' => -1,
2576    'XC_ISSET_ISEMPTY_DIM_OBJ' => -1,
2577    'XC_ISSET_ISEMPTY_PROP_OBJ' => -1,
2578    'XC_ISSET_ISEMPTY_VAR' => -1,
[720]2579    'XC_INIT_STATIC_METHOD_CALL' => -1,
[1]2580    'XC_INIT_METHOD_CALL' => -1,
2581    'XC_VERIFY_ABSTRACT_CLASS' => -1,
2582    'XC_DECLARE_CLASS' => -1,
2583    'XC_DECLARE_INHERITED_CLASS' => -1,
[714]2584    'XC_DECLARE_INHERITED_CLASS_DELAYED' => -1,
[1]2585    'XC_ADD_INTERFACE' => -1,
2586    'XC_POST_DEC_OBJ' => -1,
2587    'XC_POST_INC_OBJ' => -1,
2588    'XC_PRE_DEC_OBJ' => -1,
2589    'XC_PRE_INC_OBJ' => -1,
2590    'XC_UNSET_OBJ' => -1,
2591    'XC_JMP_NO_CTOR' => -1,
2592    'XC_FETCH_' => -1,
2593    'XC_FETCH_DIM_' => -1,
2594    'XC_UNSET_DIM_OBJ' => -1,
2595    'XC_ISSET_ISEMPTY' => -1,
2596    'XC_INIT_FCALL_BY_FUNC' => -1,
2597    'XC_DO_FCALL_BY_FUNC' => -1,
2598    'XC_DECLARE_FUNCTION_OR_CLASS' => -1,
[749]2599    'XC_INIT_NS_FCALL_BY_NAME' => -1,
2600    'XC_GOTO' => -1,
2601    'XC_CATCH' => -1,
2602    'XC_THROW' => -1,
2603    'XC_INSTANCEOF' => -1,
2604    'XC_DECLARE_FUNCTION' => -1,
2605    'XC_RAISE_ABSTRACT_ERROR' => -1,
2606    'XC_DECLARE_CONST' => -1,
2607    'XC_USER_OPCODE' => -1,
2608    'XC_JMP_SET' => -1,
2609    'XC_DECLARE_LAMBDA_FUNCTION' => -1,
[1]2610) as $k => $v) {
2611    if (!defined($k)) {
2612        define($k, $v);
2613    }
2614}
2615// }}}
2616
Note: See TracBrowser for help on using the repository browser.