Index: /trunk/decompilesample.php
===================================================================
--- /trunk/decompilesample.php	(revision 748)
+++ /trunk/decompilesample.php	(revision 749)
@@ -32,11 +32,20 @@
 	{
 		echo CONST_VALUE;
-		echo $this::CONST_VALUE;
-		echo $a::CONST_VALUE;
 		echo ClassName::CONST_VALUE;
-	}
-
-	/** doc */
-	abstract function abastractMethod();
+		unset(ClassName::$classProp);
+		unset($obj->objProp);
+		unset($this->thisProp);
+		unset($array['index']->valueProp);
+		unset($obj->array['index']);
+		unset($this->array['index']);
+		$obj->objProp = 1;
+		$this->thisProp = 1;
+		$array['index']->valueProp = 1;
+		$array['index'] = 1;
+		$array[1] = 1;
+	}
+
+	/** doc */
+	abstract public function abastractMethod();
 
 	/** doc */
@@ -79,4 +88,9 @@
 }
 
+function f1($f)
+{
+	echo $f;
+}
+
 final class Child extends ClassName implements IInterface
 {
@@ -84,6 +98,23 @@
 	{
 		parent::__construct();
+		ClassName::__construct();
 		echo __CLASS__;
 		echo __METHOD__;
+		throw new Exception();
+		$this->methodCall();
+	}
+
+	public function __destruct()
+	{
+		parent::__destruct();
+		functionCall();
+	}
+
+	static public function __callStatic($name, $args)
+	{
+	}
+
+	public function __toString()
+	{
 	}
 
@@ -110,4 +141,9 @@
 	public function __wakeup()
 	{
+	}
+
+	public function __clone()
+	{
+		return array();
 	}
 }
@@ -115,4 +151,11 @@
 echo str_replace(array('a' => 'a', 'b' => 'c'), 'b');
 $object = new ClassName();
+$object = new $className();
+try {
+	echo 'code being try';
+}
+catch (Exception $e) {
+	echo $e;
+}
 $cloned = clone $object;
 $a = 1;
@@ -135,13 +178,15 @@
 $a = $b === $c;
 $a = $b != $c;
-$a = $b <> $c;
 $a = $b < $c;
 $a = $b <= $c;
-$a = $b > $c;
 $a = $b <= $c;
 $a = $b++;
 $a = ++$b;
+$a = $obj->b++;
+$a = ++$obj->b;
 $a = $b--;
 $a = --$b;
+$a = $obj->b--;
+$a = --$obj->b;
 $a = $b and $c;
 $a = $b or $c;
@@ -150,4 +195,6 @@
 $a = $b && $c;
 $a = $b || $c;
+$a = $b ? $c : $d;
+$a = f1() ? f2() : f3();
 $a = $b instanceof ClassName;
 
@@ -176,5 +223,5 @@
 
 foreach ($array as $key => $value) {
-	echo "$key = $value\n";
+	echo $key . ' = ' . $value . "\n";
 	continue;
 }
@@ -204,28 +251,36 @@
 include_once 'include_once.php';
 
+//* >= PHP 5.3
+echo $this::CONST_VALUE;
+echo $a::CONST_VALUE;
+$this::__construct();
+$obj::__construct();
+
+$a = $b ?: $d;
+$a = f1() ?: f2();
+
+echo 'goto a';
 goto a;
-echo 'foo';
+
+for ($i = 1; $i <= 2; ++$i) {
+	goto a;
+}
 
 a:
-echo 'bar';
-
+echo 'label a';
 echo preg_replace_callback('~-([a-z])~', function ($match) {
-		return strtoupper($match[1]);
+	return strtoupper($match[1]);
 }, 'hello-world');
