Index: /branches/1.3/ChangeLog
===================================================================
--- /branches/1.3/ChangeLog	(revision 725)
+++ /branches/1.3/ChangeLog	(revision 726)
@@ -1,4 +1,6 @@
 1.3.2 2011-??-??
 ========
+ * disassembler: DECLARE_INHERITED_CLASS/DELAYED class not found
+ * disassembler: don't dump builtin functions
  * fix win32 build against win32 native gnu tools
  * compatibility fix: fix segv on shutdown when ionCube Loader is loaded
Index: /branches/1.3/Decompiler.class.php
===================================================================
--- /branches/1.3/Decompiler.class.php	(revision 725)
+++ /branches/1.3/Decompiler.class.php	(revision 726)
@@ -28,6 +28,6 @@
 
 	if (is_array($src)) {
-		die_error('array str');
-		$src = new Decompiler_Array($src, false, $indent);
+		exit('array str');
+		$src = new Decompiler_Array($src, $indent);
 		return $src->__toString();
 	}
@@ -36,7 +36,7 @@
 		if (!method_exists($src, '__toString')) {
 			var_dump($src);
-			die_error('no __toString');
-		}
-		return $src->__toString($indent);
+			exit('no __toString');
+		}
+		return $src->__toString();
 	}
 
@@ -55,9 +55,12 @@
 	}
 
-	if (is_array($value)) {
-		$value = new Decompiler_Array($value, true);
+	if ($value instanceof Decompiler_Object) {
+		// use as is
+	}
+	else if (is_array($value)) {
+		$value = new Decompiler_Array($value);
 	}
 	else {
-		$value = new Decompiler_Value($value, true);
+		$value = new Decompiler_Value($value);
 	}
 	return $value;
@@ -257,11 +260,9 @@
 class Decompiler_Array extends Decompiler_Value // {{{
 {
-	var $needExport = false;
 	var $indent = '';
 
-	function Decompiler_Array($value = array(), $needexport = false, $indent = '')
+	function Decompiler_Array($value = array(), $indent = '')
 	{
 		$this->value = $value;
-		$this->needExport = $needexport;
 		$this->indent = $indent;
 	}
@@ -286,5 +287,5 @@
 			++ $i;
 		}
-		if ($assoclen && $this->needExport) {
+		if ($assoclen) {
 			$assoclen += 2;
 		}
@@ -306,7 +307,5 @@
 			}
 
-			if ($this->needExport) {
-				$k = var_export($k, true);
-			}
+			$k = var_export($k, true);
 			if ($multiline) {
 				$exp .= sprintf("%{$assoclen}s => ", $k);
@@ -316,8 +315,5 @@
 			}
 
-			if (is_array($v)) {
-				$v = new Decompiler_Array($v, $this->needExport);
-			}
-			$exp .= str($v, $subindent);
+			$exp .= str(value($v), $subindent);
 
 			$i ++;
@@ -433,20 +429,20 @@
 		switch ($op['op_type']) {
 		case XC_IS_CONST:
-			return str(value($op['u.constant']));
+			return str(value($op['constant']));
 
 		case XC_IS_VAR:
 		case XC_IS_TMP_VAR:
 			$T = &$EX['Ts'];
-			$ret = $T[$op['u.var']];
+			$ret = $T[$op['var']];
 			if ($tostr) {
 				$ret = str($ret, $EX);
 			}
 			if ($free) {
-				unset($T[$op['u.var']]);
+				unset($T[$op['var']]);
 			}
 			return $ret;
 
 		case XC_IS_CV:
-			$var = $op['u.var'];
+			$var = $op['var'];
 			$var = $EX['op_array']['vars'][$var];
 			return '$' . $var['name'];
@@ -455,4 +451,17 @@
 			return null;
 		}
+	}
+	// }}}
+	function removeKeyPrefix($array, $prefix) // {{{
+	{
+		$prefixLen = strlen($prefix);
+		$ret = array();
+		foreach ($array as $key => $value) {
+			if (substr($key, 0, $prefixLen) == $prefix) {
+				$key = substr($key, $prefixLen);
+			}
+			$ret[$key] = $value;
+		}
+		return $ret;
 	}
 	// }}}
@@ -465,7 +474,35 @@
 		}
 		$EX['indent'] = '';
-		//for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
-		//	$opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i);
-		//}
+		for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
+			if (function_exists('xcache_get_fixed_opcode')) {
+				$opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i);
+			}
+			if (isset($opcodes[$i]['op1'])) {
+				$opcodes[$i]['op1'] = $this->removeKeyPrefix($opcodes[$i]['op1'], 'u.');
+				$opcodes[$i]['op2'] = $this->removeKeyPrefix($opcodes[$i]['op2'], 'u.');
+				$opcodes[$i]['result'] = $this->removeKeyPrefix($opcodes[$i]['result'], 'u.');
+			}
+			else {
+				$op = array(
+					'op1' => array(),
+					'op2' => array(),
+					'op3' => array(),
+				);
+				foreach ($opcodes[$i] as $name => $value) {
+					if (preg_match('!^(op1|op2|result)\\.(.*)!', $name, $m)) {
+						list(, $which, $field) = $m;
+						$op[$which][$field] = $value;
+					}
+					else if (preg_match('!^(op1|op2|result)_type$!', $name, $m)) {
+						list(, $which) = $m;
+						$op[$which]['op_type'] = $value;
+					}
+					else {
+						$op[$name] = $value;
+					}
+				}
+				$opcodes[$i] = $op;
+			}
+		}
 		// {{{ build jmp array
 		for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
@@ -481,5 +518,5 @@
 			switch ($op['opcode']) {
 			case XC_JMP:
-				$target = $op['op1']['u.var'];
+				$target = $op['op1']['var'];
 				$op['jmpouts'] = array($target);
 				$opcodes[$target]['jmpins'][] = $i;
@@ -487,5 +524,5 @@
 
 			case XC_JMPZNZ:
-				$jmpz = $op['op2']['u.opline_num'];
+				$jmpz = $op['op2']['opline_num'];
 				$jmpnz = $op['extended_value'];
 				$op['jmpouts'] = array($jmpz, $jmpnz);
@@ -501,5 +538,5 @@
 			case XC_FE_FETCH:
 			// case XC_JMP_NO_CTOR:
-				$target = $op['op2']['u.opline_num'];
+				$target = $op['op2']['opline_num'];
 				//if (!isset($target)) {
 				//	$this->dumpop($op, $EX);
@@ -539,4 +576,5 @@
 		// func call
 		$EX['object'] = null;
+		$EX['called_scope'] = null;
 		$EX['fbc'] = null;
 		$EX['argstack'] = array();
@@ -588,5 +626,5 @@
 		if ($op['opcode'] == XC_FE_FETCH) {
 			$opline = $next;
-			$next = $op['op2']['u.opline_num'];
+			$next = $op['op2']['opline_num'];
 			$end = $next - 1;
 
@@ -607,10 +645,10 @@
 		/*
 		if ($op['opcode'] == XC_JMPZ) {
-			$target = $op2['u.opline_num'];
+			$target = $op2['opline_num'];
 			if ($line + 1) {
 				$nextblock = $EX['nextbbs'][$next];
 				$jmpop = end($nextblock);
 				if ($jmpop['opcode'] == XC_JMP) {
-					$ifendline = $op2['u.opline_num'];
+					$ifendline = $op2['opline_num'];
 					if ($ifendline >= $line) {
 						$cond = $op['cond'];
@@ -657,5 +695,5 @@
 				}
 
-				$var = $fromop['result']['u.var'];
+				$var = $fromop['result']['var'];
 				var_dump($EX['Ts'][$var]);
 				$EX['Ts'][$var] = '(' . $fromop['and_or'] . " $opstr " . $EX['Ts'][$var] . ')';
@@ -719,5 +757,5 @@
 
 			$resvar = null;
-			if (($res['u.EA.type'] & EXT_TYPE_UNUSED) || $res['op_type'] == XC_IS_UNUSED) {
+			if (isset($res['EA.type']) && ($res['EA.type'] & EXT_TYPE_UNUSED) || $res['op_type'] == XC_IS_UNUSED) {
 				$istmpres = false;
 			}
@@ -749,6 +787,7 @@
 				switch ($opc) {
 				case XC_NEW: // {{{
-					array_push($EX['arg_types_stack'], array($EX['object'], $EX['fbc']));
-					$EX['object'] = (int) $res['u.var'];
+					array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
+					$EX['object'] = (int) $res['var'];
+					$EX['called_scope'] = null;
 					$EX['fbc'] = 'new ' . $this->unquoteName($this->getOpVal($op1, $EX));
 					if (PHP_VERSION < 5) {
@@ -765,8 +804,13 @@
 						case ZEND_FETCH_CLASS_PARENT:
 							$class = 'parent';
-						}
+							break;
+						case ZEND_FETCH_CLASS_STATIC:
+							$class = 'static';
+							break;
+						}
+						$istmpres = true;
 					}
 					else {
-						$class = $op2['u.constant'];
+						$class = $op2['constant'];
 						if (is_object($class)) {
 							$class = get_class($class);
@@ -778,13 +822,13 @@
 				case XC_FETCH_CONSTANT: // {{{
 					if ($op1['op_type'] == XC_IS_CONST) {
-						$resvar = $op1['u.constant'];
+						$resvar = $op1['constant'];
 					}
 					else if ($op1['op_type'] == XC_IS_UNUSED) {
-						$resvar = $op2['u.constant'];
+						$resvar = $op2['constant'];
 					}
 					else {
-						$class = $T[$op1['u.var']];
+						$class = $T[$op1['var']];
 						assert($class[0] == 'class');
-						$resvar = $class[1] . '::' . $op2['u.constant'];
+						$resvar = $class[1] . '::' . $op2['constant'];
 					}
 					break;
@@ -799,5 +843,5 @@
 				case XC_UNSET_VAR:
 					$rvalue = $this->getOpVal($op1, $EX);
-					$fetchtype = $op2[PHP_VERSION < 5 ? 'u.fetch_type' : 'u.EA.type'];
+					$fetchtype = $op2[PHP_VERSION < 5 ? 'fetch_type' : 'EA.type'];
 					switch ($fetchtype) {
 					case ZEND_FETCH_STATIC_MEMBER:
@@ -845,10 +889,10 @@
 
 							$src = new Decompiler_ListBox($list);
-							if (!isset($op1['u.var'])) {
+							if (!isset($op1['var'])) {
 								$this->dumpop($op, $EX);
 								var_dump($op);
-								die('missing u.var');
+								die('missing var');
 							}
-							$T[$op1['u.var']] = $src;
+							$T[$op1['var']] = $src;
 							unset($list);
 						}
@@ -890,5 +934,5 @@
 						$type = $rvalue->iskey ? 'fe_key' : 'fe_as';
 						$rvalue->obj[$type] = $lvalue;
-						unset($T[$op2['u.var']]);
+						unset($T[$op2['var']]);
 						break;
 					}
@@ -976,5 +1020,5 @@
 							$rvalue = "${" . $rvalue . "}";
 						}
-						if ($op2['u.EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
+						if ($op2['EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
 							$class = $this->getOpVal($op2, $EX);
 							$rvalue = $class . '::' . $rvalue;
@@ -987,8 +1031,18 @@
 						$container = $this->getOpVal($op1, $EX);
 						$dim = $this->getOpVal($op2, $EX);
-						$rvalue = $container . "[$dim]";
-					}
-
-					switch (PHP_VERSION < 5 ? $op['op2']['u.var'] /* u.constant */ : $ext) {
+						if ($opc == XC_ISSET_ISEMPTY_PROP_OBJ) {
+							if (preg_match($this->rQuotedName, $dim)) {
+								$rvalue = $container . "->" . substr($dim, 1, -1);
+							}
+							else {
+								$rvalue = $container . "->{" . $dim . "}";
+							}
+						}
+						else {
+							$rvalue = $container . "[$dim]";
+						}
+					}
+
+					switch ((PHP_VERSION < 5 ? $op['op2']['var'] /* constant */ : $ext) & (ZEND_ISSET|ZEND_ISEMPTY)) {
 					case ZEND_ISSET:
 						$rvalue = "isset($rvalue)";
@@ -997,7 +1051,4 @@
 						$rvalue = "empty($rvalue)";
 						break;
-					default:
-						$this->dumpop($op, $EX);
-						die_error('1');
 					}
 					$resvar = $rvalue;
@@ -1012,4 +1063,5 @@
 					break;
 					// }}}
+				case XC_INIT_STATIC_METHOD_CALL:
 				case XC_INIT_METHOD_CALL:
 				case XC_INIT_FCALL_BY_FUNC:
@@ -1018,11 +1070,18 @@
 						break;
 					}