-
-$greet = function($name)
-{
+$greet = function ($name) {
 	printf("Hello %s\r\n", $name);
 };
 $greet('World');
 $greet('PHP');
-
-$total = 0.00;
-
-$callback = function ($quantity, $product) use ($tax, &$total)
-{
-	$pricePerItem = constant(__CLASS__ . "::PRICE_" . strtoupper($product));
-	$total += ($pricePerItem * $quantity) * ($tax + 1.0);
+$total = 0;
+$callback = function ($quantity, $product) use ($tax, &$total) {
+	$pricePerItem = constant('PRICE_' . strtoupper($product));
+	$total += $pricePerItem * $quantity * ($tax + 1);
 };
+// */
 
 ?>
Index: /trunk/utils.c
===================================================================
--- /trunk/utils.c	(revision 716)
+++ /trunk/utils.c	(revision 749)
@@ -244,4 +244,10 @@
 			case IS_TMP_VAR:
 				break;
+
+			case IS_CONST:
+				if (spec == OPSPEC_UCLASS) {
+					break;
+				}
+				/* fall */
 
 			default:
Index: /trunk/disassembler.c
===================================================================
--- /trunk/disassembler.c	(revision 714)
+++ /trunk/disassembler.c	(revision 749)
@@ -37,26 +37,15 @@
 	add_assoc_zval_ex(dst, ZEND_STRS("op_array"), zv);
 
+	buf = emalloc(bufsize);
+
 	ALLOC_INIT_ZVAL(list);
 	array_init(list);
 	b = TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead;
 	for (; b; b = b->pListNext) {
+		int keysize, keyLength;
+
 		ALLOC_INIT_ZVAL(zv);
 		array_init(zv);
 		xc_dasm_zend_function(zv, b->pData TSRMLS_CC);
-
-		add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, zv);
-	}
-	add_assoc_zval_ex(dst, ZEND_STRS("function_table"), list);
-	
-	buf = emalloc(bufsize);
-	ALLOC_INIT_ZVAL(list);
-	array_init(list);
-	b = TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead;
-	for (; b; b = b->pListNext) {
-		int keysize, keyLength;
-
-		ALLOC_INIT_ZVAL(zv);
-		array_init(zv);
-		xc_dasm_zend_class_entry(zv, CestToCePtr(*(xc_cest_t *)b->pData) TSRMLS_CC);
 
 		keysize = BUCKET_KEY_SIZE(b) + 2;
@@ -82,4 +71,41 @@
 			}
 		}
+
+		add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), keyLength, zv);
+	}
+	add_assoc_zval_ex(dst, ZEND_STRS("function_table"), list);
+	
+	ALLOC_INIT_ZVAL(list);
+	array_init(list);
+	b = TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead;
+	for (; b; b = b->pListNext) {
+		int keysize, keyLength;
+
+		ALLOC_INIT_ZVAL(zv);
+		array_init(zv);
+		xc_dasm_zend_class_entry(zv, CestToCePtr(*(xc_cest_t *)b->pData) TSRMLS_CC);
+
+		keysize = BUCKET_KEY_SIZE(b) + 2;
+		if (keysize > bufsize) {
+			do {
+				bufsize *= 2;
+			} while (keysize > bufsize);
+			buf = erealloc(buf, bufsize);
+		}
+		memcpy(buf, BUCKET_KEY_S(b), keysize);
+		buf[keysize - 2] = buf[keysize - 1] = ""[0];
+		keyLength = b->nKeyLength;
+#ifdef IS_UNICODE
+		if (BUCKET_KEY_TYPE(b) == IS_UNICODE) {
+			if (buf[0] == ""[0] && buf[1] == ""[0]) {
+				keyLength ++;
+			}
+		} else
+#endif
+		{
+			if (buf[0] == ""[0]) {
+				keyLength ++;
+			}
+		}
 		add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), keyLength, zv);
 	}
Index: /trunk/Decompiler.class.php
===================================================================
--- /trunk/Decompiler.class.php	(revision 746)
+++ /trunk/Decompiler.class.php	(revision 749)
@@ -71,4 +71,26 @@
 }
 // }}}
+function unquoteProperty($str, $indent = '') // {{{
+{
+	$str = str($str, $indent);
+	if (preg_match("!^'[\\w_][\\w\\d_]*'\$!", $str)) {
+		return substr($str, 1, -1);
+	}
+	else {
+		return "{" . $str . "}";
+	}
+}
+// }}}
+function unquoteName($str, $indent = '') // {{{
+{
+	$str = str($str, $indent);
+	if (preg_match("!^'[\\w_][\\w\\d_]*'\$!", $str)) {
+		return substr($str, 1, -1);
+	}
+	else {
+		return $str;
+	}
+}
+// }}}
 class Decompiler_Object // {{{
 {
@@ -154,4 +176,8 @@
 			return '$' . substr($this->src, 1, -1);
 		case ZEND_FETCH_STATIC:
+			if (ZEND_ENGINE_2_3) {
+				// closure local variable?
+				return str($this->src);
+			}
 			die('static fetch cant to string');
 		case ZEND_FETCH_GLOBAL:
@@ -184,4 +210,5 @@
 	var $offsets = array();
 	var $isLast = false;
+	var $isObject = false;
 	var $assign = null;
 
@@ -189,11 +216,17 @@
 	{
 		if (is_a($this->value, 'Decompiler_ListBox')) {
-			$exp = foldToCode($this->value->obj->src, $indent);
+			$exp = str($this->value->obj->src, $indent);
 		}
 		else {
-			$exp = foldToCode($this->value, $indent);
-		}
-		foreach ($this->offsets as $dim) {
-			$exp .= '[' . foldToCode($dim, $indent) . ']';
+			$exp = str($this->value, $indent);
+		}
+		$last = count($this->offsets) - 1;
+		foreach ($this->offsets as $i => $dim) {
+			if ($this->isObject && $i == $last) {
+				$exp .= '->' . unquoteProperty($dim, $indent);
+			}
+			else {
+				$exp .= '[' . str($dim, $indent) . ']';
+			}
 		}
 		return $exp;
@@ -220,5 +253,5 @@
 				return foldToCode($dim, $indent);
 			}
-			return foldToCode($this->dims[0]->assign, $indent) . ' = ' . foldToCode($dim, $indent);
+			return foldToCode($this->dims[0]->assign, $indent) . ' = ' . str($dim, $indent);
 		}
 		/* flatten dims */
@@ -231,5 +264,5 @@
 			$assign = foldToCode($dim->assign, $indent);
 		}
-		return $this->toList($assigns) . ' = ' . foldToCode($this->src, $indent);
+		return $this->toList($assigns) . ' = ' . str($this->src, $indent);
 	}
 