-					array_push($EX['arg_types_stack'], array($EX['object'], $EX['fbc']));
-					if ($opc == XC_INIT_METHOD_CALL || $op1['op_type'] != XC_IS_UNUSED) {
+					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) {
 						$obj = $this->getOpVal($op1, $EX);
 						if (!isset($obj)) {
 							$obj = '$this';
 						}
-						$EX['object'] = $obj;
+						if ($opc == XC_INIT_STATIC_METHOD_CALL || /* PHP4 */ isset($op1['constant'])) {
+							$EX['object'] = null;
+							$EX['called_scope'] = $this->unquoteName($obj);
+						}
+						else {
+							$EX['object'] = $obj;
+							$EX['called_scope'] = null;
+						}
 						if ($res['op_type'] != XC_IS_UNUSED) {
 							$resvar = '$obj call$';
@@ -1031,8 +1090,9 @@
 					else {
 						$EX['object'] = null;
+						$EX['called_scope'] = null;
 					}
 
 					if ($opc == XC_INIT_FCALL_BY_FUNC) {
-						$which = $op1['u.var'];
+						$which = $op1['var'];
 						$EX['fbc'] = $EX['op_array']['funcs'][$which]['name'];
 					}
@@ -1043,5 +1103,5 @@
 					// }}}
 				case XC_DO_FCALL_BY_FUNC:
-					$which = $op1['u.var'];
+					$which = $op1['var'];
 					$fname = $EX['op_array']['funcs'][$which]['name'];
 					$args = $this->popargs($EX, $ext);
@@ -1065,4 +1125,5 @@
 					$resvar =
 						(isset($object) ? $object . '->' : '' )
+						. (isset($EX['called_scope']) ? $EX['called_scope'] . '::' : '' )
 						. $fname . "($args)";
 					unset($args);
@@ -1072,21 +1133,23 @@
 						$resvar = null;
 					}
-					list($EX['object'], $EX['fbc']) = array_pop($EX['arg_types_stack']);
+					list($EX['fbc'], $EX['object'], $EX['called_scope']) = array_pop($EX['arg_types_stack']);
 					break;
 					// }}}
 				case XC_VERIFY_ABSTRACT_CLASS: // {{{
-					//unset($T[$op1['u.var']]);
+					//unset($T[$op1['var']]);
 					break;
 					// }}}
 				case XC_DECLARE_CLASS: 
-				case XC_DECLARE_INHERITED_CLASS: // {{{
-					$key = $op1['u.constant'];
+				case XC_DECLARE_INHERITED_CLASS:
+				case XC_DECLARE_INHERITED_CLASS_DELAYED: // {{{
+					$key = $op1['constant'];
+					if (!isset($this->dc['class_table'][$key])) {
+						echo 'class not found: ', $key, 'existing classes are:', "\n";
+						var_dump(array_keys($this->dc['class_table']));
+						exit;
+					}
 					$class = &$this->dc['class_table'][$key];
-					if (!isset($class)) {
-						echo 'class not found: ' . $key;
-						exit;
-					}
 					$class['name'] = $this->unquoteName($this->getOpVal($op2, $EX));
-					if ($opc == XC_DECLARE_INHERITED_CLASS) {
+					if ($opc == XC_DECLARE_INHERITED_CLASS || $opc == XC_DECLARE_INHERITED_CLASS_DELAYED) {
 						$ext /= XC_SIZEOF_TEMP_VARIABLE;
 						$class['parent'] = $T[$ext];
@@ -1099,5 +1162,5 @@
 					while ($i + 2 < $ic
 					 && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE
-					 && $opcodes[$i + 2]['op1']['u.var'] == $res['u.var']
+					 && $opcodes[$i + 2]['op1']['var'] == $res['var']
 					 && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) {
 						$fetchop = &$opcodes[$i + 1];
@@ -1165,8 +1228,8 @@
 						$offset = $this->getOpVal($op2, $EX);
 						if (isset($offset)) {
-							$T[$res['u.var']]->value[$offset] = $rvalue;
+							$T[$res['var']]->value[$offset] = $rvalue;
 						}
 						else {
-							$T[$res['u.var']]->value[] = $rvalue;
+							$T[$res['var']]->value[] = $rvalue;
 						}
 					}
@@ -1202,5 +1265,5 @@
 					// }}}
 				case XC_INCLUDE_OR_EVAL: // {{{
-					$type = $op2['u.var']; // hack
+					$type = $op2['var']; // hack
 					$keyword = $this->includeTypes[$type];
 					$resvar = "$keyword(" . $this->getOpVal($op1, $EX) . ")";
@@ -1215,5 +1278,5 @@
 					$fe = new Decompiler_ForeachBox($op);
 					$fe->iskey = false;
-					$T[$res['u.var']] = $fe;
+					$T[$res['var']] = $fe;
 
 					++ $i;
@@ -1223,19 +1286,19 @@
 
 						$res = $opcodes[$i]['result'];
-						$T[$res['u.var']] = $fe;
+						$T[$res['var']] = $fe;
 					}
 					break;
 					// }}}
 				case XC_SWITCH_FREE: // {{{
-					// unset($T[$op1['u.var']]);
+					// unset($T[$op1['var']]);
 					break;
 					// }}}
 				case XC_FREE: // {{{
-					$free = $T[$op1['u.var']];
+					$free = $T[$op1['var']];
 					if (!is_a($free, 'Decompiler_Array') && !is_a($free, 'Decompiler_Box')) {
 						$op['php'] = is_object($free) ? $free : $this->unquote($free, '(', ')');
 						$lastphpop = &$op;
 					}
-					unset($T[$op1['u.var']], $free);
+					unset($T[$op1['var']], $free);
 					break;
 					// }}}
@@ -1260,8 +1323,9 @@
 					}
 					if (isset($op['cond_false'])) {
+						echo "TODO(cond_false):\n";
 						var_dump($op);// exit;
 					}
 					if ($opc == XC_JMPZ_EX || $opc == XC_JMPNZ_EX || $opc == XC_JMPZ) {
-						$targetop = &$EX['opcodes'][$op2['u.opline_num']];
+						$targetop = &$EX['opcodes'][$op2['opline_num']];
 						if ($opc == XC_JMPNZ_EX) {
 							$targetop['cond_true'][] = str($rvalue);
@@ -1291,5 +1355,5 @@
 					$lvalue = $this->getOpVal($op['result'], $EX);
 					if ($opc == XC_RECV_INIT) {
-						$default = value($op['op2']['u.constant']);
+						$default = value($op['op2']['constant']);
 					}
 					else {
@@ -1377,6 +1441,6 @@
 			if (isset($resvar)) {
 				if ($istmpres) {
-					$T[$res['u.var']] = $resvar;
-					$lastresvar = &$T[$res['u.var']];
+					$T[$res['var']] = $resvar;
+					$lastresvar = &$T[$res['var']];
 				}
 				else {
@@ -1424,9 +1488,9 @@
 			switch ($op[$k]['op_type']) {
 			case XC_IS_UNUSED:
-				$d[$kk] = '*UNUSED* ' . $op[$k]['u.opline_num'];
+				$d[$kk] = '*UNUSED* ' . $op[$k]['opline_num'];
 				break;
 
 			case XC_IS_VAR:
-				$d[$kk] = '$' . $op[$k]['u.var'];
+				$d[$kk] = '$' . $op[$k]['var'];
 				if ($kk != 'res') {
 					$d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
@@ -1435,5 +1499,5 @@
 
 			case XC_IS_TMP_VAR:
-				$d[$kk] = '#' . $op[$k]['u.var'];
+				$d[$kk] = '#' . $op[$k]['var'];
 				if ($kk != 'res') {
 					$d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
@@ -1608,6 +1672,6 @@
 		if (!empty($class['default_properties'])) {
 			echo "\n";
-			$infos = empty($class['properties_info']) ? null : $class['properties_info'];
-			foreach ($class['default_properties'] as $name => $v) {
+			$infos = !empty($class['properties_info']) ? $class['properties_info'] : null;
+			foreach (!empty($class['properties_info']) ? $class['properties_info'] : ($class['default_static_members'] + $class['default_properties']) as $name => $dummy) {
 				$info = (isset($infos) && isset($infos[$name])) ? $infos[$name] : null;
 				if (isset($info)) {
@@ -1620,4 +1684,19 @@
 
 				echo $newindent;
+				$static = false;
+				if (isset($info)) {
+					if ($info['flags'] & ZEND_ACC_STATIC) {
+						$static = true;
+					}
+				}
+				else if (isset($class['default_static_members'][$name])) {
+					$static = true;
+				}
+
+				if ($static) {
+					echo "static ";
+				}
+
+				$mangled = false;
 				if (PHP_VERSION < 5) {
 					echo 'var ';
@@ -1636,18 +1715,21 @@
 					case ZEND_ACC_PRIVATE:
 						echo "private ";
+						$mangled = true;
 						break;
 					case ZEND_ACC_PROTECTED:
 						echo "protected ";
+						$mangled = true;
 						break;
 					}
-					if ($info['flags'] & ZEND_ACC_STATIC) {
-						echo "static ";
-					}
 				}
 
 				echo '$', $name;
-				if (isset($v)) {
+
+				$key = isset($info) ? $info['name'] . ($mangled ? "\000" : "") : $name;
+
+				$value = $class[$static ? 'default_static_members' : 'default_properties'][$key];
+				if (isset($value)) {
 					echo ' = ';
-					echo str(value($v));
+					echo str(value($value));
 				}
 				echo ";\n";
@@ -1787,4 +1869,5 @@
 define('ZEND_FETCH_CLASS_AUTO',       5);
 define('ZEND_FETCH_CLASS_INTERFACE',  6);
+define('ZEND_FETCH_CLASS_STATIC',     7);
 
 define('ZEND_EVAL',               (1<<0));
@@ -1852,8 +1935,10 @@
 	'XC_ISSET_ISEMPTY_PROP_OBJ' => -1,
 	'XC_ISSET_ISEMPTY_VAR' => -1,
+	'XC_INIT_STATIC_METHOD_CALL' => -1,
 	'XC_INIT_METHOD_CALL' => -1,
 	'XC_VERIFY_ABSTRACT_CLASS' => -1,
 	'XC_DECLARE_CLASS' => -1,
 	'XC_DECLARE_INHERITED_CLASS' => -1,
+	'XC_DECLARE_INHERITED_CLASS_DELAYED' => -1,
 	'XC_ADD_INTERFACE' => -1,
 	'XC_POST_DEC_OBJ' => -1,
Index: /branches/1.3/Makefile.frag
===================================================================
--- /branches/1.3/Makefile.frag	(revision 725)
+++ /branches/1.3/Makefile.frag	(revision 726)
@@ -32,4 +32,7 @@
 disassembler.lo: $(XCACHE_PROC_H) $(srcdir)/processor.c
 
+$(builddir)/opcode_spec.lo: $(srcdir)/xcache.h $(srcdir)/opcode_spec.c $(srcdir)/opcode_spec_def.h $(srcdir)/const_string.h
+opcode_spec.lo: $(srcdir)/xcache.h $(srcdir)/opcode_spec.c $(srcdir)/opcode_spec_def.h $(srcdir)/const_string.h
+
 $(builddir)/xcache.lo: $(XCACHE_PROC_H) $(srcdir)/xc_shm.h $(srcdir)/stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.c $(srcdir)/foreachcoresig.h $(srcdir)/utils.h
 xcache.lo: $(XCACHE_PROC_H) $(srcdir)/xc_shm.h $(srcdir)/stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.c $(srcdir)/foreachcoresig.h $(srcdir)/utils.h
Index: /branches/1.3/NEWS
===================================================================
--- /branches/1.3/NEWS	(revision 725)
+++ /branches/1.3/NEWS	(revision 726)
@@ -1,4 +1,6 @@
 1.3.2 2011-??-??
 ========
+ * memory leak on recompile
+ * disassembler fixes and updates for new PHP
  * win32 build fix
  * improve compatibility with ionCube Loader
Index: /branches/1.3/const_string_opcodes_php6.x.h
===================================================================
--- /branches/1.3/const_string_opcodes_php6.x.h	(revision 725)
+++ /branches/1.3/const_string_opcodes_php6.x.h	(revision 726)
@@ -1,3 +1,3 @@
-/* size = 154 */
+/* size = 157 */
 static const char *const xc_opcode_names[] = {
 /* 0 */	"NOP",
@@ -112,5 +112,5 @@
 /* 109 */	"FETCH_CLASS",
 /* 110 */	"CLONE",
-/* 111 */	"UNDEF",
+/* 111 */	"RETURN_BY_REF",
 /* 112 */	"INIT_METHOD_CALL",
 /* 113 */	"INIT_STATIC_METHOD_CALL",
@@ -152,6 +152,9 @@
 /* 149 */	"HANDLE_EXCEPTION",
 /* 150 */	"USER_OPCODE",
-/* 151 */	"U_NORMALIZE",
+/* 151 */	"UNDEF",
 /* 152 */	"JMP_SET",
-/* 153 */	"DECLARE_LAMBDA_FUNCTION"
+/* 153 */	"DECLARE_LAMBDA_FUNCTION",
+/* 154 */	"ADD_TRAIT",
+/* 155 */	"BIND_TRAITS",
+/* 156 */	"SEPARATE"
 };
Index: /branches/1.3/coverager.c
===================================================================
--- /branches/1.3/coverager.c	(revision 725)
+++ /branches/1.3/coverager.c	(revision 726)
@@ -379,13 +379,11 @@
 static int xc_coverager_get_op_array_size_no_tail(zend_op_array *op_array) /* {{{ */
 {
-	zend_uint size;
-
-	size = op_array->size;
+	zend_uint last = op_array->last;
 	do {
 next_op:
-		if (size == 0) {
+		if (last == 0) {
 			break;
 		}
-		switch (op_array->opcodes[size - 1].opcode) {
+		switch (op_array->opcodes[last - 1].opcode) {
 #ifdef ZEND_HANDLE_EXCEPTION
 			case ZEND_HANDLE_EXCEPTION:
@@ -393,9 +391,9 @@
 			case ZEND_RETURN:
 			case ZEND_EXT_STMT:
-				size --;
+				--last;
 				goto next_op;
 		}
 	} while (0);
-	return size;
+	return last;
 }
 /* }}} */
Index: /branches/1.3/disassembler.c
===================================================================
--- /branches/1.3/disassembler.c	(revision 725)
+++ /branches/1.3/disassembler.c	(revision 726)
@@ -6,8 +6,15 @@
 #define return_value dst
 
+/* sandbox {{{ */
+#undef TG
+#undef OG
+#define TG(x) (sandbox->tmp_##x)
+#define OG(x) (sandbox->orig_##x)
+/* }}} */
+
 #ifndef HAVE_XCACHE_OPCODE_SPEC_DEF
 #error disassembler cannot be built without xcache/opcode_spec_def.h
 #endif
-static void xc_dasm(zval *dst, zend_op_array *op_array TSRMLS_DC) /* {{{ */
+static void xc_dasm(xc_sandbox_t *sandbox, zval *dst, zend_op_array *op_array TSRMLS_DC) /* {{{ */
 {
 	Bucket *b;
@@ -16,5 +23,4 @@
 	int bufsize = 2;
 	char *buf;
-	int keysize;
 
 	xc_compile_result_init_cur(&cr, op_array TSRMLS_CC);
@@ -33,5 +39,12 @@
 	ALLOC_INIT_ZVAL(list);
 	array_init(list);
-	xc_dasm_HashTable_zend_function(list, CG(function_table) TSRMLS_CC);
+	b = TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead;
+	for (; b; b = b->pListNext) {
+		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);
 	
@@ -39,5 +52,8 @@
 	ALLOC_INIT_ZVAL(list);
 	array_init(list);
-	for (b = CG(class_table)->pListHead; b; b = b->pListNext) {
+	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);
@@ -53,9 +69,9 @@
 		memcpy(buf, BUCKET_KEY_S(b), keysize);
 		buf[keysize - 2] = buf[keysize - 1] = ""[0];
-		keysize = b->nKeyLength;
+		keyLength = b->nKeyLength;
 #ifdef IS_UNICODE
 		if (BUCKET_KEY_TYPE(b) == IS_UNICODE) {
 			if (buf[0] == ""[0] && buf[1] == ""[0]) {
-				keysize ++;
+				keyLength ++;
 			}
 		} else
@@ -63,8 +79,8 @@
 		{
 			if (buf[0] == ""[0]) {
-				keysize ++;
+				keyLength ++;
 			}
 		}
-		add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), b->nKeyLength, zv);
+		add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), keyLength, zv);
 	}
 	efree(buf);
@@ -97,5 +113,5 @@
 	}
 
-	xc_dasm(dst, op_array TSRMLS_CC);
+	xc_dasm(&sandbox, dst, op_array TSRMLS_CC);
 
 	/* free */
@@ -142,5 +158,5 @@
 	}
 
-	xc_dasm(dst, op_array TSRMLS_CC);
+	xc_dasm(&sandbox, dst, op_array TSRMLS_CC);
 
 	/* free */
Index: /branches/1.3/mkstructinfo.awk
===================================================================
--- /branches/1.3/mkstructinfo.awk	(revision 725)
+++ /branches/1.3/mkstructinfo.awk	(revision 726)
@@ -50,8 +50,8 @@
 
 			if (i == 0) {
-				elms = buffer[i];
+				elms = "\"" buffer[i] "\"";
 			}
 			else {
-				elms = elms "," buffer[i];
+				elms = elms "," "\"" buffer[i] "\"";
 			}
 		}
Index: /branches/1.3/opcode_spec.c
===================================================================
--- /branches/1.3/opcode_spec.c	(revision 725)
+++ /branches/1.3/opcode_spec.c	(revision 726)
@@ -20,4 +20,9 @@
 const xc_opcode_spec_t *xc_get_opcode_spec(zend_uchar opcode)
 {
+#ifndef NDEBUG
+	if (xc_get_opcode_count() != xc_get_opcode_spec_count()) {
+		fprintf(stderr, "count mismatch: xc_get_opcode_count=%d, xc_get_opcode_spec_count=%d\n", xc_get_opcode_count(), xc_get_opcode_spec_count());
+	}
+#endif
 	assert(xc_get_opcode_count() == xc_get_opcode_spec_count());
 	assert(opcode < xc_get_opcode_spec_count());
Index: /branches/1.3/opcode_spec_def.h
===================================================================
--- /branches/1.3/opcode_spec_def.h	(revision 725)
+++ /branches/1.3/opcode_spec_def.h	(revision 726)
@@ -104,5 +104,5 @@
 #endif
 #ifdef ZEND_ENGINE_2_3
-	OPSPEC(       STD,        STD,        STD,        STD) /* 69 INIT_NS_FCALL_BY_NAME          */
+	OPSPEC(       STD,        STD,        STD,     UNUSED) /* 69 INIT_NS_FCALL_BY_NAME          */
 #else
 	OPSPEC(    UNUSED,        STD,     OPLINE,     UNUSED) /* 69 JMP_NO_CTOR                    */
@@ -147,5 +147,4 @@
 	OPSPEC(    UNUSED,      VAR_2,        STD,        VAR) /* 97 FETCH_OBJ_UNSET                */
 	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 98 FETCH_DIM_TMP_VAR              */
-
 #ifdef ZEND_ENGINE_2
 	OPSPEC(    UNUSED,     UCLASS,        STD,        TMP) /* 99 FETCH_CONSTANT                 */
@@ -153,5 +152,9 @@
 	OPSPEC(    UNUSED,        STD,     UNUSED,        TMP) /* 99 FETCH_CONSTANT                 */
 #endif
+#ifdef ZEND_ENGINE_2_3
+	OPSPEC(       STD,    JMPADDR,        STD,     UNUSED) /* 100 GOTO                           */
+#else
 	OPSPEC(   DECLARE,        STD,        STD,     UNUSED) /* 100 DECLARE_FUNCTION_OR_CLASS      */
+#endif
 	OPSPEC(       STD,        STD,        STD,        STD) /* 101 EXT_STMT                       */
 	OPSPEC(       STD,        STD,        STD,        STD) /* 102 EXT_FCALL_BEGIN                */
@@ -165,9 +168,16 @@
 	OPSPEC(    FCLASS,        STD,        STD,      CLASS) /* 109 FETCH_CLASS                    */
 	OPSPEC(    UNUSED,        STD,     UNUSED,        VAR) /* 110 CLONE                          */
+
 	OPSPEC(    UNUSED,        STD,     UNUSED,     UNUSED) /* 111 INIT_CTOR_CALL                 */
+
 	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 112 INIT_METHOD_CALL               */
+#	ifdef ZEND_ENGINE_2_3
+	OPSPEC(    UNUSED,        STD,        STD,     UNUSED) /* 113 INIT_STATIC_METHOD_CALL        */
+#	else
 	OPSPEC(    UNUSED,     UCLASS,        STD,     UNUSED) /* 113 INIT_STATIC_METHOD_CALL        */
+#	endif
 	OPSPEC(     ISSET,        STD,      FETCH,        TMP) /* 114 ISSET_ISEMPTY_VAR              */
 	OPSPEC(     ISSET,        STD,        STD,        TMP) /* 115 ISSET_ISEMPTY_DIM_OBJ          */
+
 	OPSPEC(    UNUSED,      CLASS,        STD,     UNUSED) /* 116 IMPORT_FUNCTION                */
 	OPSPEC(    UNUSED,      CLASS,        STD,     UNUSED) /* 117 IMPORT_CLASS                   */
@@ -186,4 +196,5 @@
 	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 130 ASSIGN_BW_AND_OBJ              */
 	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 131 ASSIGN_BW_XOR_OBJ              */
+
 	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 132 PRE_INC_OBJ                    */
 	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 133 PRE_DEC_OBJ                    */
@@ -200,18 +211,37 @@
 	OPSPEC(   DECLARE,        STD,        STD,     UNUSED) /* 143 DECLARE_CONST                  */
 #else
-	OPSPEC(    UNUSED,        STD,     UNUSED,     UNUSED) /* 143 START_NAMESPACE                */
-#endif
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 143 UNDEF-143                      */
+#endif
+#ifdef ZEND_ENGINE_2_3
+	OPSPEC(     IFACE,      CLASS,        STD,     UNUSED) /* 144 ADD_INTERFACE                  */
+#else
 	OPSPEC(     IFACE,      CLASS,      CLASS,     UNUSED) /* 144 ADD_INTERFACE                  */
+#endif
+#ifdef ZEND_ENGINE_2_3
+	OPSPEC(     CLASS,        STD,        STD,     OPLINE) /* 145 DECLARE_INHERITED_CLASS_DELAYED */
+#else
 	OPSPEC(    UNUSED,      CLASS,        STD,     UNUSED) /* 145 VERIFY_INSTANCEOF              */
+#endif
 	OPSPEC(    UNUSED,      CLASS,     UNUSED,     UNUSED) /* 146 VERIFY_ABSTRACT_CLASS          */
 	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 147 ASSIGN_DIM                     */
 	OPSPEC(     ISSET,        STD,        STD,        TMP) /* 148 ISSET_ISEMPTY_PROP_OBJ         */
 	OPSPEC(       STD,     UNUSED,     UNUSED,        STD) /* 149 HANDLE_EXCEPTION               */
+	OPSPEC(       STD,     UNUSED,     UNUSED,        STD) /* 150 USER_OPCODE                    */
 # ifdef ZEND_ENGINE_2_3
-	OPSPEC(       STD,     UNUSED,     UNUSED,        STD) /* 150 ZEND_USER_OPCODE               */
 	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 151 UNDEF                          */
-	OPSPEC(    UNUSED,        STD,    JMPADDR,     UNUSED) /* 152 JMP_SET                        */
-	OPSPEC(    UNUSED,        STD,        STD,     UNUSED) /* 153 DECLARE_LAMBDA_FUNCTION        */
+	OPSPEC(    UNUSED,        STD,    JMPADDR,        TMP) /* 152 JMP_SET                        */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 153 DECLARE_LAMBDA_FUNCTION        */
+# else
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 151 UNDEF                          */
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 152 UNDEF                          */
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 153 UNDEF                          */
 # endif
+#else
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 107 UNDEF                          */
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 108 UNDEF                          */
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 109 UNDEF                          */
+	OPSPEC(     FCALL,        STD,     OPLINE,        VAR) /* 61 DO_FCALL_BY_FUNC                */
+	OPSPEC(INIT_FCALL,        STD,        STD,     UNUSED) /* 111 INIT_FCALL_BY_FUNC             */
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 112 UNDEF                          */
 #endif
 };
Index: /branches/1.3/processor/hashtable.m4
===================================================================
--- /branches/1.3/processor/hashtable.m4	(revision 725)
+++ /branches/1.3/processor/hashtable.m4	(revision 726)
@@ -65,5 +65,4 @@
 
 			efree(buf);
-			return; /* no check size */
 		', `
 		dnl }}}
Index: /branches/1.3/processor/head.m4
===================================================================
--- /branches/1.3/processor/head.m4	(revision 725)
+++ /branches/1.3/processor/head.m4	(revision 726)
@@ -299,4 +299,47 @@
 }
 /* }}} */
+/* {{{ field name checker */
+IFASSERT(`dnl
+int xc_check_names(const char *file, int line, const char *functionName, const char **assert_names, int assert_names_count, HashTable *done_names)
+{
+	int errors = 0;
+	if (assert_names_count) {
+		int i;
+		Bucket *b;
+
+		for (i = 0; i < assert_names_count; ++i) {
+			if (!zend_hash_exists(done_names, assert_names[i], strlen(assert_names[i]) + 1)) {
+				fprintf(stderr
+					, "missing field at %s `#'%d %s`' : %s\n"
+					, file, line, functionName
+					, assert_names[i]
+					);
+				++errors;
+			}
+		}
+
+		for (b = done_names->pListHead; b != NULL; b = b->pListNext) {
+			int known = 0;
+			int i;
+			for (i = 0; i < assert_names_count; ++i) {
+				if (strcmp(assert_names[i], BUCKET_KEY_S(b)) == 0) {
+					known = 1;
+					break;
+				}
+			}
+			if (!known) {
+				fprintf(stderr
+					, "unknown field at %s `#'%d %s`' : %s\n"
+					, file, line, functionName
+					, BUCKET_KEY_S(b)
+					);
+				++errors;
+			}
+		}
+	}
+	return errors;
+}
+')
+/* }}} */
 dnl ================ export API
 /* export: xc_entry_t *xc_processor_store_xc_entry_t(xc_entry_t *src TSRMLS_DC); :export {{{ */