@@ -377,5 +410,4 @@
 {
 	var $rName = '!^[\\w_][\\w\\d_]*$!';
-	var $rQuotedName = "!^'[\\w_][\\w\\d_]*'\$!";
 
 	function Decompiler()
@@ -439,10 +471,10 @@
 					$curticks = $toticks;
 					if (!$curticks) {
-						echo $origindent, "}\n";
+						echo $origindent, "}\n\n";
 						$indent = $origindent;
 					}
 					else {
 						if ($oldticks) {
-							echo $origindent, "}\n";
+							echo $origindent, "}\n\n";
 						}
 						else if (!$oldticks) {
@@ -569,4 +601,5 @@
 			$op['line'] = $i;
 			switch ($op['opcode']) {
+			case XC_GOTO:
 			case XC_JMP:
 				$target = $op['op1']['var'];
@@ -587,4 +620,5 @@
 			case XC_JMPZ_EX:
 			case XC_JMPNZ_EX:
+			case XC_JMP_SET:
 			// case XC_FE_RESET:
 			case XC_FE_FETCH:
@@ -772,13 +806,4 @@
 	}
 	// }}}
-	function unquoteName($str) // {{{
-	{
-		$str = str($str);
-		if (preg_match($this->rQuotedName, $str)) {
-			$str = substr($str, 1, -1);
-		}
-		return $str;
-	}
-	// }}}
 	function dasmBasicBlock(&$EX, $opline, $last) // {{{
 	{
@@ -843,8 +868,24 @@
 					$EX['object'] = (int) $res['var'];
 					$EX['called_scope'] = null;
-					$EX['fbc'] = 'new ' . $this->unquoteName($this->getOpVal($op1, $EX));
+					$EX['fbc'] = 'new ' . unquoteName($this->getOpVal($op1, $EX), $EX);
 					if (!ZEND_ENGINE_2) {
 						$resvar = '$new object$';
 					}
+					break;
+					// }}}
+				case XC_THROW: // {{{
+					$resvar = 'throw ' . str($this->getOpVal($op1, $EX));
+					break;
+					// }}}
+				case XC_CLONE: // {{{
+					$resvar = 'clone ' . str($this->getOpVal($op1, $EX));
+					break;
+					// }}}
+				case XC_CATCH: // {{{
+					$resvar = 'catch (' . str($this->getOpVal($op1, $EX)) . ' ' . str($this->getOpVal($op2, $EX)) . ')';
+					break;
+					// }}}
+				case XC_INSTANCEOF: // {{{
+					$resvar = str($this->getOpVal($op1, $EX)) . ' instanceof ' . str($this->getOpVal($op2, $EX));
 					break;
 					// }}}
@@ -865,7 +906,7 @@
 					}
 					else {
-						$class = $op2['constant'];
-						if (is_object($class)) {
-							$class = get_class($class);
+						$class = $this->getOpVal($op2, $EX);
+						if (isset($op2['constant'])) {
+							$class = unquoteName($class);
 						}
 					}
@@ -874,15 +915,17 @@
 					// }}}
 				case XC_FETCH_CONSTANT: // {{{
+					if ($op1['op_type'] == XC_IS_UNUSED) {
+						$resvar = $op2['constant'];
+						break;
+					}
+
 					if ($op1['op_type'] == XC_IS_CONST) {
 						$resvar = $op1['constant'];
 					}
-					else if ($op1['op_type'] == XC_IS_UNUSED) {
-						$resvar = $op2['constant'];
-					}
 					else {
-						$class = $T[$op1['var']];
-						assert($class[0] == 'class');
-						$resvar = $class[1] . '::' . $op2['constant'];
-					}
+						$resvar = $this->getOpVal($op1, $EX);
+					}
+
+					$resvar = str($resvar) . '::' . unquoteName($this->getOpVal($op2, $EX));
 					break;
 					// }}}
@@ -905,9 +948,9 @@
 					case ZEND_FETCH_STATIC_MEMBER:
 						$class = $this->getOpVal($op2, $EX);
-						$rvalue = $class . '::$' . $this->unquoteName($rvalue);
+						$rvalue = str($class) . '::$' . unquoteName($rvalue, $EX);
 						break;
 					default:
-						$name = $this->unquoteName($rvalue);
-						$globalname = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[$rvalue]";
+						$name = unquoteName($rvalue, $EX);
+						$globalname = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[" . str($rvalue) . "]";
 						$rvalue = new Decompiler_Fetch($rvalue, $fetchtype, $globalname);
 						break;
@@ -931,6 +974,7 @@
 				case XC_FETCH_DIM_IS:
 				case XC_ASSIGN_DIM:
+				case XC_UNSET_DIM_OBJ: // PHP 4 only
 				case XC_UNSET_DIM:
-				case XC_UNSET_DIM_OBJ:
+				case XC_UNSET_OBJ:
 					$src = $this->getOpVal($op1, $EX, false);
 					if (is_a($src, "Decompiler_ForeachBox")) {
@@ -939,10 +983,12 @@
 						break;
 					}
-					else if (is_a($src, "Decompiler_DimBox")) {
+
+					if (is_a($src, "Decompiler_DimBox")) {
 						$dimbox = $src;
 					}
 					else {
 						if (!is_a($src, "Decompiler_ListBox")) {
-							$list = new Decompiler_List($this->getOpVal($op1, $EX, false));
+							$op1val = $this->getOpVal($op1, $EX, false);
+							$list = new Decompiler_List(isset($op1val) ? $op1val : '$this');
 
 							$src = new Decompiler_ListBox($list);
@@ -968,6 +1014,10 @@
 						$dim->isLast = true;
 					}
+					if ($opc == XC_UNSET_OBJ) {
+						$dim->isObject = true;
+					}
 					unset($dim);
 					$rvalue = $dimbox;
+					unset($dimbox);
 
 					if ($opc == XC_ASSIGN_DIM) {
@@ -975,7 +1025,7 @@
 						++ $i;
 						$rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX);
-						$resvar = str($lvalue, $EX) . ' = ' . $rvalue;
-					}
-					else if ($opc == XC_UNSET_DIM) {
+						$resvar = str($lvalue, $EX) . ' = ' . str($rvalue);
+					}
+					else if ($opc == XC_UNSET_DIM || $opc == XC_UNSET_OBJ) {
 						$op['php'] = "unset(" . str($rvalue, $EX) . ")";
 						$lastphpop = &$op;
@@ -1011,5 +1061,5 @@
 					$rvalue = $this->getOpVal($op2, $EX, false);
 					if (is_a($rvalue, 'Decompiler_Fetch')) {
-						$src = foldToCode($rvalue->src, $EX);
+						$src = str($rvalue->src, $EX);
 						if (substr($src, 1, -1) == substr($lvalue, 1)) {
 							switch ($rvalue->fetchType) {
@@ -1050,12 +1100,5 @@
 						$obj = '$this';
 					}
-					$prop = $this->getOpVal($op2, $EX);
-					if (preg_match($this->rQuotedName, $prop)) {
-						$prop = substr($prop, 1, -1);;
-						$rvalue = "{$obj}->$prop";
-					}
-					else {
-						$rvalue = "{$obj}->{" . "$prop}";
-					}
+					$rvalue = str($obj) . "->" . unquoteProperty($this->getOpVal($op2, $EX), $EX);
 					if ($res['op_type'] != XC_IS_UNUSED) {
 						$resvar = $rvalue;
@@ -1065,5 +1108,5 @@
 						$lvalue = $rvalue;
 						$rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX);
-						$resvar = "$lvalue = $rvalue";
+						$resvar = "$lvalue = " . str($rvalue);
 					}
 					break;
@@ -1125,10 +1168,5 @@
 					// }}}
 				case XC_INIT_STATIC_METHOD_CALL:
-				case XC_INIT_METHOD_CALL:
-				case XC_INIT_FCALL_BY_FUNC:
-				case XC_INIT_FCALL_BY_NAME: // {{{
-					if (($ext & ZEND_CTOR_CALL)) {
-						break;
-					}
+				case XC_INIT_METHOD_CALL: // {{{
 					array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
 					if ($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL || $op1['op_type'] != XC_IS_UNUSED) {
@@ -1139,5 +1177,5 @@
 						if ($opc == XC_INIT_STATIC_METHOD_CALL || /* PHP4 */ isset($op1['constant'])) {
 							$EX['object'] = null;
-							$EX['called_scope'] = $this->unquoteName($obj);
+							$EX['called_scope'] = unquoteName($obj, $EX);
 						}
 						else {
@@ -1154,11 +1192,24 @@
 					}
 
-					if ($opc == XC_INIT_FCALL_BY_FUNC) {
-						$which = $op1['var'];
-						$EX['fbc'] = $EX['op_array']['funcs'][$which]['name'];
-					}
-					else {
-						$EX['fbc'] = $this->getOpVal($op2, $EX, false);
-					}
+					$EX['fbc'] = $this->getOpVal($op2, $EX, false);
+					if (($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL) && !isset($EX['fbc'])) {
+						$EX['fbc'] = '__construct';
+					}
+					break;
+					// }}}
+				case XC_INIT_FCALL_BY_NAME: // {{{
+					if (!ZEND_ENGINE_2 && ($ext & ZEND_CTOR_CALL)) {
+						break;
+					}
+					$EX['object'] = null;
+					$EX['called_scope'] = null;
+					$EX['fbc'] = $this->getOpVal($op2, $EX);
+					break;
+					// }}}
+				case XC_INIT_FCALL_BY_FUNC: // {{{ deprecated even in PHP 4?
+					$EX['object'] = null;
+					$EX['called_scope'] = null;
+					$which = $op1['var'];
+					$EX['fbc'] = $EX['op_array']['funcs'][$which]['name'];
 					break;
 					// }}}
@@ -1170,5 +1221,5 @@
 					break;
 				case XC_DO_FCALL:
-					$fname = $this->unquoteName($this->getOpVal($op1, $EX, false));
+					$fname = unquoteName($this->getOpVal($op1, $EX, false), $EX);
 					$args = $this->popargs($EX, $ext);
 					$resvar = $fname . "($args)";
@@ -1177,5 +1228,5 @@
 					$object = null;
 
-					$fname = $this->unquoteName($EX['fbc']);
+					$fname = unquoteName($EX['fbc'], $EX);
 					if (!is_int($EX['object'])) {
 						$object = $EX['object'];
@@ -1211,5 +1262,5 @@
 					}
 					$class = &$this->dc['class_table'][$key];
-					$class['name'] = $this->unquoteName($this->getOpVal($op2, $EX));
+					$class['name'] = unquoteName($this->getOpVal($op2, $EX), $EX);
 					if ($opc == XC_DECLARE_INHERITED_CLASS || $opc == XC_DECLARE_INHERITED_CLASS_DELAYED) {
 						$ext /= XC_SIZEOF_TEMP_VARIABLE;
@@ -1221,10 +1272,22 @@
 					}
 
-					while ($i + 2 < $ic
-					 && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE
-					 && $opcodes[$i + 2]['op1']['var'] == $res['var']
-					 && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) {
+					for (;;) {
+						if ($i + 1 < $ic
+						 && $opcodes[$i + 1]['opcode'] == XC_ADD_INTERFACE
+						 && $opcodes[$i + 1]['op1']['var'] == $res['var']) {
+							// continue
+						}
+						else if ($i + 2 < $ic
+						 && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE
+						 && $opcodes[$i + 2]['op1']['var'] == $res['var']
+						 && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) {
+							// continue
+						}
+						else {
+							break;
+						}
+
 						$fetchop = &$opcodes[$i + 1];
-						$impl = $this->unquoteName($this->getOpVal($fetchop['op2'], $EX));
+						$impl = unquoteName($this->getOpVal($fetchop['op2'], $EX), $EX);
 						$addop = &$opcodes[$i + 2];
 						$class['interfaces'][$addop['extended_value']] = $impl;
@@ -1233,4 +1296,5 @@
 					}
 					$this->dclass($class);
+					echo "\n";
 					unset($class);
 					break;
@@ -1247,16 +1311,15 @@
 					switch ($opc) {
 					case XC_ADD_CHAR:
-						$op2val = foldToCode(chr($op2val), $EX);
+						$op2val = value(chr(str($op2val)));
 						break;
 					case XC_ADD_STRING:
-						$op2val = foldToCode($op2val, $EX);
 						break;
 					case XC_ADD_VAR:
 						break;
 					}
-					if ($op1val == "''") {
+					if (str($op1val) == "''") {
 						$rvalue = $op2val;
 					}
-					else if ($op2val == "''") {
+					else if (str($op2val) == "''") {
 						$rvalue = $op1val;
 					}
@@ -1328,5 +1391,5 @@
 					$type = $op2['var']; // hack
 					$keyword = $this->includeTypes[$type];
-					$resvar = "$keyword(" . str($this->getOpVal($op1, $EX)) . ")";
+					$resvar = "$keyword " . str($this->getOpVal($op1, $EX));
 					break;
 					// }}}
@@ -1366,4 +1429,5 @@
 				case XC_JMP_NO_CTOR:
 					break;
+				case XC_JMP_SET: // ?:
 				case XC_JMPNZ: // while
 				case XC_JMPZNZ: // for
@@ -1403,4 +1467,5 @@
 					break;
 					// }}}
+				case XC_GOTO:
 				case XC_JMP: // {{{
 					$op['cond'] = null;
@@ -1437,12 +1502,5 @@
 					$flags = array_flip(explode('_', $opname));
 					if (isset($flags['OBJ'])) {
-						$resvar = $this->getOpVal($op1, $EX);
-						$prop = $this->unquoteName($this->getOpVal($op2, $EX));
-						if ($prop{0} == '$') {
-							$resvar = $resvar . "{" . $prop . "}";
-						}
-						else {
-							$resvar = $resvar . "->" . $prop;
-						}
+						$resvar = $this->getOpVal($op1, $EX) . '->' . unquoteProperty($this->getOpVal($op2, $EX), $EX);
 					}
 					else {
@@ -1451,8 +1509,8 @@
 					$opstr = isset($flags['DEC']) ? '--' : '++';
 					if (isset($flags['POST'])) {
-						$resvar .= ' ' . $opstr;
+						$resvar .= $opstr;
 					}
 					else {
-						$resvar = "$opstr $resvar";
+						$resvar = "$opstr$resvar";
 					}
 					break;
@@ -1492,4 +1550,10 @@
 				case XC_EXT_NOP:
 					break;
+				case XC_DECLARE_LAMBDA_FUNCTION:
+					ob_start();
+					$this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']);
+					$resvar = ob_get_clean();
+					$istmpres = true;
+					break;
 				case XC_DECLARE_FUNCTION_OR_CLASS:
 					/* always removed by compiler */
@@ -1498,4 +1562,12 @@
 					$lastphpop['ticks'] = $this->getOpVal($op1, $EX);
 					// $EX['tickschanged'] = true;
+					break;
+				case XC_RAISE_ABSTRACT_ERROR:
+					// abstract function body is empty, don't need this code
+					break;
+				case XC_USER_OPCODE:
+					echo '// ZEND_USER_OPCODE, impossible to decompile';
+					break;
+				case XC_OP_DATA:
 					break;
 				default: // {{{
@@ -1559,5 +1631,5 @@
 				$d[$kk] = '$' . $op[$k]['var'];
 				if ($kk != 'res') {
-					$d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
+					$d[$kk] .= ':' . str($this->getOpVal($op[$k], $EX));
 				}
 				break;
@@ -1566,5 +1638,5 @@
 				$d[$kk] = '#' . $op[$k]['var'];
 				if ($kk != 'res') {
-					$d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
+					$d[$kk] .= ':' . str($this->getOpVal($op[$k], $EX));
 				}
 				break;
@@ -1661,5 +1733,4 @@
 	{
 		if ($nobody) {
-			$body = ";\n";
 			$EX = array();
 			$EX['op_array'] = &$func['op_array'];
@@ -1676,10 +1747,29 @@
 		}
 
-		echo 'function ', $func['op_array']['function_name'], '(';
+		$functionName = $func['op_array']['function_name'];
+		if ($functionName == '{closure}') {
+			$functionName = '';
+		}
+		echo 'function ', $functionName, '(';
 		$this->dargs($EX, $indent);
-		echo ")\n";
-		echo $indent, "{\n";
-		echo $body;
-		echo "$indent}\n";
+		echo ")";
+		if ($nobody) {
+			echo ";\n";
+		}
+		else {
+			if ($functionName !== '') {
+				echo "\n";
+				echo $indent, "{\n";
+			}
+			else {
+				echo " {\n";
+			}
+
+			echo $body;
+			echo "$indent}";
+			if ($functionName !== '') {
+				echo "\n";
+			}
+		}
 	}
 	// }}}
@@ -1695,17 +1785,16 @@
 		if (!empty($class['ce_flags'])) {
 			if ($class['ce_flags'] & ZEND_ACC_INTERFACE) {
-				echo 'interface ';
 				$isinterface = true;
 			}
 			else {
-				if ($class['ce_flags'] & ZEND_ACC_IMPLICIT_ABSTRACT) {
+				if ($class['ce_flags'] & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
 					echo "abstract ";
 				}
-				if ($class['ce_flags'] & ZEND_ACC_FINAL) {
+				if ($class['ce_flags'] & ZEND_ACC_FINAL_CLASS) {
 					echo "final ";
 				}
 			}
 		}
-		echo 'class ', $class['name'];
+		echo $isinterface ? 'interface ' : 'class ', $class['name'];
 		if ($class['parent']) {
 			echo ' extends ', $class['parent'];
@@ -1822,7 +1911,9 @@
 					}
 					echo $newindent;
+					$isAbstractMethod = false;
 					if (isset($opa['fn_flags'])) {
-						if ($opa['fn_flags'] & ZEND_ACC_ABSTRACT) {
+						if (($opa['fn_flags'] & ZEND_ACC_ABSTRACT) && !$isinterface) {
 							echo "abstract ";
+							$isAbstractMethod = true;
 						}
 						if ($opa['fn_flags'] & ZEND_ACC_FINAL) {
@@ -1848,5 +1939,5 @@
 						}
 					}
-					$this->dfunction($func, $newindent, $isinterface);
+					$this->dfunction($func, $newindent, $isinterface || $isAbstractMethod);
 					if ($opa['function_name'] == 'Decompiler') {
 						//exit;
@@ -1879,9 +1970,9 @@
 	function output() // {{{
 	{
-		echo "<?". "php\n";
+		echo "<?". "php\n\n";
 		foreach ($this->dc['class_table'] as $key => $class) {
 			if ($key{0} != "\0") {
+				$this->dclass($class);
 				echo "\n";
-				$this->dclass($class);
 			}
 		}
@@ -1889,10 +1980,9 @@
 		foreach ($this->dc['function_table'] as $key => $func) {
 			if ($key{0} != "\0") {
+				$this->dfunction($func);
 				echo "\n";
-				$this->dfunction($func);
-			}
-		}
-
-		echo "\n";
+			}
+		}
+
 		$this->dop_array($this->dc['op_array']);
 		echo "\n?" . ">\n";
@@ -1903,29 +1993,4 @@
 
 // {{{ defines
-define('ZEND_ACC_STATIC',         0x01);
-define('ZEND_ACC_ABSTRACT',       0x02);
-define('ZEND_ACC_FINAL',          0x04);
-define('ZEND_ACC_IMPLEMENTED_ABSTRACT',       0x08);
-
-define('ZEND_ACC_IMPLICIT_ABSTRACT_CLASS',    0x10);
-define('ZEND_ACC_EXPLICIT_ABSTRACT_CLASS',    0x20);
-define('ZEND_ACC_FINAL_CLASS',                0x40);
-define('ZEND_ACC_INTERFACE',                  0x80);
-define('ZEND_ACC_PUBLIC',     0x100);
-define('ZEND_ACC_PROTECTED',  0x200);
-define('ZEND_ACC_PRIVATE',    0x400);
-define('ZEND_ACC_PPP_MASK',  (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE));
-
-define('ZEND_ACC_CHANGED',    0x800);
-define('ZEND_ACC_IMPLICIT_PUBLIC',    0x1000);
-
-define('ZEND_ACC_CTOR',       0x2000);
-define('ZEND_ACC_DTOR',       0x4000);
-define('ZEND_ACC_CLONE',      0x8000);
-
-define('ZEND_ACC_ALLOW_STATIC',   0x10000);
-
-define('ZEND_ACC_SHADOW', 0x2000);
-
 define('ZEND_ENGINE_2_4', PHP_VERSION >= "5.3.99");
 define('ZEND_ENGINE_2_3', ZEND_ENGINE_2_4 || PHP_VERSION >= "5.3.");
@@ -1933,4 +1998,32 @@
 define('ZEND_ENGINE_2_1', ZEND_ENGINE_2_2 || PHP_VERSION >= "5.1.");
 define('ZEND_ENGINE_2',   ZEND_ENGINE_2_1 || PHP_VERSION >= "5.0.");
+
+define('ZEND_ACC_STATIC',         0x01);
+define('ZEND_ACC_ABSTRACT',       0x02);
+define('ZEND_ACC_FINAL',          0x04);
+define('ZEND_ACC_IMPLEMENTED_ABSTRACT',       0x08);
+
+define('ZEND_ACC_IMPLICIT_ABSTRACT_CLASS',    0x10);
+define('ZEND_ACC_EXPLICIT_ABSTRACT_CLASS',    0x20);
+define('ZEND_ACC_FINAL_CLASS',                0x40);
+define('ZEND_ACC_INTERFACE',                  0x80);
+if (ZEND_ENGINE_2_4) {
+	define('ZEND_ACC_TRAIT',                  0x120);
+}
+define('ZEND_ACC_PUBLIC',     0x100);
+define('ZEND_ACC_PROTECTED',  0x200);
+define('ZEND_ACC_PRIVATE',    0x400);
+define('ZEND_ACC_PPP_MASK',  (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE));
+
+define('ZEND_ACC_CHANGED',    0x800);
+define('ZEND_ACC_IMPLICIT_PUBLIC',    0x1000);
+
+define('ZEND_ACC_CTOR',       0x2000);
+define('ZEND_ACC_DTOR',       0x4000);
+define('ZEND_ACC_CLONE',      0x8000);
+
+define('ZEND_ACC_ALLOW_STATIC',   0x10000);
+
+define('ZEND_ACC_SHADOW', 0x2000);
 
 if (ZEND_ENGINE_2_4) {
@@ -2031,5 +2124,5 @@
 	'XC_ASSIGN_DIM' => -1,
 	'XC_UNSET_DIM' => -1,
-	'XC_FETCH_OBJ_' => -1,
+	'XC_UNSET_OBJ' => -1,
 	'XC_ASSIGN_OBJ' => -1,
 	'XC_ISSET_ISEMPTY_DIM_OBJ' => -1,
@@ -2052,9 +2145,19 @@
 	'XC_FETCH_DIM_' => -1,
 	'XC_UNSET_DIM_OBJ' => -1,
-	'XC_FETCH_OBJ_' => -1,
 	'XC_ISSET_ISEMPTY' => -1,
 	'XC_INIT_FCALL_BY_FUNC' => -1,
 	'XC_DO_FCALL_BY_FUNC' => -1,
 	'XC_DECLARE_FUNCTION_OR_CLASS' => -1,
+	'XC_INIT_NS_FCALL_BY_NAME' => -1,
+	'XC_GOTO' => -1,
+	'XC_CATCH' => -1,
+	'XC_THROW' => -1,
+	'XC_INSTANCEOF' => -1,
+	'XC_DECLARE_FUNCTION' => -1,
+	'XC_RAISE_ABSTRACT_ERROR' => -1,
+	'XC_DECLARE_CONST' => -1,
+	'XC_USER_OPCODE' => -1,
+	'XC_JMP_SET' => -1,
+	'XC_DECLARE_LAMBDA_FUNCTION' => -1,
 ) as $k => $v) {
 	if (!defined($k)) {
@@ -2063,5 +2166,5 @@
 }
 
-/* XC_UNDEF XC_OP_DATA
+//* XC_UNDEF XC_OP_DATA
 $content = file_get_contents(__FILE__);
 for ($i = 0; $opname = xcache_get_opcode($i); $i ++) {