Index: /branches/1.3/processor/main.m4
===================================================================
--- /branches/1.3/processor/main.m4	(revision 725)
+++ /branches/1.3/processor/main.m4	(revision 726)
@@ -164,13 +164,4 @@
 dnl }}}
 dnl {{{ COPYNULL(1:elm)
-# foreach(VAR, (LIST), STMT)
-m4_define([foreach],
-       [m4_pushdef([$1])_foreach([$1], [$2], [$3])m4_popdef([$1])])
-m4_define([_arg1], [$1])
-m4_define([_foreach],
-       [ifelse([$2], [()], ,
-       [m4_define([$1], _arg1$2)$3[]_foreach([$1],
-                                                       (shift$2),
-                                                       [$3])])])
 define(`COPYNULL', `
 	COPYNULL_EX(`dst->$1', `$2')DONE(`$1')
@@ -195,10 +186,23 @@
 dnl }}}
 dnl {{{ DONE_*
-define(`DONE_SIZE', `IFASSERT(`
+define(`DONE_SIZE', `IFASSERT(`dnl
 	done_size += $1`';
 	done_count ++;
 ')')
 define(`DONE', `
-	define(`ELEMENTS_DONE', defn(`ELEMENTS_DONE')`,$1')
+	define(`ELEMENTS_DONE', defn(`ELEMENTS_DONE')`,"$1"')
+	IFASSERT(`dnl
+		if (zend_hash_exists(&done_names, "$1", sizeof("$1"))) {
+			fprintf(stderr
+				, "duplicate field at %s `#'%d FUNC_NAME`' : %s\n"
+				, __FILE__, __LINE__
+				, "$1"
+				);
+		}
+		else {
+			zend_uchar b = 1;
+			zend_hash_add(&done_names, "$1", sizeof("$1"), (void*)&b, sizeof(b), NULL);
+		}
+	')
 	DONE_SIZE(`sizeof(src->$1)')
 ')
Index: /branches/1.3/processor/processor.m4
===================================================================
--- /branches/1.3/processor/processor.m4	(revision 725)
+++ /branches/1.3/processor/processor.m4	(revision 726)
@@ -85,5 +85,4 @@
 #endif
 	} while(0);
-	return;
 	', `
 		dnl IFDASM else
@@ -223,9 +222,15 @@
 	DISPATCH(zend_uint, class_name_len)
 	PROC_ZSTRING_L(, class_name, class_name_len)
+#ifdef ZEND_ENGINE_2_4
+	DISPATCH(zend_uchar, type_hint)
+#else
 	DISPATCH(zend_bool, array_type_hint)
+#endif
 	DISPATCH(zend_bool, allow_null)
 	DISPATCH(zend_bool, pass_by_reference)
+#ifndef ZEND_ENGINE_2_4
 	DISPATCH(zend_bool, return_reference)
 	DISPATCH(int, required_num_args)
+#endif
 ')
 #endif
@@ -273,4 +278,7 @@
 	PROC_ZSTRING_L(, name, name_length)
 	DISPATCH(ulong, h)
+#ifdef ZEND_ENGINE_2_4
+	DISPATCH(int, offset)
+#endif
 #ifdef ZEND_ENGINE_2_1
 	DISPATCH(int, doc_comment_len)
@@ -285,4 +293,5 @@
 dnl }}}
 DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{
+	int i;
 	IFCALCCOPY(`
 		processor->active_class_entry_src = src;
@@ -307,31 +316,57 @@
 	STRUCT_P(int, refcount)
 #endif
+#ifndef ZEND_ENGINE_2_4
 	DISPATCH(zend_bool, constants_updated)
+#endif
 #ifdef ZEND_ENGINE_2
 	DISPATCH(zend_uint, ce_flags)
 #endif
 
-	STRUCT(HashTable, default_properties, HashTable_zval_ptr)
+#ifdef ZEND_ENGINE_2_4
+	DISPATCH(int, default_properties_count)
+	STRUCT_ARRAY(default_properties_count, zval, default_properties_table)
+	DISPATCH(int, default_static_members_count)
+	STRUCT_ARRAY(default_static_members_count, zval, default_static_members_table)
+	IFCOPY(`dst->static_members_table = &dst->default_static_members_table;')
+	DONE(static_members_table)
+#else
 	IFCOPY(`dst->builtin_functions = src->builtin_functions;')
 	DONE(builtin_functions)
-#ifdef ZEND_ENGINE_2
+	STRUCT(HashTable, default_properties, HashTable_zval_ptr)
+#	ifdef ZEND_ENGINE_2
 	STRUCT(HashTable, properties_info, HashTable_zend_property_info)
-#	ifdef ZEND_ENGINE_2_1
+#		ifdef ZEND_ENGINE_2_1
 	STRUCT(HashTable, default_static_members, HashTable_zval_ptr)
 	IFCOPY(`dst->static_members = &dst->default_static_members;')
 	DONE(static_members)
-#	else
+#		else
 	STRUCT_P(HashTable, static_members, HashTable_zval_ptr)
-#	endif
+#		endif
+#	endif
+#endif /* ZEND_ENGINE_2_4 */
+
+#ifdef ZEND_ENGINE_2
 	STRUCT(HashTable, constants_table, HashTable_zval_ptr)
 
 	dnl runtime binding: ADD_INTERFACE will deal with it
+	dnl runtime binding: ADD_TRAIT will deal with it
 	IFRESTORE(`
 		if (src->num_interfaces) {
 			CALLOC(dst->interfaces, zend_class_entry*, src->num_interfaces)
 			DONE(`interfaces')
+#	ifdef ZEND_ENGINE_2_4
+			CALLOC(dst->traits, zend_class_entry*, src->num_traits)
+			DONE(`traits')
+			DONE(`trait_aliases')
+			DONE(`trait_precedences')
+#	endif
 		}
 		else {
-			COPYNULL(interfaces)
+			COPYNULL(`interfaces')
+#	ifdef ZEND_ENGINE_2_4
+			COPYNULL(`traits')
+			COPYNULL(`trait_aliases')
+			COPYNULL(`trait_precedences')
+#	endif
 		}
 	')
@@ -350,7 +385,17 @@
 			*/
 			DONE(`interfaces')
+#	ifdef ZEND_ENGINE_2_4
+			DONE(`traits')
+			DONE(`trait_aliases')
+			DONE(`trait_precedences')
+#	endif
 		}
 		else {
-			COPYNULL(interfaces)
+			COPYNULL(`interfaces')
+#	ifdef ZEND_ENGINE_2_4
+			COPYNULL(`traits')
+			COPYNULL(`trait_aliases')
+			COPYNULL(`trait_precedences')
+#	endif
 		}
 	')
@@ -358,15 +403,35 @@
 		IFDASM(`', `
 			DONE(`interfaces')
+#	ifdef ZEND_ENGINE_2_4
+			DONE(`traits')
+			DONE(`trait_aliases')
+			DONE(`trait_precedences')
+#	endif
 		')
 	')
 	DISPATCH(zend_uint, num_interfaces)
-
+#	ifdef ZEND_ENGINE_2_4
+	DISPATCH(zend_uint, num_traits)
+#	endif
+
+#	ifdef ZEND_ENGINE_2_4
+	DISABLECHECK(`
+	IFRESTORE(`COPY(info.user.filename)', `PROC_STRING(info.user.filename)')
+	DISPATCH(zend_uint, info.user.line_start)
+	DISPATCH(zend_uint, info.user.line_end)
+	DISPATCH(zend_uint, info.user.doc_comment_len)
+	PROC_ZSTRING_L(, info.user.doc_comment, info.user.doc_comment_len)
+	')
+	DONE(info)
+#	else
 	IFRESTORE(`COPY(filename)', `PROC_STRING(filename)')
 	DISPATCH(zend_uint, line_start)
 	DISPATCH(zend_uint, line_end)
-#ifdef ZEND_ENGINE_2_1
+#		ifdef ZEND_ENGINE_2_1
 	DISPATCH(zend_uint, doc_comment_len)
 	PROC_ZSTRING_L(, doc_comment, doc_comment_len)
-#endif
+#		endif
+#	endif
+
 	/* # NOT DONE */
 	COPY(serialize_func)
@@ -376,7 +441,7 @@
 	COPY(get_iterator)
 	COPY(interface_gets_implemented)
-#ifdef ZEND_ENGINE_2_3
+#	ifdef ZEND_ENGINE_2_3
 	COPY(get_static_method)
-#endif
+#	endif
 	COPY(serialize)
 	COPY(unserialize)
@@ -388,18 +453,20 @@
 	COPY(__set)
 /* should be >5.1 */
-#ifdef ZEND_ENGINE_2_1
+#	ifdef ZEND_ENGINE_2_1
 	COPY(__unset)
 	COPY(__isset)
-# if defined(ZEND_ENGINE_2_2) || PHP_MAJOR_VERSION >= 6
+#	 if defined(ZEND_ENGINE_2_2) || PHP_MAJOR_VERSION >= 6
 	COPY(__tostring)
-# endif
-#endif
+#	 endif
+#	endif
 	COPY(__call)
-#ifdef ZEND_CALLSTATIC_FUNC_NAME
+#	ifdef ZEND_CALLSTATIC_FUNC_NAME
 	COPY(__callstatic)
-#endif
+#	endif
+#	ifndef ZEND_ENGINE_2_4
 	/* # NOT DONE */
 	COPY(module)
-#else
+#	endif
+#else /* ZEND_ENGINE_2 */
 	COPY(handle_function_call)
 	COPY(handle_property_get)
@@ -415,4 +482,50 @@
 ')
 dnl }}}
+#ifdef ZEND_ENGINE_2_4
+undefine(`UNION_znode_op')
+define(`UNION_znode_op', `dnl {{{
+	assert(src->$1_type == IS_CONST ||
+		src->$1_type == IS_VAR ||
+		src->$1_type == IS_CV ||
+		src->$1_type == IS_TMP_VAR ||
+		src->$1_type == IS_UNUSED);
+	dnl dirty dispatch
+	DISABLECHECK(`
+	switch (src->$1_type) {
+		case IS_CONST:
+			dnl TODO: fix me, use literals
+			IFDASM(`{
+				zval *zv;
+				ALLOC_INIT_ZVAL(zv);
+				*zv = ((zend_literal *) src->$1.ptr)->constant;
+				zval_copy_ctor(zv);
+				add_assoc_zval_ex(dst, ZEND_STRS("$1.constant"), zv);
+				}
+			', `
+				DISPATCH(zend_uint, $1.constant)
+			')
+			break;
+		IFCOPY(`
+			IFNOTMEMCPY(`
+				default:
+					*dst = *src;
+			')
+		', `
+		case IS_VAR:
+		case IS_TMP_VAR:
+		case IS_CV:
+			DISPATCH(zend_uint, $1.var)
+			break;
+		case IS_UNUSED:
+			IFDASM(`DISPATCH(zend_uint, $1.var)')
+			DISPATCH(zend_uint, $1.opline_num)
+			break;
+		')
+	}
+	')
+	DONE($1)
+')
+dnl }}}
+#else
 DEF_STRUCT_P_FUNC(`znode', , `dnl {{{
 	DISPATCH(int, op_type)
@@ -459,15 +572,30 @@
 	')
 	DONE(u)
+#if 0
+	DONE(EA)
+#endif
 #undef XCACHE_IS_CV
 ')
 dnl }}}
+#endif
 DEF_STRUCT_P_FUNC(`zend_op', , `dnl {{{
 	DISPATCH(zend_uchar, opcode)
+#ifdef ZEND_ENGINE_2_4
+	UNION_znode_op(result)
+	UNION_znode_op(op1)
+	UNION_znode_op(op2)
+#else
 	STRUCT(znode, result)
 	STRUCT(znode, op1)
 	STRUCT(znode, op2)
+#endif
 	DISPATCH(ulong, extended_value)
 	DISPATCH(uint, lineno)
 #ifdef ZEND_ENGINE_2_1
+#ifdef ZEND_ENGINE_2_4
+	DISPATCH(zend_uchar, op1_type)
+	DISPATCH(zend_uchar, op2_type)
+	DISPATCH(zend_uchar, result_type)
+#endif
 	IFCOPY(`
 		switch (src->opcode) {
@@ -476,5 +604,5 @@
 #endif
 			case ZEND_JMP:
-				dst->op1.u.jmp_addr = processor->active_opcodes_dst + (src->op1.u.jmp_addr - processor->active_opcodes_src);
+				Z_OP(dst->op1).jmp_addr = processor->active_opcodes_dst + (Z_OP(src->op1).jmp_addr - processor->active_opcodes_src);
 				break;
 
@@ -486,5 +614,5 @@
 			case ZEND_JMP_SET:
 #endif
-				dst->op2.u.jmp_addr = processor->active_opcodes_dst + (src->op2.u.jmp_addr - processor->active_opcodes_src);
+				Z_OP(dst->op2).jmp_addr = processor->active_opcodes_dst + (Z_OP(src->op2).jmp_addr - processor->active_opcodes_src);
 				break;
 
@@ -497,4 +625,12 @@
 ')
 dnl }}}
+#ifdef ZEND_ENGINE_2_4
+DEF_STRUCT_P_FUNC(`zend_literal', , `dnl {{{
+	STRUCT(zval, constant)
+	DISPATCH(zend_ulong, hash_value)
+	DISPATCH(zend_uint,  cache_slot)
+')
+dnl }}}
+#endif
 DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
 	IFRESTORE(`
@@ -535,5 +671,7 @@
 	DISPATCH(zend_uint, num_args)
 	DISPATCH(zend_uint, required_num_args)
+#	ifndef ZEND_ENGINE_2_4
 	DISPATCH(zend_bool, pass_rest_by_reference)
+#	endif
 #else
 	if (src->arg_types) {
@@ -541,5 +679,4 @@
 		IFCOPY(`memcpy(dst->arg_types, src->arg_types, sizeof(src->arg_types[0]) * (src->arg_types[0]+1));')
 		IFDASM(`do {
-			zend_uint ii;
 			int i;
 			zval *zv;
@@ -567,5 +704,7 @@
 	}
 #endif
+#ifndef ZEND_ENGINE_2_4
 	DISPATCH(unsigned char, return_reference)
+#endif
 	/* END of common elements */
 #ifdef IS_UNICODE
@@ -584,10 +723,14 @@
 	popdef(`AFTER_ALLOC')
 	DISPATCH(zend_uint, last)
+#ifndef ZEND_ENGINE_2_4
 	IFCOPY(`dst->size = src->last;DONE(size)', `DISPATCH(zend_uint, size)')
+#endif
 
 #ifdef IS_CV
 	STRUCT_ARRAY(last_var, zend_compiled_variable, vars)
 	DISPATCH(int, last_var)
+#	ifndef ZEND_ENGINE_2_4
 	IFCOPY(`dst->size_var = src->last_var;DONE(size_var)', `DISPATCH(zend_uint, size_var)')
+#	endif
 #else
 	dnl zend_cv.m4 is illegal to be made public, don not ask me for it
@@ -601,5 +744,7 @@
 	STRUCT_ARRAY_I(last_brk_cont, zend_brk_cont_element, brk_cont_array)
 	DISPATCH(zend_uint, last_brk_cont)
+#ifndef ZEND_ENGINE_2_4
 	DISPATCH(zend_uint, current_brk_cont)
+#endif
 #ifndef ZEND_ENGINE_2
 	DISPATCH(zend_bool, uses_globals)
@@ -613,11 +758,15 @@
 	STRUCT_P(HashTable, static_variables, HashTable_zval_ptr)
 
+#ifndef ZEND_ENGINE_2_4
 	COPY(start_op)
 	DISPATCH(int, backpatch_count)
+#endif
 #ifdef ZEND_ENGINE_2_3
 	DISPATCH(zend_uint, this_var)
 #endif
 
+#ifndef ZEND_ENGINE_2_4
 	DISPATCH(zend_bool, done_pass_two)
+#endif
 	/* 5.0 <= ver < 5.3 */
 #if defined(ZEND_ENGINE_2) && !defined(ZEND_ENGINE_2_3)
@@ -647,4 +796,11 @@
 #if defined(HARDENING_PATCH) && HARDENING_PATCH
 	DISPATCH(zend_bool, created_by_eval)
+#endif
+#ifdef ZEND_ENGINE_2_4
+	DISPATCH(int, last_literal)
+	IFRESTORE(`COPY(literals)', `STRUCT_ARRAY_I(last_literal, zend_literal, literals)')
+
+	COPYNULL(run_time_cache)
+	COPYNULL(last_cache_slot)
 #endif
 	} while (0);
@@ -680,4 +836,5 @@
 			')
 	')
+
 #endif
 
Index: /branches/1.3/processor/struct.m4
===================================================================
--- /branches/1.3/processor/struct.m4	(revision 725)
+++ /branches/1.3/processor/struct.m4	(revision 726)
@@ -30,9 +30,8 @@
 	{
 		pushdef(`ELEMENTS_DONE')
-		ifdef(`SIZEOF_$1', , `m4_errprint(`AUTOCHECK WARN: $1: missing structinfo, dont panic')define(`SIZEOF_$1', 0)')
 		IFASSERT(`
 			/* {{{ init assert */
-			ifdef(`SIZEOF_$1', , `m4_errprint(`missing SIZEOF_$1, safe to ignore')define(`SIZEOF_$1', 0)')
-			ifdef(`COUNTOF_$1', , `m4_errprint(`missing COUNTOF_$1, safe to ignore')define(`COUNTOF_$1', 0)')
+			ifdef(`SIZEOF_$1', , `m4_errprint(`missing SIZEOF_$1, safe to ignore')')
+			ifdef(`COUNTOF_$1', , `m4_errprint(`missing COUNTOF_$1, safe to ignore'))')
 			dnl SIZEOF_x COUNTOF_x can be both defined or both not
 			ifdef(`SIZEOF_$1', `
@@ -48,4 +47,7 @@
 			int assert_size = SIZEOF_$1, assert_count = COUNTOF_$1;
 			int done_size = 0, done_count = 0;
+			const char *assert_names[] = { ifdef(`ELEMENTSOF_$1', `ELEMENTSOF_$1') };
+			HashTable done_names;
+			zend_hash_init(&done_names, 0, NULL, NULL, 0);
 			/* }}} */
 			IFRESTORE(`assert(xc_is_shm(src));')
@@ -53,4 +55,5 @@
 			do {
 		')
+		ifdef(`SIZEOF_$1', , `m4_errprint(`AUTOCHECK WARN: $1: missing structinfo, dont panic')')
 
 		ifdef(`USEMEMCPY', `IFCOPY(`
@@ -68,7 +71,15 @@
 			INDENT()fprintf(stderr, "}\n");
 		')
-		ifdef(`SKIPASSERT_ONCE', `undefine(`SKIPASSERT_ONCE')', `
+		ifdef(`SKIPASSERT_ONCE', `
+			undefine(`SKIPASSERT_ONCE')
 			IFASSERT(`
-				/* {{{ check assert */
+				zend_hash_destroy(&done_names);
+			')
+		', `
+			IFASSERT(`
+			/* {{{ check assert */ do {
+				int name_check_errors = xc_check_names(__FILE__, __LINE__, "FUNC_NAME", assert_names, sizeof(assert_names) / sizeof(assert_names[0]), &done_names);
+				zend_hash_destroy(&done_names);
+
 				if (done_count != assert_count) {
 					fprintf(stderr
@@ -85,8 +96,8 @@
 						);
 				}
-				if (done_count != assert_count || done_size != assert_size) {
+				if (name_check_errors || done_count != assert_count || done_size != assert_size) {
 					assert(0);
 				}
-				/* }}} */
+			} while (0); /* }}} */
 			')
 			ifdef(`ELEMENTSOF_$1', `
Index: /branches/1.3/utils.c
===================================================================
--- /branches/1.3/utils.c	(revision 725)
+++ /branches/1.3/utils.c	(revision 726)
@@ -20,6 +20,6 @@
 
 #define OP_ZVAL_DTOR(op) do { \
-	Z_UNSET_ISREF((op).u.constant); \
-	zval_dtor(&(op).u.constant); \
+	Z_UNSET_ISREF(Z_OP_CONSTANT(op)); \
+	zval_dtor(&Z_OP_CONSTANT(op)); \
 } while(0)
 xc_compile_result_t *xc_compile_result_init(xc_compile_result_t *cr, /* {{{ */
@@ -135,7 +135,9 @@
 	zend_op *opline, *end;
 
+#ifndef ZEND_ENGINE_2_4
 	if (!op_array->done_pass_two) {
 		return 0;
 	}
+#endif
 
 	opline = op_array->opcodes;
@@ -148,6 +150,6 @@
 #endif
 			case ZEND_JMP:
-				opline->op1.u.opline_num = opline->op1.u.jmp_addr - op_array->opcodes;
-				assert(opline->op1.u.opline_num < op_array->last);
+				Z_OP(opline->op1).opline_num = Z_OP(opline->op1).jmp_addr - op_array->opcodes;
+				assert(Z_OP(opline->op1).opline_num < op_array->last);
 				break;
 			case ZEND_JMPZ:
@@ -158,6 +160,6 @@
 			case ZEND_JMP_SET:
 #endif
-				opline->op2.u.opline_num = opline->op2.u.jmp_addr - op_array->opcodes;
-				assert(opline->op2.u.opline_num < op_array->last);
+				Z_OP(opline->op2).opline_num = Z_OP(opline->op2).jmp_addr - op_array->opcodes;
+				assert(Z_OP(opline->op2).opline_num < op_array->last);
 				break;
 		}
@@ -165,5 +167,7 @@
 		opline++;
 	}
+#ifndef ZEND_ENGINE_2_4
 	op_array->done_pass_two = 0;
+#endif
 
 	return 0;
@@ -174,7 +178,9 @@
 	zend_op *opline, *end;
 
+#ifndef ZEND_ENGINE_2_4
 	if (op_array->done_pass_two) {
 		return 0;
 	}
+#endif
 
 	/*
@@ -186,12 +192,12 @@
 	end = opline + op_array->last;
 	while (opline < end) {
-		if (opline->op1.op_type == IS_CONST) {
-			Z_SET_ISREF(opline->op1.u.constant);
-			Z_SET_REFCOUNT(opline->op1.u.constant, 2); /* Make sure is_ref won't be reset */
-
-		}
-		if (opline->op2.op_type == IS_CONST) {
-			Z_SET_ISREF(opline->op2.u.constant);
-			Z_SET_REFCOUNT(opline->op2.u.constant, 2);
+		if (Z_OP_TYPE(opline->op1) == IS_CONST) {
+			Z_SET_ISREF(Z_OP_CONSTANT(opline->op1));
+			Z_SET_REFCOUNT(Z_OP_CONSTANT(opline->op1), 2); /* Make sure is_ref won't be reset */
+
+		}
+		if (Z_OP_TYPE(opline->op2) == IS_CONST) {
+			Z_SET_ISREF(Z_OP_CONSTANT(opline->op2));
+			Z_SET_REFCOUNT(Z_OP_CONSTANT(opline->op2), 2);
 		}
 #ifdef ZEND_ENGINE_2_1
@@ -201,6 +207,6 @@
 #endif
 			case ZEND_JMP:
-				assert(opline->op1.u.opline_num < op_array->last);
-				opline->op1.u.jmp_addr = op_array->opcodes + opline->op1.u.opline_num;
+				assert(Z_OP(opline->op1).opline_num < op_array->last);
+				Z_OP(opline->op1).jmp_addr = op_array->opcodes + Z_OP(opline->op1).opline_num;
 				break;
 			case ZEND_JMPZ:
@@ -211,6 +217,6 @@
 			case ZEND_JMP_SET:
 #endif
-				assert(opline->op2.u.opline_num < op_array->last);
-				opline->op2.u.jmp_addr = op_array->opcodes + opline->op2.u.opline_num;
+				assert(Z_OP(opline->op2).opline_num < op_array->last);
+				Z_OP(opline->op2).jmp_addr = op_array->opcodes + Z_OP(opline->op2).opline_num;
 				break;
 		}
@@ -220,5 +226,7 @@
 	}
 
+#ifndef ZEND_ENGINE_2_4
 	op_array->done_pass_two = 1;
+#endif
 	return 0;
 }
@@ -226,11 +234,11 @@
 
 #ifdef HAVE_XCACHE_OPCODE_SPEC_DEF
-static void xc_fix_opcode_ex_znode(int tofix, xc_op_spec_t spec, znode *znode, int type TSRMLS_DC) /* {{{ */
+static void xc_fix_opcode_ex_znode(int tofix, xc_op_spec_t spec, zend_uchar *op_type, znode_op *op, int type TSRMLS_DC) /* {{{ */
 {
 #ifdef ZEND_ENGINE_2
-	if ((znode->op_type != IS_UNUSED && (spec == OPSPEC_UCLASS || spec == OPSPEC_CLASS)) ||
+	if ((*op_type != IS_UNUSED && (spec == OPSPEC_UCLASS || spec == OPSPEC_CLASS)) ||
 			spec == OPSPEC_FETCH) {
 		if (tofix) {
-			switch (znode->op_type) {
+			switch (*op_type) {
 			case IS_VAR:
 			case IS_TMP_VAR:
@@ -239,17 +247,17 @@
 			default:
 				/* TODO: data lost, find a way to keep it */
-				/* assert(znode->op_type == IS_CONST); */
-				znode->op_type = IS_TMP_VAR;
+				/* assert(*op_type == IS_CONST); */
+				*op_type = IS_TMP_VAR;
 			}
 		}
 	}
-	switch (znode->op_type) {
+	switch (*op_type) {
 	case IS_TMP_VAR:
 	case IS_VAR:
 		if (tofix) {
-			znode->u.var /= sizeof(temp_variable);
+			Z_OP(*op).var /= sizeof(temp_variable);
 		}
 		else {
-			znode->u.var *= sizeof(temp_variable);
+			Z_OP(*op).var *= sizeof(temp_variable);
 		}
 	}
@@ -270,7 +278,7 @@
 			spec = xc_get_opcode_spec(opline->opcode);
 
-			xc_fix_opcode_ex_znode(tofix, spec->op1, &opline->op1, 0 TSRMLS_CC);
-			xc_fix_opcode_ex_znode(tofix, spec->op2, &opline->op2, 1 TSRMLS_CC);
-			xc_fix_opcode_ex_znode(tofix, spec->res, &opline->result, 2 TSRMLS_CC);
+			xc_fix_opcode_ex_znode(tofix, spec->op1, &Z_OP_TYPE(opline->op1),    &opline->op1, 0 TSRMLS_CC);
+			xc_fix_opcode_ex_znode(tofix, spec->op2, &Z_OP_TYPE(opline->op2),    &opline->op2, 1 TSRMLS_CC);
+			xc_fix_opcode_ex_znode(tofix, spec->res, &Z_OP_TYPE(opline->result), &opline->result, 2 TSRMLS_CC);
 		}
 	}
@@ -304,9 +312,9 @@
 #endif
 			case ZEND_JMP:
-				next = begin + opline->op1.u.opline_num;
+				next = begin + Z_OP(opline->op1).opline_num;
 				break;
 
 			case ZEND_JMPZNZ:
-				next = begin + max(opline->op2.u.opline_num, opline->extended_value);
+				next = begin + max(Z_OP(opline->op2).opline_num, opline->extended_value);
 				break;
 
@@ -318,5 +326,5 @@
 			case ZEND_JMP_SET:
 #endif
-				next = begin + opline->op2.u.opline_num;
+				next = begin + Z_OP(opline->op2).opline_num;
 				break;
 
@@ -371,5 +379,5 @@
 			}
 
-			parent_name = &(opline - 1)->op2.u.constant;
+			parent_name = &(Z_OP_CONSTANT((opline - 1)->op2));
 			TRACE("binding with parent %s", Z_STRVAL_P(parent_name));
 			if (zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) {
@@ -387,5 +395,5 @@
 			zend_op *fetch_class_opline = opline - 1;
 
-			TRACE("%s %p", Z_STRVAL(fetch_class_opline->op2.u.constant), Z_STRVAL(fetch_class_opline->op2.u.constant));
+			TRACE("%s %p", Z_STRVAL(Z_OP_CONSTANT(fetch_class_opline->op2)), Z_STRVAL(Z_OP_CONSTANT(fetch_class_opline->op2)));
 			OP_ZVAL_DTOR(fetch_class_opline->op2);
 			fetch_class_opline->opcode = ZEND_NOP;
@@ -421,5 +429,5 @@
 	}
 
-	zend_hash_del(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len);
+	zend_hash_del(class_table, Z_OP_CONSTANT(opline->op1).value.str.val, Z_OP_CONSTANT(opline->op1).value.str.len);
 	OP_ZVAL_DTOR(opline->op1);
 	OP_ZVAL_DTOR(opline->op2);
@@ -512,5 +520,5 @@
 				ZESW(&stored_ce_ptr, NULL)
 				) == FAILURE) {
-		CG(zend_lineno) = ZESW(0, cep->line_start);
+		CG(zend_lineno) = ZESW(0, Z_CLASS_INFO(*cep).line_start);
 #ifdef IS_UNICODE
 		zend_error(E_ERROR, "Cannot redeclare class %R", type, cep->name);
Index: /branches/1.3/xcache.c
===================================================================
--- /branches/1.3/xcache.c	(revision 725)
+++ /branches/1.3/xcache.c	(revision 726)
@@ -931,6 +931,6 @@
 	xc_entry_data_php_t *php = (xc_entry_data_php_t *) data;
 
-	class_name = opline->op1.u.constant.value.str.val;
-	class_len  = opline->op1.u.constant.value.str.len;
+	class_name = Z_OP_CONSTANT(opline->op1).value.str.val;
+	class_len  = Z_OP_CONSTANT(opline->op1).value.str.len;
 	if (zend_hash_find(CG(class_table), class_name, class_len, (void **) &cest) == FAILURE) {
 		assert(0);
@@ -2437,19 +2437,20 @@
 	}
 
-	if (value->type == IS_CONSTANT) {
+	switch ((Z_TYPE_P(value) & IS_CONSTANT_TYPE_MASK)) {
+	case IS_CONSTANT:
 		*return_value = *value;
 		zval_copy_ctor(return_value);
 		return_value->type = UNISW(IS_STRING, UG(unicode) ? IS_UNICODE : IS_STRING);
-		return;
-	}
-
-	if (value->type == IS_CONSTANT_ARRAY) {
+		break;
+
+	case IS_CONSTANT_ARRAY:
 		*return_value = *value;
 		zval_copy_ctor(return_value);
 		return_value->type = IS_ARRAY;
-		return;
-	}
-
-	RETURN_NULL();
+		break;
+
+	default:
+		RETURN_NULL();
+	}
 }
 /* }}} */
@@ -2478,5 +2479,5 @@
 }
 /* }}} */
-static function_entry xcache_functions[] = /* {{{ */
+static zend_function_entry xcache_functions[] = /* {{{ */
 {
 	PHP_FE(xcache_count,             NULL)
Index: /branches/1.3/xcache.h
===================================================================
--- /branches/1.3/xcache.h	(revision 725)
+++ /branches/1.3/xcache.h	(revision 726)
@@ -22,12 +22,15 @@
 
 #define HAVE_INODE
-#if !defined(ZEND_ENGINE_2_1) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1 || PHP_MAJOR_VERSION > 5)
+#if !defined(ZEND_ENGINE_2_4) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 99 || PHP_MAJOR_VERSION > 5)
+#	define ZEND_ENGINE_2_4
+#endif
+#if !defined(ZEND_ENGINE_2_3) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 || defined(ZEND_ENGINE_2_4))
+#	define ZEND_ENGINE_2_3
+#endif
+#if !defined(ZEND_ENGINE_2_2) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 2 || defined(ZEND_ENGINE_2_3))
+#	define ZEND_ENGINE_2_2
+#endif
+#if !defined(ZEND_ENGINE_2_1) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 || defined(ZEND_ENGINE_2_2))
 #	define ZEND_ENGINE_2_1
-#endif
-#if !defined(ZEND_ENGINE_2_2) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2 || PHP_MAJOR_VERSION > 5)
-#	define ZEND_ENGINE_2_2
-#endif
-#if !defined(ZEND_ENGINE_2_3) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3 || PHP_MAJOR_VERSION > 5)
-#	define ZEND_ENGINE_2_3
 #endif
 
@@ -89,4 +92,20 @@
 #	define add_assoc_null_ex my_add_assoc_null_ex
 #endif
+
+#ifdef ZEND_ENGINE_2_4
+#	define Z_OP(op) (op)
+#	define Z_OP_CONSTANT(op) (op).literal->constant
+#	define Z_OP_TYPE(op) op##_##type
+
+#	define Z_CLASS_INFO(className) (className).info.user
+#else
+#	define Z_OP(op) (op).u
+#	define Z_OP_CONSTANT(op) (op).u.constant
+#	define Z_OP_TYPE(op) (op).op_type
+typedef znode znode_op;
+
+#	define Z_CLASS_INFO(className) (className)
+#endif
+
 /* }}} */
 
