Index: /tags/1.3.0-rc1/xcache_globals.h
===================================================================
--- /tags/1.3.0-rc1/xcache_globals.h	(revision 627)
+++ /tags/1.3.0-rc1/xcache_globals.h	(revision 627)
@@ -0,0 +1,38 @@
+
+ZEND_BEGIN_MODULE_GLOBALS(xcache)
+	zend_bool initial_compile_file_called; /* true is origin_compile_file is called */
+	zend_bool cacher;      /* true if enabled */
+	zend_bool stat;
+#ifdef HAVE_XCACHE_OPTIMIZER
+	zend_bool optimizer;   /* true if enabled */
+#endif
+#ifdef HAVE_XCACHE_COVERAGER
+	zend_bool coverager;
+	zend_bool coverage_enabled;
+	HashTable *coverages;  /* coverages[file][line] = times */
+#endif
+	xc_stack_t *php_holds;
+	xc_stack_t *var_holds;
+	time_t request_time;
+	long   var_ttl;
+	zend_bool auth_enabled;
+
+#ifdef ZEND_ENGINE_2
+	HashTable gc_op_arrays;
+#endif
+
+#ifdef HAVE_XCACHE_CONSTANT
+	HashTable internal_constant_table;
+#endif
+	HashTable internal_function_table;
+	HashTable internal_class_table;
+	zend_bool internal_table_copied;
+ZEND_END_MODULE_GLOBALS(xcache)
+
+ZEND_EXTERN_MODULE_GLOBALS(xcache)
+
+#ifdef ZTS
+# define XG(v) TSRMG(xcache_globals_id, zend_xcache_globals *, v)
+#else
+# define XG(v) (xcache_globals.v)
+#endif
Index: /tags/1.3.0-rc1/xcache-test.ini
===================================================================
--- /tags/1.3.0-rc1/xcache-test.ini	(revision 627)
+++ /tags/1.3.0-rc1/xcache-test.ini	(revision 627)
@@ -0,0 +1,24 @@
+memory_limit = 256M
+
+[xcache]
+zend_extension_debug_ts=./modules/xcache.so
+zend_extension_debug=./modules/xcache.so
+zend_extension_ts=./modules/xcache.so
+zend_extension=./modules/xcache.so
+xcache.cacher = On
+xcache.test=1
+xcache.size = 16M
+xcache.count = 1
+xcache.var_size = 1M
+xcache.var_count = 1
+xcache.var_slots = 1000
+; xcache.mmap_path = "/dev/zero"
+xcache.mmap_path = "/tmp/xcache"
+xcache.readonly_protection = Off
+xcache.optimizer = Off
+xcache.coredump_directory = "/tmp/"
+;xcache.coveragedump_directory = "/tmp/pcov/"
+xcache.coverager = On
+
+xcache.admin.user = "test"
+xcache.admin.pass = "098f6bcd4621d373cade4e832627b4f6"
Index: /tags/1.3.0-rc1/disassembler.c
===================================================================
--- /tags/1.3.0-rc1/disassembler.c	(revision 622)
+++ /tags/1.3.0-rc1/disassembler.c	(revision 622)
@@ -0,0 +1,165 @@
+#include "disassembler.h"
+#include "xcache.h"
+#include "utils.h"
+#include "processor.h"
+
+#define return_value dst
+
+#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) /* {{{ */
+{
+	Bucket *b;
+	zval *zv, *list;
+	xc_compile_result_t cr;
+	int bufsize = 2;
+	char *buf;
+	int keysize;
+
+	xc_compile_result_init_cur(&cr, op_array TSRMLS_CC);
+
+	xc_apply_op_array(&cr, (apply_func_t) xc_undo_pass_two TSRMLS_CC);
+	xc_apply_op_array(&cr, (apply_func_t) xc_fix_opcode TSRMLS_CC);
+
+	/* go */
+	array_init(dst);
+
+	ALLOC_INIT_ZVAL(zv);
+	array_init(zv);
+	xc_dasm_zend_op_array(zv, op_array TSRMLS_CC);
+	add_assoc_zval_ex(dst, ZEND_STRS("op_array"), zv);
+
+	ALLOC_INIT_ZVAL(list);
+	array_init(list);
+	xc_dasm_HashTable_zend_function(list, CG(function_table) TSRMLS_CC);
+	add_assoc_zval_ex(dst, ZEND_STRS("function_table"), list);
+	
+	buf = emalloc(bufsize);
+	ALLOC_INIT_ZVAL(list);
+	array_init(list);
+	for (b = CG(class_table)->pListHead; b; b = b->pListNext) {
+		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];
+		keysize = b->nKeyLength;
+#ifdef IS_UNICODE
+		if (BUCKET_KEY_TYPE(b) == IS_UNICODE) {
+			if (buf[0] == ""[0] && buf[1] == ""[0]) {
+				keysize ++;
+			}
+		} else
+#endif
+		{
+			if (buf[0] == ""[0]) {
+				keysize ++;
+			}
+		}
+		add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), b->nKeyLength, zv);
+	}
+	efree(buf);
+	add_assoc_zval_ex(dst, ZEND_STRS("class_table"), list);
+
+	/*xc_apply_op_array(&cr, (apply_func_t) xc_redo_pass_two TSRMLS_CC);*/
+	xc_compile_result_free(&cr);
+
+	return;
+}
+/* }}} */
+void xc_dasm_string(zval *dst, zval *source TSRMLS_DC) /* {{{ */
+{
+	int catched;
+	zend_op_array *op_array = NULL;
+	xc_sandbox_t sandbox;
+	char *eval_name = zend_make_compiled_string_description("runtime-created function" TSRMLS_CC);
+
+	xc_sandbox_init(&sandbox, eval_name TSRMLS_CC);
+
+	catched = 0;
+	zend_try {
+		op_array = compile_string(source, eval_name TSRMLS_CC);
+	} zend_catch {
+		catched = 1;
+	} zend_end_try();
+
+	if (catched || !op_array) {
+		goto err_compile;
+	}
+
+	xc_dasm(dst, op_array TSRMLS_CC);
+
+	/* free */
+	efree(eval_name);
+#ifdef ZEND_ENGINE_2
+	destroy_op_array(op_array TSRMLS_CC);
+#else
+	destroy_op_array(op_array);
+#endif
+	efree(op_array);
+	xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
+	return;
+
+err_compile:
+	efree(eval_name);
+	xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
+
+	RETURN_FALSE;
+}
+/* }}} */
+void xc_dasm_file(zval *dst, const char *filename TSRMLS_DC) /* {{{ */
+{
+	int catched;
+	zend_op_array *op_array = NULL;
+	xc_sandbox_t sandbox;
+	zval *zfilename;
+
+	MAKE_STD_ZVAL(zfilename);
+	zfilename->value.str.val = estrdup(filename);
+	zfilename->value.str.len = strlen(filename);
+	zfilename->type = IS_STRING;
+
+	xc_sandbox_init(&sandbox, zfilename->value.str.val TSRMLS_CC);
+
+	catched = 0;
+	zend_try {
+		op_array = compile_filename(ZEND_REQUIRE, zfilename TSRMLS_CC);
+	} zend_catch {
+		catched = 1;
+	} zend_end_try();
+
+	if (catched || !op_array) {
+		goto err_compile;
+	}
+
+	xc_dasm(dst, op_array TSRMLS_CC);
+
+	/* free */
+#ifdef ZEND_ENGINE_2
+	destroy_op_array(op_array TSRMLS_CC);
+#else
+	destroy_op_array(op_array);
+#endif
+	efree(op_array);
+	xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
+	zval_dtor(zfilename);
+	FREE_ZVAL(zfilename);
+	return;
+
+err_compile:
+	xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
+
+	zval_dtor(zfilename);
+	FREE_ZVAL(zfilename);
+	RETURN_FALSE;
+}
+/* }}} */
Index: /tags/1.3.0-rc1/processor.c
===================================================================
--- /tags/1.3.0-rc1/processor.c	(revision 394)
+++ /tags/1.3.0-rc1/processor.c	(revision 394)
@@ -0,0 +1,1 @@
+#include "processor_real.c"
Index: /tags/1.3.0-rc1/disassembler.h
===================================================================
--- /tags/1.3.0-rc1/disassembler.h	(revision 394)
+++ /tags/1.3.0-rc1/disassembler.h	(revision 394)
@@ -0,0 +1,4 @@
+#include "php.h"
+
+void xc_dasm_string(zval *return_value, zval *code TSRMLS_DC);
+void xc_dasm_file(zval *return_value, const char *filename TSRMLS_DC);
Index: /tags/1.3.0-rc1/phpdc.phpr
===================================================================
--- /tags/1.3.0-rc1/phpdc.phpr	(revision 623)
+++ /tags/1.3.0-rc1/phpdc.phpr	(revision 623)
@@ -0,0 +1,30 @@
+#! /usr/bin/php -dopen_basedir=
+<?php
+
+$srcdir = dirname(__FILE__);
+require_once("$srcdir/Decompiler.class.php");
+if (file_exists("$srcdir/phpdc.debug.php")) {
+	include("$srcdir/phpdc.debug.php");
+}
+
+if (!isset($argv)) {
+	$argv = $_SERVER['argv'];
+	$argc = $_SERVER['argc'];
+}
+
+$dc = new Decompiler();
+if (isset($argv[1])) {
+	$dc->decompileFile($argv[1]);
+}
+else {
+	$phpcode = '';
+	if (!defined('stdin')) {
+		define('stdin', fopen('php://stdin', 'rb'));
+	}
+	while (!feof(stdin)) {
+		$phpcode .= fgets(stdin);
+	}
+	$dc->decompileFile($phpcode);
+}
+$dc->output();
+
Index: /tags/1.3.0-rc1/INSTALL
===================================================================
--- /tags/1.3.0-rc1/INSTALL	(revision 604)
+++ /tags/1.3.0-rc1/INSTALL	(revision 604)
@@ -0,0 +1,26 @@
+# vim:ts=4:sw=4
+Installtion:
+
+    $ phpize --clean && phpize
+    $ ./configure --help
+    $ CFLAGS='your cflags' ./configure --enable-xcache --enable...
+    $ make
+    $ su
+    # make install
+	(update php.ini, restart php)
+
+Reinstall:
+
+	$ mv config.nice conf
+	$ make distclean && phpize --clean && phpize
+	$ mv conf config.nice
+	$ ./config.nice
+	$ make
+	$ su
+	# make install
+	(update php.ini, restart php)
+
+Update php.ini:
+	$ su
+	# cat xcache.ini >> /etc/php.ini
+	# $EDITOR /etc/php.ini
Index: /tags/1.3.0-rc1/lock.c
===================================================================
--- /tags/1.3.0-rc1/lock.c	(revision 394)
+++ /tags/1.3.0-rc1/lock.c	(revision 394)
@@ -0,0 +1,157 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <php.h>
+#ifndef ZEND_WIN32
+typedef int HANDLE;
+#	ifndef INVALID_HANDLE_VALUE
+#		define INVALID_HANDLE_VALUE -1
+#	endif
+#	define CloseHandle(h) close(h)
+#endif
+#include "lock.h"
+
+struct _xc_lock_t {
+	HANDLE fd;
+	char *pathname;
+};
+
+#ifndef ZEND_WIN32
+#	include <unistd.h>
+#	include <fcntl.h>
+#	include <errno.h>
+#	define LCK_WR F_WRLCK
+#	define LCK_RD F_RDLCK
+#	define LCK_UN F_UNLCK
+#	define LCK_NB 0
+static inline int dolock(xc_lock_t *lck, int type) /* {{{ */
+{ 
+	int ret;
+	struct flock lock;
+
+	lock.l_type = type;
+	lock.l_start = 0;
+	lock.l_whence = SEEK_SET;
+	lock.l_len = 1;
+	lock.l_pid = 0;
+
+	do {
+		ret = fcntl(lck->fd, F_SETLKW, &lock);
+	} while (ret < 0 && errno == EINTR);
+	return ret;
+}
+/* }}} */
+#else
+
+#	include <win32/flock.h>
+#	include <io.h>
+#	include <fcntl.h>
+#	include <sys/types.h>
+#	include <sys/stat.h>
+#	ifndef errno
+#		define errno GetLastError()
+#	endif
+#	define getuid() 0
+#	define LCK_WR LOCKFILE_EXCLUSIVE_LOCK
+#	define LCK_RD 0
+#	define LCK_UN 0
+#	define LCK_NB LOCKFILE_FAIL_IMMEDIATELY
+static inline int dolock(xc_lock_t *lck, int type) /* {{{ */
+{ 
+	static OVERLAPPED offset = {0, 0, 0, 0, NULL};
+
+	if (type == LCK_UN) {
+		return UnlockFileEx((HANDLE)lck->fd, 0, 1, 0, &offset);
+	}
+	else {
+		return LockFileEx((HANDLE)lck->fd, type, 0, 1, 0, &offset);
+	}
+}
+/* }}} */
+#endif
+
+xc_lock_t *xc_fcntl_init(const char *pathname) /* {{{ */
+{
+	HANDLE fd;
+	xc_lock_t *lck;
+	int size;
+	char *myname;
+
+	if (pathname == NULL) {
+		static int i = 0;
+		const char default_tmpdir[] = { DEFAULT_SLASH, 't', 'm', 'p', '\0' };
+		const char *tmpdir;
+
+		tmpdir = getenv("TEMP");
+		if (!tmpdir) {
+			tmpdir = getenv("TMP");
+			if (!tmpdir) {
+				tmpdir = default_tmpdir;
+			}
+		}
+		size = strlen(tmpdir) + sizeof("/.xcache.lock") - 1 + 3 * 10 + 100;
+		myname = malloc(size);
+		snprintf(myname, size - 1, "%s%c.xcache.%d.%d.%d.lock", tmpdir, DEFAULT_SLASH, (int) getuid(), i ++, rand());
+		pathname = myname;
+	}
+	else {
+		myname = NULL;
+	}
+
+	fd = (HANDLE) open(pathname, O_RDWR|O_CREAT, 0666);
+
+	if (fd != INVALID_HANDLE_VALUE) {
+		lck = malloc(sizeof(lck[0]));
+
+#ifndef __CYGWIN__
+		unlink(pathname);
+#endif
+		lck->fd = fd;
+		size = strlen(pathname) + 1;
+		lck->pathname = malloc(size);
+		memcpy(lck->pathname, pathname, size);
+	}
+	else {
+		fprintf(stderr, "xc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
+		lck = NULL;
+	}
+
+	if (myname) {
+		free(myname);
+	}
+
+	return lck;
+}
+/* }}} */
+void xc_fcntl_destroy(xc_lock_t *lck) /* {{{ */
+{   
+	CloseHandle(lck->fd);
+#ifdef __CYGWIN__
+	unlink(lck->pathname);
+#endif
+	free(lck->pathname);
+	free(lck);
+}
+/* }}} */
+void xc_fcntl_lock(xc_lock_t *lck) /* {{{ */
+{   
+	if (dolock(lck, LCK_WR) < 0) {
+		fprintf(stderr, "xc_fcntl_lock failed errno:%d", errno);
+	}
+}
+/* }}} */
+void xc_fcntl_rdlock(xc_lock_t *lck) /* {{{ */
+{   
+	if (dolock(lck, LCK_RD) < 0) {
+		fprintf(stderr, "xc_fcntl_lock failed errno:%d", errno);
+	}
+}
+/* }}} */
+void xc_fcntl_unlock(xc_lock_t *lck) /* {{{ */
+{   
+	if (dolock(lck, LCK_UN) < 0) {
+		fprintf(stderr, "xc_fcntl_unlock failed errno:%d", errno);
+	}
+}
+/* }}} */
Index: /tags/1.3.0-rc1/foreachcoresig.h
===================================================================
--- /tags/1.3.0-rc1/foreachcoresig.h	(revision 394)
+++ /tags/1.3.0-rc1/foreachcoresig.h	(revision 394)
@@ -0,0 +1,50 @@
+/* all signals generate coredump by default is list here */
+
+#ifdef SIGABRT
+FOREACH_SIG(SIGABRT);
+#endif
+
+#ifdef SIGBUS
+FOREACH_SIG(SIGBUS);
+#endif
+
+#ifdef SIGEMT
+FOREACH_SIG(SIGEMT);
+#endif
+
+#ifdef SIGFPE
+FOREACH_SIG(SIGFPE);
+#endif
+
+#ifdef SIGILL
+FOREACH_SIG(SIGILL);
+#endif
+
+#ifdef SIGIOT
+FOREACH_SIG(SIGIOT);
+#endif
+
+#ifdef SIGQUIT
+FOREACH_SIG(SIGQUIT);
+#endif
+
+#ifdef SIGSEGV
+FOREACH_SIG(SIGSEGV);
+#endif
+
+#ifdef SIGSYS
+FOREACH_SIG(SIGSYS);
+#endif
+
+#ifdef SIGTRAP
+FOREACH_SIG(SIGTRAP);
+#endif
+
+#ifdef SIGXCPU
+FOREACH_SIG(SIGXCPU);
+#endif
+
+#ifdef SIGXFSZ
+FOREACH_SIG(SIGXFSZ);
+#endif
+
Index: /tags/1.3.0-rc1/xcache.c
===================================================================
--- /tags/1.3.0-rc1/xcache.c	(revision 641)
+++ /tags/1.3.0-rc1/xcache.c	(revision 641)
@@ -0,0 +1,3091 @@
+
+#if 0
+#define XCACHE_DEBUG
+#endif
+
+#if 0
+#define SHOW_DPRINT
+#endif
+
+/* {{{ macros */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <signal.h>
+
+#include "php.h"
+#include "ext/standard/info.h"
+#include "ext/standard/md5.h"
+#include "ext/standard/php_math.h"
+#include "zend_extensions.h"
+#include "SAPI.h"
+
+#include "xcache.h"
+#ifdef ZEND_ENGINE_2_1
+#include "ext/date/php_date.h"
+#endif
+#include "optimizer.h"
+#include "coverager.h"
+#include "disassembler.h"
+#include "align.h"
+#include "stack.h"
+#include "xcache_globals.h"
+#include "processor.h"
+#include "const_string.h"
+#include "opcode_spec.h"
+#include "utils.h"
+
+#define VAR_ENTRY_EXPIRED(pentry) ((pentry)->ttl && XG(request_time) > pentry->ctime + (pentry)->ttl)
+#define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0)
+#define LOCK(x) xc_lock(x->lck)
+#define UNLOCK(x) xc_unlock(x->lck)
+
+#define ENTER_LOCK_EX(x) \
+	xc_lock(x->lck); \
+	zend_try { \
+		do
+#define LEAVE_LOCK_EX(x) \
+		while (0); \
+	} zend_catch { \
+		catched = 1; \
+	} zend_end_try(); \
+	xc_unlock(x->lck)
+
+#define ENTER_LOCK(x) do { \
+	int catched = 0; \
+	ENTER_LOCK_EX(x)
+#define LEAVE_LOCK(x) \
+	LEAVE_LOCK_EX(x); \
+	if (catched) { \
+		zend_bailout(); \
+	} \
+} while(0)
+
+/* }}} */
+
+/* {{{ globals */
+static char *xc_shm_scheme = NULL;
+static char *xc_mmap_path = NULL;
+static char *xc_coredump_dir = NULL;
+
+static xc_hash_t xc_php_hcache = {0};
+static xc_hash_t xc_php_hentry = {0};
+static xc_hash_t xc_var_hcache = {0};
+static xc_hash_t xc_var_hentry = {0};
+
+static zend_ulong xc_php_ttl    = 0;
+static zend_ulong xc_var_maxttl = 0;
+
+enum { xc_deletes_gc_interval = 120 };
+static zend_ulong xc_php_gc_interval = 0;
+static zend_ulong xc_var_gc_interval = 0;
+
+/* total size */
+static zend_ulong xc_php_size  = 0;
+static zend_ulong xc_var_size  = 0;
+
+static xc_cache_t **xc_php_caches = NULL;
+static xc_cache_t **xc_var_caches = NULL;
+
+static zend_bool xc_initized = 0;
+static time_t xc_init_time = 0;
+static long unsigned xc_init_instance_id = 0;
+#ifdef ZTS
+static long unsigned xc_init_instance_subid = 0;
+#endif
+static zend_compile_file_t *origin_compile_file = NULL;
+static zend_compile_file_t *old_compile_file = NULL;
+static zend_llist_element  *xc_llist_zend_extension = NULL;
+
+static zend_bool xc_test = 0;
+static zend_bool xc_readonly_protection = 0;
+
+zend_bool xc_have_op_array_ctor = 0;
+
+static zend_bool xc_module_gotup = 0;
+static zend_bool xc_zend_extension_gotup = 0;
+static zend_bool xc_zend_extension_faked = 0;
+#if !COMPILE_DL_XCACHE
+#	define zend_extension_entry xcache_zend_extension_entry
+#endif
+ZEND_DLEXPORT zend_extension zend_extension_entry;
+ZEND_DECLARE_MODULE_GLOBALS(xcache);
+/* }}} */
+
+/* any function in *_dmz is only safe be called within locked(single thread) area */
+
+static inline int xc_entry_equal_dmz(xc_entry_t *a, xc_entry_t *b) /* {{{ */
+{
+	/* this function isn't required but can be in dmz */
+
+	if (a->type != b->type) {
+		return 0;
+	}
+	switch (a->type) {
+		case XC_TYPE_PHP:
+#ifdef HAVE_INODE
+			do {
+				xc_entry_data_php_t *ap = a->data.php;
+				xc_entry_data_php_t *bp = b->data.php;
+				if (ap->inode) {
+					return ap->inode == bp->inode
+						&& ap->device == bp->device;
+				}
+			} while(0);
+#endif
+			/* fall */
+
+		case XC_TYPE_VAR:
+			do {
+#ifdef IS_UNICODE
+				if (a->name_type == IS_UNICODE) {
+					if (a->name.ustr.len != b->name.ustr.len) {
+						return 0;
+					}
+					return memcmp(a->name.ustr.val, b->name.ustr.val, (a->name.ustr.len + 1) * sizeof(UChar)) == 0;
+				}
+				else {
+					return memcmp(a->name.str.val, b->name.str.val, a->name.str.len + 1) == 0;
+				}
+#else
+				return memcmp(a->name.str.val, b->name.str.val, a->name.str.len + 1) == 0;
+#endif
+
+			} while(0);
+		default:
+			assert(0);
+	}
+	return 0;
+}
+/* }}} */
+static void xc_entry_free_real_dmz(volatile xc_entry_t *xce) /* {{{ */
+{
+	xce->cache->mem->handlers->free(xce->cache->mem, (xc_entry_t *)xce);
+}
+/* }}} */
+static void xc_entry_add_dmz(xc_entry_t *xce) /* {{{ */
+{
+	xc_entry_t **head = &(xce->cache->entries[xce->hvalue]);
+	xce->next = *head;
+	*head = xce;
+	xce->cache->entries_count ++;
+}
+/* }}} */
+static xc_entry_t *xc_entry_store_dmz(xc_entry_t *xce TSRMLS_DC) /* {{{ */
+{
+	xc_entry_t *stored_xce;
+
+	xce->hits  = 0;
+	xce->ctime = XG(request_time);
+	xce->atime = XG(request_time);
+	stored_xce = xc_processor_store_xc_entry_t(xce TSRMLS_CC);
+	if (stored_xce) {
+		xc_entry_add_dmz(stored_xce);
+		return stored_xce;
+	}
+	else {
+		xce->cache->ooms ++;
+		return NULL;
+	}
+}
+/* }}} */
+static void xc_entry_free_dmz(xc_entry_t *xce TSRMLS_DC) /* {{{ */
+{
+	xce->cache->entries_count --;
+	if (xce->refcount == 0) {
+		xc_entry_free_real_dmz(xce);
+	}
+	else {
+		xce->next = xce->cache->deletes;
+		xce->cache->deletes = xce;
+		xce->dtime = XG(request_time);
+		xce->cache->deletes_count ++;
+	}
+	return;
+}
+/* }}} */
+static void xc_entry_remove_dmz(xc_entry_t *xce TSRMLS_DC) /* {{{ */
+{
+	xc_entry_t **pp = &(xce->cache->entries[xce->hvalue]);
+	xc_entry_t *p;
+	for (p = *pp; p; pp = &(p->next), p = p->next) {
+		if (xc_entry_equal_dmz(xce, p)) {
+			/* unlink */
+			*pp = p->next;
+			xc_entry_free_dmz(xce TSRMLS_CC);
+			return;
+		}
+	}
+	assert(0);
+}
+/* }}} */
+static xc_entry_t *xc_entry_find_dmz(xc_entry_t *xce TSRMLS_DC) /* {{{ */
+{
+	xc_entry_t *p;
+	for (p = xce->cache->entries[xce->hvalue]; p; p = p->next) {
+		if (xc_entry_equal_dmz(xce, p)) {
+			if (p->type == XC_TYPE_VAR || /* PHP */ (p->data.php->mtime == xce->data.php->mtime && p->data.php->sourcesize == xce->data.php->sourcesize)) {
+				p->hits ++;
+				p->atime = XG(request_time);
+				return p;
+			}
+			else {
+				xc_entry_remove_dmz(p TSRMLS_CC);
+				return NULL;
+			}
+		}
+	}
+	return NULL;
+}
+/* }}} */
+static void xc_entry_hold_php_dmz(xc_entry_t *xce TSRMLS_DC) /* {{{ */
+{
+	TRACE("hold %s", xce->name.str.val);
+	xce->refcount ++;
+	xc_stack_push(&XG(php_holds)[xce->cache->cacheid], (void *)xce);
+}
+/* }}} */
+#if 0
+static void xc_entry_hold_var_dmz(xc_entry_t *xce TSRMLS_DC) /* {{{ */
+{
+	xce->refcount ++;
+	xc_stack_push(&XG(var_holds)[xce->cache->cacheid], (void *)xce);
+}
+/* }}} */
+#endif
+static inline zend_uint advance_wrapped(zend_uint val, zend_uint count) /* {{{ */
+{
+	if (val + 1 >= count) {
+		return 0;
+	}
+	return val + 1;
+}
+/* }}} */
+static void xc_counters_inc(time_t *curtime, zend_uint *curslot, time_t period, zend_ulong *counters, zend_uint count TSRMLS_DC) /* {{{ */
+{
+	time_t n = XG(request_time) / period;
+	if (*curtime != n) {
+		zend_uint target_slot = n % count;
+		if (n - *curtime > period) {
+			memset(counters, 0, sizeof(counters[0]) * count);
+		}
+		else {
+			zend_uint slot;
+			for (slot = advance_wrapped(*curslot, count);
+					slot != target_slot;
+					slot = advance_wrapped(slot, count)) {
+				counters[slot] = 0;
+			}
+			counters[target_slot] = 0;
+		}
+		*curtime = n;
+		*curslot = target_slot;
+	}
+	counters[*curslot] ++;
+}
+/* }}} */
+static void xc_cache_hit_dmz(xc_cache_t *cache TSRMLS_DC) /* {{{ */
+{
+	cache->hits ++;
+
+	xc_counters_inc(&cache->hits_by_hour_cur_time
+			, &cache->hits_by_hour_cur_slot, 60 * 60
+			, cache->hits_by_hour
+			, sizeof(cache->hits_by_hour) / sizeof(cache->hits_by_hour[0])
+			TSRMLS_CC);
+
+	xc_counters_inc(&cache->hits_by_second_cur_time
+			, &cache->hits_by_second_cur_slot
+			, 1
+			, cache->hits_by_second
+			, sizeof(cache->hits_by_second) / sizeof(cache->hits_by_second[0])
+			TSRMLS_CC);
+}
+/* }}} */
+
+/* helper function that loop through each entry */
+#define XC_ENTRY_APPLY_FUNC(name) int name(xc_entry_t *entry TSRMLS_DC)
+typedef XC_ENTRY_APPLY_FUNC((*cache_apply_dmz_func_t));
+static void xc_entry_apply_dmz(xc_cache_t *cache, cache_apply_dmz_func_t apply_func TSRMLS_DC) /* {{{ */
+{
+	xc_entry_t *p, **pp;
+	int i, c;
+
+	for (i = 0, c = cache->hentry->size; i < c; i ++) {
+		pp = &(cache->entries[i]);
+		for (p = *pp; p; p = *pp) {
+			if (apply_func(p TSRMLS_CC)) {
+				/* unlink */
+				*pp = p->next;
+				xc_entry_free_dmz(p TSRMLS_CC);
+			}
+			else {
+				pp = &(p->next);
+			}
+		}
+	}
+}
+/* }}} */
+
+#define XC_CACHE_APPLY_FUNC(name) void name(xc_cache_t *cache TSRMLS_DC)
+/* call graph:
+ * xc_gc_expires_php -> xc_gc_expires_one -> xc_entry_apply_dmz -> xc_gc_expires_php_entry_dmz
+ * xc_gc_expires_var -> xc_gc_expires_one -> xc_entry_apply_dmz -> xc_gc_expires_var_entry_dmz
+ */
+static XC_ENTRY_APPLY_FUNC(xc_gc_expires_php_entry_dmz) /* {{{ */
+{
+	TRACE("ttl %lu, %lu %lu", (zend_ulong) XG(request_time), (zend_ulong) entry->atime, xc_php_ttl);
+	if (XG(request_time) > entry->atime + xc_php_ttl) {
+		return 1;
+	}
+	return 0;
+}
+/* }}} */
+static XC_ENTRY_APPLY_FUNC(xc_gc_expires_var_entry_dmz) /* {{{ */
+{
+	if (VAR_ENTRY_EXPIRED(entry)) {
+		return 1;
+	}
+	return 0;
+}
+/* }}} */
+static void xc_gc_expires_one(xc_cache_t *cache, zend_ulong gc_interval, cache_apply_dmz_func_t apply_func TSRMLS_DC) /* {{{ */
+{
+	TRACE("interval %lu, %lu %lu", (zend_ulong) XG(request_time), (zend_ulong) cache->last_gc_expires, gc_interval);
+	if (XG(request_time) - cache->last_gc_expires >= gc_interval) {
+		ENTER_LOCK(cache) {
+			if (XG(request_time) - cache->last_gc_expires >= gc_interval) {
+				cache->last_gc_expires = XG(request_time);
+				xc_entry_apply_dmz(cache, apply_func TSRMLS_CC);
+			}
+		} LEAVE_LOCK(cache);
+	}
+}
+/* }}} */
+static void xc_gc_expires_php(TSRMLS_D) /* {{{ */
+{
+	int i, c;
+
+	if (!xc_php_ttl || !xc_php_gc_interval || !xc_php_caches) {
+		return;
+	}
+
+	for (i = 0, c = xc_php_hcache.size; i < c; i ++) {
+		xc_gc_expires_one(xc_php_caches[i], xc_php_gc_interval, xc_gc_expires_php_entry_dmz TSRMLS_CC);
+	}
+}
+/* }}} */
+static void xc_gc_expires_var(TSRMLS_D) /* {{{ */
+{
+	int i, c;
+
+	if (!xc_var_gc_interval || !xc_var_caches) {
+		return;
+	}
+
+	for (i = 0, c = xc_var_hcache.size; i < c; i ++) {
+		xc_gc_expires_one(xc_var_caches[i], xc_var_gc_interval, xc_gc_expires_var_entry_dmz TSRMLS_CC);
+	}
+}
+/* }}} */
+
+static XC_CACHE_APPLY_FUNC(xc_gc_delete_dmz) /* {{{ */
+{
+	xc_entry_t *p, **pp;
+
+	pp = &cache->deletes;
+	for (p = *pp; p; p = *pp) {
+		if (XG(request_time) - p->dtime > 3600) {
+			p->refcount = 0;
+			/* issue warning here */
+		}
+		if (p->refcount == 0) {
+			/* unlink */
+			*pp = p->next;
+			cache->deletes_count --;
+			xc_entry_free_real_dmz(p);
+		}
+		else {
+			pp = &(p->next);
+		}
+	}
+}
+/* }}} */
+static XC_CACHE_APPLY_FUNC(xc_gc_deletes_one) /* {{{ */
+{
+	if (cache->deletes && XG(request_time) - cache->last_gc_deletes > xc_deletes_gc_interval) {
+		ENTER_LOCK(cache) {
+			if (cache->deletes && XG(request_time) - cache->last_gc_deletes > xc_deletes_gc_interval) {
+				cache->last_gc_deletes = XG(request_time);
+				xc_gc_delete_dmz(cache TSRMLS_CC);
+			}
+		} LEAVE_LOCK(cache);
+	}
+}
+/* }}} */
+static void xc_gc_deletes(TSRMLS_D) /* {{{ */
+{
+	int i, c;
+
+	if (xc_php_caches) {
+		for (i = 0, c = xc_php_hcache.size; i < c; i ++) {
+			xc_gc_deletes_one(xc_php_caches[i] TSRMLS_CC);
+		}
+	}
+
+	if (xc_var_caches) {
+		for (i = 0, c = xc_var_hcache.size; i < c; i ++) {
+			xc_gc_deletes_one(xc_var_caches[i] TSRMLS_CC);
+		}
+	}
+}
+/* }}} */
+
+/* helper functions for user functions */
+static void xc_fillinfo_dmz(int cachetype, xc_cache_t *cache, zval *return_value TSRMLS_DC) /* {{{ */
+{
+	zval *blocks, *hits;
+	int i;
+	const xc_block_t *b;
+#ifndef NDEBUG
+	xc_memsize_t avail = 0;
+#endif
+	xc_mem_t *mem = cache->mem;
+	const xc_mem_handlers_t *handlers = mem->handlers;
+	zend_ulong interval;
+	if (cachetype == XC_TYPE_PHP) {
+		interval = xc_php_ttl ? xc_php_gc_interval : 0;
+	}
+	else {
+		interval = xc_var_gc_interval;
+	}
+
+	add_assoc_long_ex(return_value, ZEND_STRS("slots"),     cache->hentry->size);
+	add_assoc_long_ex(return_value, ZEND_STRS("compiling"), cache->compiling);
+	add_assoc_long_ex(return_value, ZEND_STRS("misses"),    cache->misses);
+	add_assoc_long_ex(return_value, ZEND_STRS("hits"),      cache->hits);
+	add_assoc_long_ex(return_value, ZEND_STRS("clogs"),     cache->clogs);
+	add_assoc_long_ex(return_value, ZEND_STRS("ooms"),      cache->ooms);
+	add_assoc_long_ex(return_value, ZEND_STRS("errors"),    cache->errors);
+
+	add_assoc_long_ex(return_value, ZEND_STRS("cached"),    cache->entries_count);
+	add_assoc_long_ex(return_value, ZEND_STRS("deleted"),   cache->deletes_count);
+	if (interval) {
+		time_t gc = (cache->last_gc_expires + interval) - XG(request_time);
+		add_assoc_long_ex(return_value, ZEND_STRS("gc"),    gc > 0 ? gc : 0);
+	}
+	else {
+		add_assoc_null_ex(return_value, ZEND_STRS("gc"));
+	}
+	MAKE_STD_ZVAL(hits);
+	array_init(hits);
+	for (i = 0; i < sizeof(cache->hits_by_hour) / sizeof(cache->hits_by_hour[0]); i ++) {
+		add_next_index_long(hits, (long) cache->hits_by_hour[i]);
+	}
+	add_assoc_zval_ex(return_value, ZEND_STRS("hits_by_hour"), hits);
+
+	MAKE_STD_ZVAL(hits);
+	array_init(hits);
+	for (i = 0; i < sizeof(cache->hits_by_second) / sizeof(cache->hits_by_second[0]); i ++) {
+		add_next_index_long(hits, (long) cache->hits_by_second[i]);
+	}
+	add_assoc_zval_ex(return_value, ZEND_STRS("hits_by_second"), hits);
+
+	MAKE_STD_ZVAL(blocks);
+	array_init(blocks);
+
+	add_assoc_long_ex(return_value, ZEND_STRS("size"),  handlers->size(mem));
+	add_assoc_long_ex(return_value, ZEND_STRS("avail"), handlers->avail(mem));
+	add_assoc_bool_ex(return_value, ZEND_STRS("can_readonly"), xc_readonly_protection);
+
+	for (b = handlers->freeblock_first(mem); b; b = handlers->freeblock_next(b)) {
+		zval *bi;
+
+		MAKE_STD_ZVAL(bi);
+		array_init(bi);
+
+		add_assoc_long_ex(bi, ZEND_STRS("size"),   handlers->block_size(b));
+		add_assoc_long_ex(bi, ZEND_STRS("offset"), handlers->block_offset(mem, b));
+		add_next_index_zval(blocks, bi);
+#ifndef NDEBUG
+		avail += handlers->block_size(b);
+#endif
+	}
+	add_assoc_zval_ex(return_value, ZEND_STRS("free_blocks"), blocks);
+#ifndef NDEBUG
+	assert(avail == handlers->avail(mem));
+#endif
+}
+/* }}} */
+static void xc_fillentry_dmz(xc_entry_t *entry, int del, zval *list TSRMLS_DC) /* {{{ */
+{
+	zval* ei;
+	xc_entry_data_php_t *php;
+	xc_entry_data_var_t *var;
+
+	ALLOC_INIT_ZVAL(ei);
+	array_init(ei);
+
+	add_assoc_long_ex(ei, ZEND_STRS("size"),     entry->size);
+	add_assoc_long_ex(ei, ZEND_STRS("refcount"), entry->refcount);
+	add_assoc_long_ex(ei, ZEND_STRS("hits"),     entry->hits);
+	add_assoc_long_ex(ei, ZEND_STRS("ctime"),    entry->ctime);
+	add_assoc_long_ex(ei, ZEND_STRS("atime"),    entry->atime);
+	add_assoc_long_ex(ei, ZEND_STRS("hvalue"),   entry->hvalue);
+	if (del) {
+		add_assoc_long_ex(ei, ZEND_STRS("dtime"), entry->dtime);
+	}
+#ifdef IS_UNICODE
+	do {
+		zval *zv;
+		ALLOC_INIT_ZVAL(zv);
+		switch (entry->name_type) {
+			case IS_UNICODE:
+					ZVAL_UNICODEL(zv, entry->name.ustr.val, entry->name.ustr.len, 1);
+				break;
+			case IS_STRING:
+				ZVAL_STRINGL(zv, entry->name.str.val, entry->name.str.len, 1);
+				break;
+			default:
+				assert(0);
+		}
+		zv->type = entry->name_type;
+		add_assoc_zval_ex(ei, ZEND_STRS("name"), zv);
+	} while (0);
+#else
+	add_assoc_stringl_ex(ei, ZEND_STRS("name"), entry->name.str.val, entry->name.str.len, 1);
+#endif
+	switch (entry->type) {
+		case XC_TYPE_PHP:
+			php = entry->data.php;
+			add_assoc_long_ex(ei, ZEND_STRS("sourcesize"),    php->sourcesize);
+#ifdef HAVE_INODE
+			add_assoc_long_ex(ei, ZEND_STRS("device"),        php->device);
+			add_assoc_long_ex(ei, ZEND_STRS("inode"),         php->inode);
+#endif
+			add_assoc_long_ex(ei, ZEND_STRS("mtime"),         php->mtime);
+
+#ifdef HAVE_XCACHE_CONSTANT
+			add_assoc_long_ex(ei, ZEND_STRS("constinfo_cnt"), php->constinfo_cnt);
+#endif
+			add_assoc_long_ex(ei, ZEND_STRS("function_cnt"),  php->funcinfo_cnt);
+			add_assoc_long_ex(ei, ZEND_STRS("class_cnt"),     php->classinfo_cnt);
+#ifdef ZEND_ENGINE_2_1
+			add_assoc_long_ex(ei, ZEND_STRS("autoglobal_cnt"),php->autoglobal_cnt);
+#endif
+			break;
+		case XC_TYPE_VAR:
+			var = entry->data.var;
+			break;
+
+		default:
+			assert(0);
+	}
+
+	add_next_index_zval(list, ei);
+}
+/* }}} */
+static void xc_filllist_dmz(xc_cache_t *cache, zval *return_value TSRMLS_DC) /* {{{ */
+{
+	zval* list;
+	int i, c;
+	xc_entry_t *e;
+
+	ALLOC_INIT_ZVAL(list);
+	array_init(list);
+
+	for (i = 0, c = cache->hentry->size; i < c; i ++) {
+		for (e = cache->entries[i]; e; e = e->next) {
+			xc_fillentry_dmz(e, 0, list TSRMLS_CC);
+		}
+	}
+	add_assoc_zval(return_value, "cache_list", list);
+
+	ALLOC_INIT_ZVAL(list);
+	array_init(list);
+	for (e = cache->deletes; e; e = e->next) {
+		xc_fillentry_dmz(e, 1, list TSRMLS_CC);
+	}
+	add_assoc_zval(return_value, "deleted_list", list);
+}
+/* }}} */
+
+static zend_op_array *xc_entry_install(xc_entry_t *xce, zend_file_handle *h TSRMLS_DC) /* {{{ */
+{
+	zend_uint i;
+	xc_entry_data_php_t *p = xce->data.php;
+	zend_op_array *old_active_op_array = CG(active_op_array);
+#ifndef ZEND_ENGINE_2
+	ALLOCA_FLAG(use_heap)
+	/* new ptr which is stored inside CG(class_table) */
+	xc_cest_t **new_cest_ptrs = (xc_cest_t **)my_do_alloca(sizeof(xc_cest_t*) * p->classinfo_cnt, use_heap);
+#endif
+
+	CG(active_op_array) = p->op_array;
+
+#ifdef HAVE_XCACHE_CONSTANT
+	/* install constant */
+	for (i = 0; i < p->constinfo_cnt; i ++) {
+		xc_constinfo_t *ci = &p->constinfos[i];
+		xc_install_constant(xce->name.str.val, &ci->constant,
+				UNISW(0, ci->type), ci->key, ci->key_size, ci->h TSRMLS_CC);
+	}
+#endif
+
+	/* install function */
+	for (i = 0; i < p->funcinfo_cnt; i ++) {
+		xc_funcinfo_t  *fi = &p->funcinfos[i];
+		xc_install_function(xce->name.str.val, &fi->func,
+				UNISW(0, fi->type), fi->key, fi->key_size, fi->h TSRMLS_CC);
+	}
+
+	/* install class */
+	for (i = 0; i < p->classinfo_cnt; i ++) {
+		xc_classinfo_t *ci = &p->classinfos[i];
+#ifndef ZEND_ENGINE_2
+		zend_class_entry *ce = CestToCePtr(ci->cest);
+		/* fix pointer to the be which inside class_table */
+		if (ce->parent) {
+			zend_uint class_idx = (/* class_num */ (int) (long) ce->parent) - 1;
+			assert(class_idx < i);
+			ci->cest.parent = new_cest_ptrs[class_idx];
+		}
+		new_cest_ptrs[i] =
+#endif
+#ifdef ZEND_COMPILE_DELAYED_BINDING
+		xc_install_class(xce->name.str.val, &ci->cest, -1,
+				UNISW(0, ci->type), ci->key, ci->key_size, ci->h TSRMLS_CC);
+#else
+		xc_install_class(xce->name.str.val, &ci->cest, ci->oplineno,
+				UNISW(0, ci->type), ci->key, ci->key_size, ci->h TSRMLS_CC);
+#endif
+	}
+
+#ifdef ZEND_ENGINE_2_1
+	/* trigger auto_globals jit */
+	for (i = 0; i < p->autoglobal_cnt; i ++) {
+		xc_autoglobal_t *aginfo = &p->autoglobals[i];
+		/*
+		zend_auto_global *auto_global;
+		if (zend_u_hash_quick_find(CG(auto_globals), aginfo->type, aginfo->key, aginfo->key_len+1, aginfo->h, (void **) &auto_global)==SUCCESS) {
+			if (auto_global->armed) {
+				auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
+			}
+		}
+		*/
+		zend_u_is_auto_global(aginfo->type, aginfo->key, aginfo->key_len TSRMLS_CC);
+	}
+#endif
+
+	i = 1;
+	zend_hash_add(&EG(included_files), xce->name.str.val, xce->name.str.len+1, (void *)&i, sizeof(int), NULL);
+	if (h) {
+		zend_llist_add_element(&CG(open_files), h);
+	}
+
+#ifndef ZEND_ENGINE_2
+	my_free_alloca(new_cest_ptrs, use_heap);
+#endif
+	CG(active_op_array) = old_active_op_array;
+	return p->op_array;
+}
+/* }}} */
+
+static inline void xc_entry_unholds_real(xc_stack_t *holds, xc_cache_t **caches, int cachecount TSRMLS_DC) /* {{{ */
+{
+	int i;
+	xc_stack_t *s;
+	xc_cache_t *cache;
+	xc_entry_t *xce;
+
+	for (i = 0; i < cachecount; i ++) {
+		s = &holds[i];
+		TRACE("holded %d", xc_stack_count(s));
+		if (xc_stack_count(s)) {
+			cache = ((xc_entry_t *)xc_stack_top(s))->cache;
+			ENTER_LOCK(cache) {
+				while (xc_stack_count(s)) {
+					xce = (xc_entry_t*) xc_stack_pop(s);
+					TRACE("unhold %s", xce->name.str.val);
+					xce->refcount --;
+					assert(xce->refcount >= 0);
+				}
+			} LEAVE_LOCK(cache);
+		}
+	}
+}
+/* }}} */
+static void xc_entry_unholds(TSRMLS_D) /* {{{ */
+{
+	if (xc_php_caches) {
+		xc_entry_unholds_real(XG(php_holds), xc_php_caches, xc_php_hcache.size TSRMLS_CC);
+	}
+
+	if (xc_var_caches) {
+		xc_entry_unholds_real(XG(var_holds), xc_var_caches, xc_var_hcache.size TSRMLS_CC);
+	}
+}
+/* }}} */
+static int xc_stat(const char *filename, const char *include_path, struct stat *pbuf TSRMLS_DC) /* {{{ */
+{
+	char filepath[MAXPATHLEN];
+	char *paths, *path;
+	char *tokbuf;
+	int size = strlen(include_path) + 1;
+	char tokens[] = { DEFAULT_DIR_SEPARATOR, '\0' };
+	ALLOCA_FLAG(use_heap)
+
+	paths = (char *)my_do_alloca(size, use_heap);
+	memcpy(paths, include_path, size);
+
+	for (path = php_strtok_r(paths, tokens, &tokbuf); path; path = php_strtok_r(NULL, tokens, &tokbuf)) {
+		if (snprintf(filepath, sizeof(filepath), "%s/%s", path, filename) >= MAXPATHLEN - 1) {
+			continue;
+		}
+		if (VCWD_STAT(filepath, pbuf) == 0) {
+			my_free_alloca(paths, use_heap);
+			return SUCCESS;
+		}
+	}
+
+	my_free_alloca(paths, use_heap);
+
+	return FAILURE;
+}
+/* }}} */
+
+#define HASH(i) (i)
+#define HASH_ZSTR_L(t, s, l) HASH(zend_u_inline_hash_func(t, s, (l + 1) * sizeof(UChar)))
+#define HASH_STR_L(s, l) HASH(zend_inline_hash_func(s, l + 1))
+#define HASH_STR(s) HASH_STR_L(s, strlen(s) + 1)
+#define HASH_NUM(n) HASH(n)
+static inline xc_hash_value_t xc_hash_fold(xc_hash_value_t hvalue, const xc_hash_t *hasher) /* {{{ fold hash bits as needed */
+{
+	xc_hash_value_t folded = 0;
+	while (hvalue) {
+		folded ^= (hvalue & hasher->mask);
+		hvalue >>= hasher->bits;
+	}
+	return folded;
+}
+/* }}} */
+static inline xc_hash_value_t xc_entry_hash_name(xc_entry_t *xce TSRMLS_DC) /* {{{ */
+{
+	return UNISW(NOTHING, UG(unicode) ? HASH_ZSTR_L(xce->name_type, xce->name.uni.val, xce->name.uni.len) :)
+		HASH_STR_L(xce->name.str.val, xce->name.str.len);
+}
+/* }}} */
+#define xc_entry_hash_var xc_entry_hash_name
+static inline xc_hash_value_t xc_entry_hash_php(xc_entry_t *xce TSRMLS_DC) /* {{{ */
+{
+#ifdef HAVE_INODE
+	if (xce->data.php->inode) {
+		return HASH(xce->data.php->device + xce->data.php->inode);
+	}
+#endif
+	return xc_entry_hash_name(xce TSRMLS_CC);
+}
+/* }}} */
+static int xc_entry_init_key_php(xc_entry_t *xce, char *filename, char *opened_path_buffer TSRMLS_DC) /* {{{ */
+{
+	struct stat buf, *pbuf;
+	xc_hash_value_t hv;
+	int cacheid;
+	xc_entry_data_php_t *php;
+	char *ptr;
+	time_t delta;
+
+	if (!filename || !SG(request_info).path_translated) {
+		return FAILURE;
+	}
+
+	if (strstr(filename, "://") != NULL) {
+		return FAILURE;
+	}
+
+	php = xce->data.php;
+
+	if (XG(stat)) {
+		if (strcmp(SG(request_info).path_translated, filename) == 0) {
+			/* sapi has already done this stat() for us */
+			pbuf = sapi_get_stat(TSRMLS_C);
+			if (pbuf) {
+				goto stat_done;
+			}
+		}
+
+		/* absolute path */
+		pbuf = &buf;
+		if (IS_ABSOLUTE_PATH(filename, strlen(filename))) {
+			if (VCWD_STAT(filename, pbuf) != 0) {
+				return FAILURE;
+			}
+			goto stat_done;
+		}
+
+		/* relative path */
+		if (*filename == '.' && (IS_SLASH(filename[1]) || filename[1] == '.')) {
+			ptr = filename + 1;
+			if (*ptr == '.') {
+				while (*(++ptr) == '.');
+				if (!IS_SLASH(*ptr)) {
+					goto not_relative_path;
+				}   
+			}
+
+			if (VCWD_STAT(filename, pbuf) != 0) {
+				return FAILURE;
+			}
+			goto stat_done;
+		}
+not_relative_path:
+
+		/* use include_path */
+		if (xc_stat(filename, PG(include_path), pbuf TSRMLS_CC) != SUCCESS) {
+			return FAILURE;
+		}
+
+		/* fall */
+
+stat_done:
+		delta = XG(request_time) - pbuf->st_mtime;
+		if (abs(delta) < 2 && !xc_test) {
+			return FAILURE;
+		}
+
+		php->mtime        = pbuf->st_mtime;
+#ifdef HAVE_INODE
+		php->device       = pbuf->st_dev;
+		php->inode        = pbuf->st_ino;
+#endif
+		php->sourcesize   = pbuf->st_size;
+	}
+	else { /* XG(inode) */
+		php->mtime        = 0;
+#ifdef HAVE_INODE
+		php->device       = 0;
+		php->inode        = 0;
+#endif
+		php->sourcesize   = 0;
+	}
+
+#ifdef HAVE_INODE
+	if (!php->inode)
+#endif
+	{
+		/* hash on filename, let's expand it to real path */
+		filename = expand_filepath(filename, opened_path_buffer TSRMLS_CC);
+		if (filename == NULL) {
+			return FAILURE;
+		}
+	}
+
+	UNISW(NOTHING, xce->name_type = IS_STRING;)
+	xce->name.str.val = filename;
+	xce->name.str.len = strlen(filename);
+
+	hv = xc_entry_hash_php(xce TSRMLS_CC);
+	cacheid = xc_hash_fold(hv, &xc_php_hcache);
+	xce->cache = xc_php_caches[cacheid];
+	xce->hvalue = xc_hash_fold(hv, &xc_php_hentry);
+
+	xce->type = XC_TYPE_PHP;
+	return SUCCESS;
+}
+/* }}} */
+#ifndef ZEND_COMPILE_DELAYED_BINDING
+static void xc_cache_early_binding_class_cb(zend_op *opline, int oplineno, void *data TSRMLS_DC) /* {{{ */
+{
+	char *class_name;
+	int i, class_len;
+	xc_cest_t cest;
+	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;
+	if (zend_hash_find(CG(class_table), class_name, class_len, (void **) &cest) == FAILURE) {
+		assert(0);
+	}
+	TRACE("got ZEND_DECLARE_INHERITED_CLASS: %s", class_name + 1);
+	/* let's see which class */
+	for (i = 0; i < php->classinfo_cnt; i ++) {
+		if (memcmp(ZSTR_S(php->classinfos[i].key), class_name, class_len) == 0) {
+			php->classinfos[i].oplineno = oplineno;
+			php->have_early_binding = 1;
+			break;
+		}
+	}
+
+	if (i == php->classinfo_cnt) {
+		assert(0);
+	}
+}
+/* }}} */
+#endif
+static zend_op_array *xc_check_initial_compile_file(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */
+{
+	XG(initial_compile_file_called) = 1;
+	return origin_compile_file(h, type TSRMLS_CC);
+}
+/* }}} */
+static zend_op_array *xc_compile_file(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */
+{
+	xc_sandbox_t sandbox;
+	zend_op_array *op_array;
+	xc_entry_t xce, *stored_xce;
+	xc_entry_data_php_t php;
+	xc_cache_t *cache;
+	zend_bool clogged = 0;
+	zend_bool catched = 0;
+	char *filename;
+	char opened_path_buffer[MAXPATHLEN];
+	int old_constinfo_cnt, old_funcinfo_cnt, old_classinfo_cnt;
+
+	if (!xc_initized) {
+		assert(0);
+	}
+
+	if (!XG(cacher)) {
+		op_array = old_compile_file(h, type TSRMLS_CC);
+#ifdef HAVE_XCACHE_OPTIMIZER
+		if (XG(optimizer)) {
+			xc_optimize(op_array TSRMLS_CC);
+		}
+#endif
+		return op_array;
+	}
+
+	/* {{{ prepare key
+	 * include_once() and require_once() gives us opened_path
+	 * however, include() and require() non-absolute path which break
+	 * included_files, and may confuse with (include|require)_once
+	 * -- Xuefer
+	 */
+
+	filename = h->opened_path ? h->opened_path : h->filename;
+	xce.data.php = &php;
+	if (xc_entry_init_key_php(&xce, filename, opened_path_buffer TSRMLS_CC) != SUCCESS) {
+		return old_compile_file(h, type TSRMLS_CC);
+	}
+	cache = xce.cache;
+	/* }}} */
+	/* {{{ restore */
+	/* stale precheck */
+	if (cache->compiling) {
+		cache->clogs ++; /* is it safe here? */
+		return old_compile_file(h, type TSRMLS_CC);
+	}
+
+	stored_xce = NULL;
+	op_array = NULL;
+	ENTER_LOCK_EX(cache) {
+		/* clogged */
+		if (cache->compiling) {
+			cache->clogs ++;
+			op_array = NULL;
+			clogged = 1;
+			break;
+		}
+
+		stored_xce = xc_entry_find_dmz(&xce TSRMLS_CC);
+		/* found */
+		if (stored_xce) {
+			TRACE("found %s, catch it", stored_xce->name.str.val);
+			xc_entry_hold_php_dmz(stored_xce TSRMLS_CC);
+			xc_cache_hit_dmz(cache TSRMLS_CC);
+			break;
+		}
+
+		cache->compiling = XG(request_time);
+		cache->misses ++;
+	} LEAVE_LOCK_EX(cache);
+
+	if (catched) {
+		cache->compiling = 0;
+		zend_bailout();
+	}
+
+	/* found */
+	if (stored_xce) {
+		goto restore;
+	}
+
+	/* clogged */
+	if (clogged) {
+		return old_compile_file(h, type TSRMLS_CC);
+	}
+	/* }}} */
+
+	/* {{{ compile */
+	TRACE("compiling %s", filename);
+
+	/* make compile inside sandbox */
+	xc_sandbox_init(&sandbox, filename TSRMLS_CC);
+
+	old_classinfo_cnt = zend_hash_num_elements(CG(class_table));
+	old_funcinfo_cnt  = zend_hash_num_elements(CG(function_table));
+	old_constinfo_cnt  = zend_hash_num_elements(EG(zend_constants));
+
+	XG(initial_compile_file_called) = 0;
+	zend_try {
+		op_array = old_compile_file(h, type TSRMLS_CC);
+	} zend_catch {
+		catched = 1;
+	} zend_end_try();
+
+	if (catched) {
+		goto err_bailout;
+	}
+
+	if (op_array == NULL) {
+		goto err_oparray;
+	}
+
+	if (!XG(initial_compile_file_called)) {
+		xc_sandbox_free(&sandbox, XC_InstallNoBinding TSRMLS_CC);
+		ENTER_LOCK(cache) {
+			cache->compiling = 0;
+			/* it's not cachable, but don't scare the users with high misses */
+			cache->misses --;
+		} LEAVE_LOCK(cache);
+		return op_array;
+	}
+
+	filename = h->opened_path ? h->opened_path : h->filename;
+	/* none-inode enabled entry hash/compare on name
+	 * do not update to its name to real pathname
+	 */
+#ifdef HAVE_INODE
+	if (xce.data.php->inode)
+	{
+		if (xce.name.str.val != filename) {
+			xce.name.str.val = filename;
+			xce.name.str.len = strlen(filename);
+		}
+	}
+#endif
+
+#ifdef HAVE_XCACHE_OPTIMIZER
+	if (XG(optimizer)) {
+		xc_optimize(op_array TSRMLS_CC);
+	}
+#endif
+	/* }}} */
+	/* {{{ prepare */
+	php.op_array      = op_array;
+
+#ifdef HAVE_XCACHE_CONSTANT
+	php.constinfo_cnt  = zend_hash_num_elements(EG(zend_constants)) - old_constinfo_cnt;
+#endif
+	php.funcinfo_cnt   = zend_hash_num_elements(CG(function_table)) - old_funcinfo_cnt;
+	php.classinfo_cnt  = zend_hash_num_elements(CG(class_table))    - old_classinfo_cnt;
+#ifdef ZEND_ENGINE_2_1
+	/* {{{ count php.autoglobal_cnt */ {
+		Bucket *b;
+
+		php.autoglobal_cnt = 0;
+		for (b = CG(auto_globals)->pListHead; b != NULL; b = b->pListNext) {
+			zend_auto_global *auto_global = (zend_auto_global *) b->pData;
+			/* check if actived */
+			if (auto_global->auto_global_callback && !auto_global->armed) {
+				php.autoglobal_cnt ++;
+			}
+		}
+	}
+	/* }}} */
+#endif
+
+#define X_ALLOC_N(var, cnt) do {     \
+	if (php.cnt) {                   \
+		ECALLOC_N(php.var, php.cnt); \
+		if (!php.var) {              \
+			goto err_##var;          \
+		}                            \
+	}                                \
+	else {                           \
+		php.var = NULL;              \
+	}                                \
+} while (0)
+
+#ifdef HAVE_XCACHE_CONSTANT
+	X_ALLOC_N(constinfos,  constinfo_cnt);
+#endif
+	X_ALLOC_N(funcinfos,   funcinfo_cnt);
+	X_ALLOC_N(classinfos,  classinfo_cnt);
+#ifdef ZEND_ENGINE_2_1
+	X_ALLOC_N(autoglobals, autoglobal_cnt);
+#endif
+#undef X_ALLOC
+	/* }}} */
+	/* {{{ shallow copy, pointers only */ {
+		Bucket *b;
+		unsigned int i;
+		unsigned int j;
+
+#define COPY_H(vartype, var, cnt, name, datatype) do {        \
+	for (i = 0, j = 0; b; i ++, b = b->pListNext) {           \
+		vartype *data = &php.var[j];                          \
+                                                              \
+		if (i < old_##cnt) {                                  \
+			continue;                                         \
+		}                                                     \
+		j ++;                                                 \
+                                                              \
+		assert(i < old_##cnt + php.cnt);                      \
+		assert(b->pData);                                     \
+		memcpy(&data->name, b->pData, sizeof(datatype));      \
+		UNISW(NOTHING, data->type = b->key.type;)             \
+		if (UNISW(1, b->key.type == IS_STRING)) {             \
+			ZSTR_S(data->key)      = BUCKET_KEY_S(b);          \
+		}                                                     \
+		else {                                                \
+			ZSTR_U(data->key)      = BUCKET_KEY_U(b);         \
+		}                                                     \
+		data->key_size   = b->nKeyLength;                     \
+		data->h          = b->h;                              \
+	}                                                         \
+} while(0)
+
+#ifdef HAVE_XCACHE_CONSTANT
+		b = EG(zend_constants)->pListHead; COPY_H(xc_constinfo_t, constinfos, constinfo_cnt, constant, zend_constant);
+#endif
+		b = CG(function_table)->pListHead; COPY_H(xc_funcinfo_t,  funcinfos,  funcinfo_cnt,  func,     zend_function);
+		b = CG(class_table)->pListHead;    COPY_H(xc_classinfo_t, classinfos, classinfo_cnt, cest,     xc_cest_t);
+
+#undef COPY_H
+
+		/* for ZE1, cest need to be fixed inside store */
+
+#ifdef ZEND_ENGINE_2_1
+		/* scan for acatived auto globals */
+		i = 0;
+		for (b = CG(auto_globals)->pListHead; b != NULL; b = b->pListNext) {
+			zend_auto_global *auto_global = (zend_auto_global *) b->pData;
+			/* check if actived */
+			if (auto_global->auto_global_callback && !auto_global->armed) {
+				xc_autoglobal_t *data = &php.autoglobals[i];
+
+				assert(i < php.autoglobal_cnt);
+				i ++;
+				UNISW(NOTHING, data->type = b->key.type;)
+				if (UNISW(1, b->key.type == IS_STRING)) {
+					ZSTR_S(data->key)     = BUCKET_KEY_S(b);
+				}
+				else {
+					ZSTR_U(data->key)     = BUCKET_KEY_U(b);
+				}
+				data->key_len = b->nKeyLength - 1;
+				data->h       = b->h;
+			}
+		}
+#endif
+	}
+	/* }}} */
+#ifndef ZEND_COMPILE_DELAYED_BINDING
+	/* {{{ find inherited classes that should be early-binding */
+	php.have_early_binding = 0;
+	{
+		int i;
+		for (i = 0; i < php.classinfo_cnt; i ++) {
+			php.classinfos[i].oplineno = -1;
+		}
+	}
+
+	xc_undo_pass_two(php.op_array TSRMLS_CC);
+	xc_foreach_early_binding_class(php.op_array, xc_cache_early_binding_class_cb, (void *) &php TSRMLS_CC);
+	xc_redo_pass_two(php.op_array TSRMLS_CC);
+	/* }}} */
+#endif
+
+#ifdef SHOW_DPRINT
+	xc_dprint(&xce, 0 TSRMLS_CC);
+#endif
+	ENTER_LOCK_EX(cache) { /* {{{ store/add entry */
+		stored_xce = xc_entry_store_dmz(&xce TSRMLS_CC);
+	} LEAVE_LOCK_EX(cache);
+	/* }}} */
+	TRACE("%s", "stored");
+
+#define X_FREE(var) \
+	if (xce.data.php->var) { \
+		efree(xce.data.php->var); \
+	} \
+err_##var:
+
+#ifdef ZEND_ENGINE_2_1
+	X_FREE(autoglobals)
+#endif
+	X_FREE(classinfos)
+	X_FREE(funcinfos)
+#ifdef HAVE_XCACHE_CONSTANT
+	X_FREE(constinfos)
+#endif
+#undef X_FREE
+
+err_oparray:
+err_bailout:
+
+	if (xc_test && stored_xce) {
+		/* free it, no install. restore now */
+		xc_sandbox_free(&sandbox, XC_NoInstall TSRMLS_CC);
+	}
+	else if (!op_array) {
+		/* failed to compile free it, no install */
+		xc_sandbox_free(&sandbox, XC_NoInstall TSRMLS_CC);
+	}
+	else {
+		zend_op_array *old_active_op_array = CG(active_op_array);
+		CG(active_op_array) = op_array;
+		xc_sandbox_free(&sandbox, XC_Install TSRMLS_CC);
+		CG(active_op_array) = old_active_op_array;
+	}
+
+	ENTER_LOCK(cache) {
+		cache->compiling = 0;
+	} LEAVE_LOCK(cache);
+	if (catched) {
+		cache->errors ++;
+		zend_bailout();
+	}
+	if (xc_test && stored_xce) {
+#ifdef ZEND_ENGINE_2
+		destroy_op_array(op_array TSRMLS_CC);
+#else
+		destroy_op_array(op_array);
+#endif
+		efree(op_array);
+		h = NULL;
+		goto restore;
+	}
+	return op_array;
+
+restore:
+	CG(in_compilation)    = 1;
+	CG(compiled_filename) = stored_xce->name.str.val;
+	CG(zend_lineno)       = 0;
+	TRACE("restoring %s", stored_xce->name.str.val);
+	xc_processor_restore_xc_entry_t(&xce, stored_xce, xc_readonly_protection TSRMLS_CC);
+#ifdef SHOW_DPRINT
+	xc_dprint(&xce, 0 TSRMLS_CC);
+#endif
+
+	catched = 0;
+	zend_try {
+		op_array = xc_entry_install(&xce, h TSRMLS_CC);
+	} zend_catch {
+		catched = 1;
+	} zend_end_try();
+
+#define X_FREE(var) \
+	if (xce.data.php->var) { \
+		efree(xce.data.php->var); \
+	}
+	X_FREE(classinfos)
+	X_FREE(funcinfos)
+#ifdef HAVE_XCACHE_CONSTANT
+	X_FREE(constinfos)
+#endif
+#undef X_FREE
+	efree(xce.data.php);
+
+	if (catched) {
+		zend_bailout();
+	}
+	CG(in_compilation)    = 0;
+	CG(compiled_filename) = NULL;
+	TRACE("restored  %s", stored_xce->name.str.val);
+	return op_array;
+}
+/* }}} */
+
+/* gdb helper functions, but N/A for coredump */
+int xc_is_rw(const void *p) /* {{{ */
+{
+	xc_shm_t *shm;
+	int i;
+
+	if (xc_php_caches) {
+		for (i = 0; i < xc_php_hcache.size; i ++) {
+			shm = xc_php_caches[i]->shm;
+			if (shm->handlers->is_readwrite(shm, p)) {
+				return 1;
+			}
+		}
+	}
+
+	if (xc_var_caches) {
+		for (i = 0; i < xc_var_hcache.size; i ++) {
+			shm = xc_var_caches[i]->shm;
+			if (shm->handlers->is_readwrite(shm, p)) {
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+/* }}} */
+int xc_is_ro(const void *p) /* {{{ */
+{
+	xc_shm_t *shm;
+	int i;
+
+	if (xc_php_caches) {
+		for (i = 0; i < xc_php_hcache.size; i ++) {
+			shm = xc_php_caches[i]->shm;
+			if (shm->handlers->is_readonly(shm, p)) {
+				return 1;
+			}
+		}
+	}
+
+	if (xc_var_caches) {
+		for (i = 0; i < xc_var_hcache.size; i ++) {
+			shm = xc_var_caches[i]->shm;
+			if (shm->handlers->is_readonly(shm, p)) {
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+/* }}} */
+int xc_is_shm(const void *p) /* {{{ */
+{
+	return xc_is_ro(p) || xc_is_rw(p);
+}
+/* }}} */
+
+#ifdef ZEND_ENGINE_2
+/* {{{ xc_gc_op_array_t */
+typedef struct {
+	zend_uint num_args;
+	zend_arg_info *arg_info;
+} xc_gc_op_array_t;
+/* }}} */
+void xc_gc_add_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	xc_gc_op_array_t gc_op_array;
+	gc_op_array.num_args = op_array->num_args;
+	gc_op_array.arg_info = op_array->arg_info;
+#ifdef ZEND_ENGINE_2
+	zend_hash_next_index_insert(&XG(gc_op_arrays), (void *) &gc_op_array, sizeof(gc_op_array), NULL);
+#endif
+}
+/* }}} */
+static void xc_gc_op_array(void *pDest) /* {{{ */
+{
+	xc_gc_op_array_t *op_array = (xc_gc_op_array_t *) pDest;
+	zend_uint i;
+	if (op_array->arg_info) {
+		for (i = 0; i < op_array->num_args; i++) {
+			efree((char *) ZSTR_V(op_array->arg_info[i].name));
+			if (ZSTR_V(op_array->arg_info[i].class_name)) {
+				efree((char *) ZSTR_V(op_array->arg_info[i].class_name));
+			}
+		}
+		efree(op_array->arg_info);
+	}
+}
+/* }}} */
+#endif
+
+/* module helper function */
+static int xc_init_constant(int module_number TSRMLS_DC) /* {{{ */
+{
+	typedef struct {
+		const char *prefix;
+		zend_uchar (*getsize)();
+		const char *(*get)(zend_uchar i);
+	} xc_meminfo_t;
+	xc_meminfo_t nameinfos[] = {
+		{ "",        xc_get_op_type_count,   xc_get_op_type   },
+		{ "",        xc_get_data_type_count, xc_get_data_type },
+		{ "",        xc_get_opcode_count,    xc_get_opcode    },
+		{ "OPSPEC_", xc_get_op_spec_count,   xc_get_op_spec   },
+		{ NULL, NULL, NULL }
+	};
+	xc_meminfo_t* p;
+	zend_uchar i, count;
+	char const_name[96];
+	int const_name_len;
+	int undefdone = 0;
+
+	for (p = nameinfos; p->getsize; p ++) {
+		count = p->getsize();
+		for (i = 0; i < count; i ++) {
+			const char *name = p->get(i);
+			if (!name) continue;
+			if (strcmp(name, "UNDEF") == 0) {
+				if (undefdone) continue;
+				undefdone = 1;
+			}
+			const_name_len = snprintf(const_name, sizeof(const_name), "XC_%s%s", p->prefix, name);
+			zend_register_long_constant(const_name, const_name_len+1, i, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
+		}
+	}
+
+	zend_register_long_constant(ZEND_STRS("XC_SIZEOF_TEMP_VARIABLE"), sizeof(temp_variable), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
+	zend_register_long_constant(ZEND_STRS("XC_TYPE_PHP"), XC_TYPE_PHP, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
+	zend_register_long_constant(ZEND_STRS("XC_TYPE_VAR"), XC_TYPE_VAR, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
+	zend_register_stringl_constant(ZEND_STRS("XCACHE_VERSION"), ZEND_STRL(XCACHE_VERSION), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
+	zend_register_stringl_constant(ZEND_STRS("XCACHE_MODULES"), ZEND_STRL(XCACHE_MODULES), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
+	return 0;
+}
+/* }}} */
+static xc_shm_t *xc_cache_destroy(xc_cache_t **caches, xc_hash_t *hcache) /* {{{ */
+{
+	int i;
+	xc_cache_t *cache;
+	xc_shm_t *shm;
+
+	if (!caches) {
+		return NULL;
+	}
+	shm = NULL;
+	for (i = 0; i < hcache->size; i ++) {
+		cache = caches[i];
+		if (cache) {
+			if (cache->lck) {
+				xc_lock_destroy(cache->lck);
+			}
+			/* do NOT free
+			if (cache->entries) {
+				cache->mem->handlers->free(cache->mem, cache->entries);
+			}
+			cache->mem->handlers->free(cache->mem, cache);
+			*/
+			shm = cache->shm;
+			shm->handlers->memdestroy(cache->mem);
+		}
+	}
+	free(caches);
+	return shm;
+}
+/* }}} */
+static xc_cache_t **xc_cache_init(xc_shm_t *shm, xc_hash_t *hcache, xc_hash_t *hentry, xc_shmsize_t shmsize) /* {{{ */
+{
+	xc_cache_t **caches = NULL, *cache;
+	xc_mem_t *mem;
+	time_t now = time(NULL);
+	int i;
+	xc_memsize_t memsize;
+
+	memsize = shmsize / hcache->size;
+
+	/* Don't let it break out of mem after ALIGNed
+	 * This is important for 
+	 * Simply loop until it fit our need
+	 */
+	while (ALIGN(memsize) * hcache->size > shmsize && ALIGN(memsize) != memsize) {
+		if (memsize < ALIGN(1)) {
+			CHECK(NULL, "cache too small");
+		}
+		memsize --;
+	}
+
+	CHECK(caches = calloc(hcache->size, sizeof(xc_cache_t *)), "caches OOM");
+
+	for (i = 0; i < hcache->size; i ++) {
+		CHECK(mem            = shm->handlers->meminit(shm, memsize), "Failed init memory allocator");
+		CHECK(cache          = mem->handlers->calloc(mem, 1, sizeof(xc_cache_t)), "cache OOM");
+		CHECK(cache->entries = mem->handlers->calloc(mem, hentry->size, sizeof(xc_entry_t*)), "entries OOM");
+		CHECK(cache->lck     = xc_lock_init(NULL), "can't create lock");
+
+		cache->hcache  = hcache;
+		cache->hentry  = hentry;
+		cache->shm     = shm;
+		cache->mem     = mem;
+		cache->cacheid = i;
+		cache->last_gc_deletes = now;
+		cache->last_gc_expires = now;
+		caches[i] = cache;
+	}
+	return caches;
+
+err:
+	if (caches) {
+		xc_cache_destroy(caches, hcache);
+	}
+	return NULL;
+}
+/* }}} */
+static void xc_destroy() /* {{{ */
+{
+	xc_shm_t *shm = NULL;
+
+	if (old_compile_file) {
+		zend_compile_file = old_compile_file;
+		old_compile_file = NULL;
+	}
+
+	if (origin_compile_file) {
+		zend_compile_file = origin_compile_file;
+		origin_compile_file = NULL;
+	}
+
+	if (xc_php_caches) {
+		shm = xc_cache_destroy(xc_php_caches, &xc_php_hcache);
+		xc_php_caches = NULL;
+	}
+
+	if (xc_var_caches) {
+		shm = xc_cache_destroy(xc_var_caches, &xc_var_hcache);
+		xc_var_caches = NULL;
+	}
+
+	if (shm) {
+		xc_shm_destroy(shm);
+	}
+
+	xc_initized = 0;
+}
+/* }}} */
+static int xc_init(int module_number TSRMLS_DC) /* {{{ */
+{
+	xc_shm_t *shm;
+	xc_shmsize_t shmsize = ALIGN(xc_php_size) + ALIGN(xc_var_size);
+
+	xc_php_caches = xc_var_caches = NULL;
+	shm = NULL;
+
+	if (shmsize < (size_t) xc_php_size || shmsize < (size_t) xc_var_size) {
+		zend_error(E_ERROR, "XCache: neither xcache.size nor xcache.var_size can be negative");
+		goto err;
+	}
+
+	if (xc_php_size || xc_var_size) {
+		CHECK(shm = xc_shm_init(xc_shm_scheme, shmsize, xc_readonly_protection, xc_mmap_path, NULL), "Cannot create shm");
+		if (!shm->handlers->can_readonly(shm)) {
+			xc_readonly_protection = 0;
+		}
+
+		if (xc_php_size) {
+			old_compile_file = zend_compile_file;
+			zend_compile_file = xc_compile_file;
+
+			CHECK(xc_php_caches = xc_cache_init(shm, &xc_php_hcache, &xc_php_hentry, xc_php_size), "failed init opcode cache");
+		}
+
+		if (xc_var_size) {
+			CHECK(xc_var_caches = xc_cache_init(shm, &xc_var_hcache, &xc_var_hentry, xc_var_size), "failed init variable cache");
+		}
+	}
+	return SUCCESS;
+
+err:
+	xc_destroy();
+	if (xc_php_caches || xc_var_caches) {
+		/* shm destroied in xc_destroy() */
+	}
+	else if (shm) {
+		xc_shm_destroy(shm);
+	}
+	return 0;
+}
+/* }}} */
+static void xc_request_init(TSRMLS_D) /* {{{ */
+{
+	int i;
+
+	if (!XG(internal_table_copied)) {
+		zend_function tmp_func;
+		xc_cest_t tmp_cest;
+
+#ifdef HAVE_XCACHE_CONSTANT
+		zend_hash_destroy(&XG(internal_constant_table));
+#endif
+		zend_hash_destroy(&XG(internal_function_table));
+		zend_hash_destroy(&XG(internal_class_table));
+
+#ifdef HAVE_XCACHE_CONSTANT
+		zend_hash_init_ex(&XG(internal_constant_table), 20,  NULL, (dtor_func_t) xc_zend_constant_dtor, 1, 0);
+#endif
+		zend_hash_init_ex(&XG(internal_function_table), 100, NULL, NULL, 1, 0);
+		zend_hash_init_ex(&XG(internal_class_table),    10,  NULL, NULL, 1, 0);
+
+#ifdef HAVE_XCACHE_CONSTANT
+		xc_copy_internal_zend_constants(&XG(internal_constant_table), EG(zend_constants));
+#endif
+		zend_hash_copy(&XG(internal_function_table), CG(function_table), NULL, &tmp_func, sizeof(tmp_func));
+		zend_hash_copy(&XG(internal_class_table), CG(class_table), NULL, &tmp_cest, sizeof(tmp_cest));
+
+		XG(internal_table_copied) = 1;
+	}
+	if (xc_php_caches && !XG(php_holds)) {
+		XG(php_holds) = calloc(xc_php_hcache.size, sizeof(xc_stack_t));
+		for (i = 0; i < xc_php_hcache.size; i ++) {
+			xc_stack_init(&XG(php_holds[i]));
+		}
+	}
+
+	if (xc_var_caches && !XG(var_holds)) {
+		XG(var_holds) = calloc(xc_var_hcache.size, sizeof(xc_stack_t));
+		for (i = 0; i < xc_var_hcache.size; i ++) {
+			xc_stack_init(&XG(var_holds[i]));
+		}
+	}
+
+#ifdef ZEND_ENGINE_2
+	zend_hash_init(&XG(gc_op_arrays), 32, NULL, xc_gc_op_array, 0);
+#endif
+
+#if PHP_API_VERSION <= 20041225
+	XG(request_time) = time(NULL);
+#else
+	XG(request_time) = sapi_get_request_time(TSRMLS_C);
+#endif
+
+#ifdef HAVE_XCACHE_COVERAGER
+	xc_coverager_request_init(TSRMLS_C);
+#endif
+}
+/* }}} */
+static void xc_request_shutdown(TSRMLS_D) /* {{{ */
+{
+	xc_entry_unholds(TSRMLS_C);
+#ifdef ZEND_ENGINE_2
+	zend_hash_destroy(&XG(gc_op_arrays));
+#endif
+	xc_gc_expires_php(TSRMLS_C);
+	xc_gc_expires_var(TSRMLS_C);
+	xc_gc_deletes(TSRMLS_C);
+#ifdef HAVE_XCACHE_COVERAGER
+	xc_coverager_request_shutdown(TSRMLS_C);
+#endif
+}
+/* }}} */
+/* {{{ PHP_GINIT_FUNCTION(xcache) */
+static
+#ifdef PHP_GINIT_FUNCTION
+PHP_GINIT_FUNCTION(xcache)
+#else
+void xc_init_globals(zend_xcache_globals* xcache_globals TSRMLS_DC)
+#endif
+{
+	memset(xcache_globals, 0, sizeof(zend_xcache_globals));
+
+#ifdef HAVE_XCACHE_CONSTANT
+	zend_hash_init_ex(&xcache_globals->internal_constant_table, 1, NULL, (dtor_func_t) xc_zend_constant_dtor, 1, 0);
+#endif
+	zend_hash_init_ex(&xcache_globals->internal_function_table, 1, NULL, NULL, 1, 0);
+	zend_hash_init_ex(&xcache_globals->internal_class_table,    1, NULL, NULL, 1, 0);
+}
+/* }}} */
+/* {{{ PHP_GSHUTDOWN_FUNCTION(xcache) */
+static
+#ifdef PHP_GSHUTDOWN_FUNCTION
+PHP_GSHUTDOWN_FUNCTION(xcache)
+#else
+void xc_shutdown_globals(zend_xcache_globals* xcache_globals TSRMLS_DC)
+#endif
+{
+	int i;
+
+	if (xcache_globals->php_holds != NULL) {
+		for (i = 0; i < xc_php_hcache.size; i ++) {
+			xc_stack_destroy(&xcache_globals->php_holds[i]);
+		}
+		free(xcache_globals->php_holds);
+		xcache_globals->php_holds = NULL;
+	}
+
+	if (xcache_globals->var_holds != NULL) {
+		for (i = 0; i < xc_var_hcache.size; i ++) {
+			xc_stack_destroy(&xcache_globals->var_holds[i]);
+		}
+		free(xcache_globals->var_holds);
+		xcache_globals->var_holds = NULL;
+	}
+
+	if (xcache_globals->internal_table_copied) {
+#ifdef HAVE_XCACHE_CONSTANT
+		zend_hash_destroy(&xcache_globals->internal_constant_table);
+#endif
+		zend_hash_destroy(&xcache_globals->internal_function_table);
+		zend_hash_destroy(&xcache_globals->internal_class_table);
+	}
+}
+/* }}} */
+
+/* user functions */
+static int xcache_admin_auth_check(TSRMLS_D) /* {{{ */
+{
+	zval **server = NULL;
+	zval **user = NULL;
+	zval **pass = NULL;
+	char *admin_user = NULL;
+	char *admin_pass = NULL;
+	HashTable *ht;
+
+	/* auth disabled, nothing to do.. */
+	if (!XG(auth_enabled)) {
+		return 1;
+	}
+
+	if (cfg_get_string("xcache.admin.user", &admin_user) == FAILURE || !admin_user[0]) {
+		admin_user = NULL;
+	}
+	if (cfg_get_string("xcache.admin.pass", &admin_pass) == FAILURE || !admin_pass[0]) {
+		admin_pass = NULL;
+	}
+
+	if (admin_user == NULL || admin_pass == NULL) {
+		php_error_docref(XCACHE_WIKI_URL "/InstallAdministration" TSRMLS_CC, E_ERROR,
+				"xcache.admin.user and/or xcache.admin.pass settings is not configured."
+				" Make sure you've modified the correct php ini file for your php used in webserver.");
+		zend_bailout();
+	}
+	if (strlen(admin_pass) != 32) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "xcache.admin.pass is %lu chars unexpectedly, it is supposed to be the password after md5() which should be 32 chars", (unsigned long) strlen(admin_pass));
+		zend_bailout();
+	}
+
+#ifdef ZEND_ENGINE_2_1
+	zend_is_auto_global("_SERVER", sizeof("_SERVER") - 1 TSRMLS_CC);
+#endif
+	if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server) != SUCCESS || Z_TYPE_PP(server) != IS_ARRAY) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "_SERVER is corrupted");
+		zend_bailout();
+	}
+	ht = HASH_OF((*server));
+
+	if (zend_hash_find(ht, "PHP_AUTH_USER", sizeof("PHP_AUTH_USER"), (void **) &user) == FAILURE) {
+	 	user = NULL;
+	}
+	else if (Z_TYPE_PP(user) != IS_STRING) {
+		user = NULL;
+	}
+
+	if (zend_hash_find(ht, "PHP_AUTH_PW", sizeof("PHP_AUTH_PW"), (void **) &pass) == FAILURE) {
+	 	pass = NULL;
+	}
+	else if (Z_TYPE_PP(pass) != IS_STRING) {
+		pass = NULL;
+	}
+
+	if (user != NULL && pass != NULL && strcmp(admin_user, Z_STRVAL_PP(user)) == 0) {
+		PHP_MD5_CTX context;
+		char md5str[33];
+		unsigned char digest[16];
+
+		PHP_MD5Init(&context);
+		PHP_MD5Update(&context, (unsigned char *) Z_STRVAL_PP(pass), Z_STRLEN_PP(pass));
+		PHP_MD5Final(digest, &context);
+
+		md5str[0] = '\0';
+		make_digest(md5str, digest);
+		if (strcmp(admin_pass, md5str) == 0) {
+			return 1;
+		}
+	}
+
+#define STR "HTTP/1.0 401 Unauthorized"
+	sapi_add_header_ex(STR, sizeof(STR) - 1, 1, 1 TSRMLS_CC);
+#undef STR
+#define STR "WWW-authenticate: Basic Realm=\"XCache Administration\""
+	sapi_add_header_ex(STR, sizeof(STR) - 1, 1, 1 TSRMLS_CC);
+#undef STR
+#define STR "Content-type: text/html; charset=UTF-8"
+	sapi_add_header_ex(STR, sizeof(STR) - 1, 1, 1 TSRMLS_CC);
+#undef STR
+	ZEND_PUTS("<html>\n");
+	ZEND_PUTS("<head><title>XCache Authentication Failed</title></head>\n");
+	ZEND_PUTS("<body>\n");
+	ZEND_PUTS("<h1>XCache Authentication Failed</h1>\n");
+	ZEND_PUTS("<p>You're not authorized to access this page due to wrong username and/or password you typed.<br />The following check points is suggested:</p>\n");
+	ZEND_PUTS("<ul>\n");
+	ZEND_PUTS("<li>Be aware that `Username' and `Password' is case sense. Check capslock status led on your keyboard, and punch left/right Shift keys once for each</li>\n");
+	ZEND_PUTS("<li>Make sure the md5 password is generated correctly. You may use <a href=\"mkpassword.php\">mkpassword.php</a></li>\n");
+	ZEND_PUTS("<li>Reload browser cache by pressing F5 and/or Ctrl+F5, or simply clear browser cache after you've updated username/password in php ini.</li>\n");
+	ZEND_PUTS("</ul>\n");
+	ZEND_PUTS("Check <a href=\"" XCACHE_WIKI_URL "/InstallAdministration\">XCache wiki page</a> for more information.\n");
+	ZEND_PUTS("</body>\n");
+	ZEND_PUTS("</html>\n");
+
+	zend_bailout();
+	return 0;
+}
+/* }}} */
+/* {{{ xcache_admin_operate */
+typedef enum { XC_OP_COUNT, XC_OP_INFO, XC_OP_LIST, XC_OP_CLEAR } xcache_op_type;
+static void xcache_admin_operate(xcache_op_type optype, INTERNAL_FUNCTION_PARAMETERS)
+{
+	long type;
+	int size;
+	xc_cache_t **caches, *cache;
+	long id = 0;
+
+	xcache_admin_auth_check(TSRMLS_C);
+
+	if (!xc_initized) {
+		RETURN_NULL();
+	}
+
+	if (optype == XC_OP_COUNT) {
+		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type) == FAILURE) {
+			return;
+		}
+	}
+	else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &type, &id) == FAILURE) {
+		return;
+	}
+
+	switch (type) {
+		case XC_TYPE_PHP:
+			size = xc_php_hcache.size;
+			caches = xc_php_caches;
+			break;
+
+		case XC_TYPE_VAR:
+			size = xc_var_hcache.size;
+			caches = xc_var_caches;
+			break;
+
+		default:
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown type %ld", type);
+			RETURN_FALSE;
+	}
+
+	switch (optype) {
+		case XC_OP_COUNT:
+			RETURN_LONG(size)
+			break;
+
+		case XC_OP_INFO:
+		case XC_OP_LIST:
+			if (id < 0 || id >= size) {
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache not exists");
+				RETURN_FALSE;
+			}
+
+			array_init(return_value);
+
+			cache = caches[id];
+			ENTER_LOCK(cache) {
+				if (optype == XC_OP_INFO) {
+					xc_fillinfo_dmz(type, cache, return_value TSRMLS_CC);
+				}
+				else {
+					xc_filllist_dmz(cache, return_value TSRMLS_CC);
+				}
+			} LEAVE_LOCK(cache);
+			break;
+		case XC_OP_CLEAR:
+			{
+				xc_entry_t *e, *next;
+				int i, c;
+
+				if (id < 0 || id >= size) {
+					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache not exists");
+					RETURN_FALSE;
+				}
+
+				cache = caches[id];
+				ENTER_LOCK(cache) {
+					for (i = 0, c = cache->hentry->size; i < c; i ++) {
+						for (e = cache->entries[i]; e; e = next) {
+							next = e->next;
+							xc_entry_remove_dmz(e TSRMLS_CC);
+						}
+						cache->entries[i] = NULL;
+					}
+				} LEAVE_LOCK(cache);
+				xc_gc_deletes(TSRMLS_C);
+			}
+			break;
+
+		default:
+			assert(0);
+	}
+}
+/* }}} */
+/* {{{ proto int xcache_count(int type)
+   Return count of cache on specified cache type */
+PHP_FUNCTION(xcache_count)
+{
+	xcache_admin_operate(XC_OP_COUNT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+/* {{{ proto array xcache_info(int type, int id)
+   Get cache info by id on specified cache type */
+PHP_FUNCTION(xcache_info)
+{
+	xcache_admin_operate(XC_OP_INFO, INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+/* {{{ proto array xcache_list(int type, int id)
+   Get cache entries list by id on specified cache type */
+PHP_FUNCTION(xcache_list)
+{
+	xcache_admin_operate(XC_OP_LIST, INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+/* {{{ proto array xcache_clear_cache(int type, int id)
+   Clear cache by id on specified cache type */
+PHP_FUNCTION(xcache_clear_cache)
+{
+	xcache_admin_operate(XC_OP_CLEAR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+
+#define VAR_DISABLED_WARNING() do { \
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "xcache.var_size is either 0 or too small to enable var data caching"); \
+} while (0)
+
+static int xc_entry_init_key_var(xc_entry_t *xce, zval *name TSRMLS_DC) /* {{{ */
+{
+	xc_hash_value_t hv;
+	int cacheid;
+
+	switch (Z_TYPE_P(name)) {
+#ifdef IS_UNICODE
+		case IS_UNICODE:
+#endif
+		case IS_STRING:
+			break;
+		default:
+#ifdef IS_UNICODE
+			convert_to_unicode(name);
+#else
+			convert_to_string(name);
+#endif
+	}
+#ifdef IS_UNICODE
+	xce->name_type = name->type;
+#endif
+	xce->name = name->value;
+
+	hv = xc_entry_hash_var(xce TSRMLS_CC);
+
+	cacheid = (hv & xc_var_hcache.mask);
+	xce->cache = xc_var_caches[cacheid];
+	hv >>= xc_var_hcache.bits;
+	xce->hvalue = (hv & xc_var_hentry.mask);
+
+	xce->type = XC_TYPE_VAR;
+	return SUCCESS;
+}
+/* }}} */
+/* {{{ proto mixed xcache_get(string name)
+   Get cached data by specified name */
+PHP_FUNCTION(xcache_get)
+{
+	xc_entry_t xce, *stored_xce;
+	xc_entry_data_var_t var;
+	zval *name;
+	int found = 0;
+
+	if (!xc_var_caches) {
+		VAR_DISABLED_WARNING();
+		RETURN_NULL();
+	}
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) {
+		return;
+	}
+	xce.data.var = &var;
+	xc_entry_init_key_var(&xce, name TSRMLS_CC);
+
+	ENTER_LOCK(xce.cache) {
+		stored_xce = xc_entry_find_dmz(&xce TSRMLS_CC);
+		if (stored_xce) {
+			if (!VAR_ENTRY_EXPIRED(stored_xce)) {
+				found = 1;
+				xc_processor_restore_zval(return_value, stored_xce->data.var->value, stored_xce->have_references TSRMLS_CC);
+				/* return */
+				break;
+			}
+			else {
+				xc_entry_remove_dmz(stored_xce TSRMLS_CC);
+			}
+		}
+
+		RETVAL_NULL();
+	} LEAVE_LOCK(xce.cache);
+	if (found) {
+		xc_cache_hit_dmz(xce.cache TSRMLS_CC);
+	}
+	else {
+		xce.cache->misses ++;
+	}
+}
+/* }}} */
+/* {{{ proto bool  xcache_set(string name, mixed value [, int ttl])
+   Store data to cache by specified name */
+PHP_FUNCTION(xcache_set)
+{
+	xc_entry_t xce, *stored_xce;
+	xc_entry_data_var_t var;
+	zval *name;
+	zval *value;
+
+	if (!xc_var_caches) {
+		VAR_DISABLED_WARNING();
+		RETURN_NULL();
+	}
+
+	xce.ttl = XG(var_ttl);
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &name, &value, &xce.ttl) == FAILURE) {
+		return;
+	}
+
+	/* max ttl */
+	if (xc_var_maxttl && (!xce.ttl || xce.ttl > xc_var_maxttl)) {
+		xce.ttl = xc_var_maxttl;
+	}
+
+	xce.data.var = &var;
+	xc_entry_init_key_var(&xce, name TSRMLS_CC);
+
+	ENTER_LOCK(xce.cache) {
+		stored_xce = xc_entry_find_dmz(&xce TSRMLS_CC);
+		if (stored_xce) {
+			xc_entry_remove_dmz(stored_xce TSRMLS_CC);
+		}
+		var.value = value;
+		RETVAL_BOOL(xc_entry_store_dmz(&xce TSRMLS_CC) != NULL ? 1 : 0);
+	} LEAVE_LOCK(xce.cache);
+}
+/* }}} */
+/* {{{ proto bool  xcache_isset(string name)
+   Check if an entry exists in cache by specified name */
+PHP_FUNCTION(xcache_isset)
+{
+	xc_entry_t xce, *stored_xce;
+	xc_entry_data_var_t var;
+	zval *name;
+	int found = 0;
+
+	if (!xc_var_caches) {
+		VAR_DISABLED_WARNING();
+		RETURN_FALSE;
+	}
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) {
+		return;
+	}
+	xce.data.var = &var;
+	xc_entry_init_key_var(&xce, name TSRMLS_CC);
+
+	ENTER_LOCK(xce.cache) {
+		stored_xce = xc_entry_find_dmz(&xce TSRMLS_CC);
+		if (stored_xce) {
+			if (!VAR_ENTRY_EXPIRED(stored_xce)) {
+				found = 1;
+				RETVAL_TRUE;
+				/* return */
+				break;
+			}
+			else {
+				xc_entry_remove_dmz(stored_xce TSRMLS_CC);
+			}
+		}
+
+		RETVAL_FALSE;
+	} LEAVE_LOCK(xce.cache);
+	if (found) {
+		xc_cache_hit_dmz(xce.cache TSRMLS_CC);
+	}
+	else {
+		xce.cache->misses ++;
+	}
+}
+/* }}} */
+/* {{{ proto bool  xcache_unset(string name)
+   Unset existing data in cache by specified name */
+PHP_FUNCTION(xcache_unset)
+{
+	xc_entry_t xce, *stored_xce;
+	xc_entry_data_var_t var;
+	zval *name;
+
+	if (!xc_var_caches) {
+		VAR_DISABLED_WARNING();
+		RETURN_FALSE;
+	}
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) {
+		return;
+	}
+	xce.data.var = &var;
+	xc_entry_init_key_var(&xce, name TSRMLS_CC);
+
+	ENTER_LOCK(xce.cache) {
+		stored_xce = xc_entry_find_dmz(&xce TSRMLS_CC);
+		if (stored_xce) {
+			xc_entry_remove_dmz(stored_xce TSRMLS_CC);
+			RETVAL_TRUE;
+		}
+		else {
+			RETVAL_FALSE;
+		}
+	} LEAVE_LOCK(xce.cache);
+}
+/* }}} */
+static inline void xc_var_inc_dec(int inc, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
+{
+	xc_entry_t xce, *stored_xce;
+	xc_entry_data_var_t var, *stored_var;
+	zval *name;
+	long count = 1;
+	long value = 0;
+	zval oldzval;
+
+	if (!xc_var_caches) {
+		VAR_DISABLED_WARNING();
+		RETURN_NULL();
+	}
+
+	xce.ttl = XG(var_ttl);
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ll", &name, &count, &xce.ttl) == FAILURE) {
+		return;
+	}
+
+	/* max ttl */
+	if (xc_var_maxttl && (!xce.ttl || xce.ttl > xc_var_maxttl)) {
+		xce.ttl = xc_var_maxttl;
+	}
+
+	xce.data.var = &var;
+	xc_entry_init_key_var(&xce, name TSRMLS_CC);
+
+	ENTER_LOCK(xce.cache) {
+		stored_xce = xc_entry_find_dmz(&xce TSRMLS_CC);
+		if (stored_xce) {
+			TRACE("incdec: gotxce %s", xce.name.str.val);
+			/* timeout */
+			if (VAR_ENTRY_EXPIRED(stored_xce)) {
+				TRACE("%s", "incdec: expired");
+				xc_entry_remove_dmz(stored_xce TSRMLS_CC);
+				stored_xce = NULL;
+			}
+			else {
+				/* do it in place */
+				stored_var = stored_xce->data.var;
+				if (Z_TYPE_P(stored_var->value) == IS_LONG) {
+					zval *zv;
+					stored_xce->ctime = XG(request_time);
+					stored_xce->ttl   = xce.ttl;
+					TRACE("%s", "incdec: islong");
+					value = Z_LVAL_P(stored_var->value);
+					value += (inc == 1 ? count : - count);
+					RETVAL_LONG(value);
+
+					zv = (zval *) xce.cache->shm->handlers->to_readwrite(xce.cache->shm, (char *) stored_var->value);
+					Z_LVAL_P(zv) = value;
+					break; /* leave lock */
+				}
+				else {
+					TRACE("%s", "incdec: notlong");
+					xc_processor_restore_zval(&oldzval, stored_xce->data.var->value, stored_xce->have_references TSRMLS_CC);
+					convert_to_long(&oldzval);
+					value = Z_LVAL(oldzval);
+					zval_dtor(&oldzval);
+				}
+			}
+		}
+		else {
+			TRACE("incdec: %s not found", xce.name.str.val);
+		}
+
+		value += (inc == 1 ? count : - count);
+		RETVAL_LONG(value);
+		var.value = return_value;
+
+		if (stored_xce) {
+			xce.atime = stored_xce->atime;
+			xce.ctime = stored_xce->ctime;
+			xce.hits  = stored_xce->hits;
+			xc_entry_remove_dmz(stored_xce TSRMLS_CC);
+		}
+		xc_entry_store_dmz(&xce TSRMLS_CC);
+
+	} LEAVE_LOCK(xce.cache);
+}
+/* }}} */
+/* {{{ proto int xcache_inc(string name [, int value [, int ttl]])
+   Increase an int counter in cache by specified name, create it if not exists */
+PHP_FUNCTION(xcache_inc)
+{
+	xc_var_inc_dec(1, INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+/* {{{ proto int xcache_dec(string name [, int value [, int ttl]])
+   Decrease an int counter in cache by specified name, create it if not exists */
+PHP_FUNCTION(xcache_dec)
+{
+	xc_var_inc_dec(-1, INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+#ifdef HAVE_XCACHE_DPRINT
+/* {{{ proto bool  xcache_dprint(mixed value)
+   Prints variable (or value) internal struct (debug only) */
+PHP_FUNCTION(xcache_dprint)
+{
+	zval *value;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
+		return;
+	}
+	xc_dprint_zval(value, 0 TSRMLS_CC);
+}
+/* }}} */
+#endif
+/* {{{ proto string xcache_asm(string filename)
+ */
+#ifdef HAVE_XCACHE_ASSEMBLER
+PHP_FUNCTION(xcache_asm)
+{
+}
+#endif
+/* }}} */
+#ifdef HAVE_XCACHE_DISASSEMBLER
+/* {{{ proto array  xcache_dasm_file(string filename)
+   Disassemble file into opcode array by filename */
+PHP_FUNCTION(xcache_dasm_file)
+{
+	char *filename;
+	int filename_len;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+		return;
+	}
+	if (!filename_len) RETURN_FALSE;
+
+	xc_dasm_file(return_value, filename TSRMLS_CC);
+}
+/* }}} */
+/* {{{ proto array  xcache_dasm_string(string code)
+   Disassemble php code into opcode array */
+PHP_FUNCTION(xcache_dasm_string)
+{
+	zval *code;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &code) == FAILURE) {
+		return;
+	}
+	xc_dasm_string(return_value, code TSRMLS_CC);
+}
+/* }}} */
+#endif
+/* {{{ proto string xcache_encode(string filename)
+   Encode php file into XCache opcode encoded format */
+#ifdef HAVE_XCACHE_ENCODER
+PHP_FUNCTION(xcache_encode)
+{
+}
+#endif
+/* }}} */
+/* {{{ proto bool xcache_decode_file(string filename)
+   Decode(load) opcode from XCache encoded format file */
+#ifdef HAVE_XCACHE_DECODER
+PHP_FUNCTION(xcache_decode_file)
+{
+}
+#endif
+/* }}} */
+/* {{{ proto bool xcache_decode_string(string data)
+   Decode(load) opcode from XCache encoded format data */
+#ifdef HAVE_XCACHE_DECODER
+PHP_FUNCTION(xcache_decode_string)
+{
+}
+#endif
+/* }}} */
+/* {{{ xc_call_getter */
+typedef const char *(xc_name_getter_t)(zend_uchar type);
+static void xc_call_getter(xc_name_getter_t getter, int count, INTERNAL_FUNCTION_PARAMETERS)
+{
+	long spec;
+	const char *name;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &spec) == FAILURE) {
+		return;
+	}
+	if (spec >= 0 && spec < count) {
+		name = getter((zend_uchar) spec);
+		if (name) {
+			/* RETURN_STRING */
+			int len = strlen(name);
+			return_value->value.str.len = len;
+			return_value->value.str.val = estrndup(name, len);
+			return_value->type = IS_STRING; 
+			return;
+		}
+	}
+	RETURN_NULL();
+}
+/* }}} */
+/* {{{ proto string xcache_get_op_type(int op_type) */
+PHP_FUNCTION(xcache_get_op_type)
+{
+	xc_call_getter(xc_get_op_type, xc_get_op_type_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+/* {{{ proto string xcache_get_data_type(int type) */
+PHP_FUNCTION(xcache_get_data_type)
+{
+	xc_call_getter(xc_get_data_type, xc_get_data_type_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+/* {{{ proto string xcache_get_opcode(int opcode) */
+PHP_FUNCTION(xcache_get_opcode)
+{
+	xc_call_getter(xc_get_opcode, xc_get_opcode_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+/* {{{ proto string xcache_get_op_spec(int op_type) */
+PHP_FUNCTION(xcache_get_op_spec)
+{
+	xc_call_getter(xc_get_op_spec, xc_get_op_spec_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+#ifdef HAVE_XCACHE_OPCODE_SPEC_DEF
+/* {{{ proto string xcache_get_opcode_spec(int opcode) */
+PHP_FUNCTION(xcache_get_opcode_spec)
+{
+	long spec;
+	const xc_opcode_spec_t *opspec;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &spec) == FAILURE) {
+		return;
+	}
+	if ((zend_uchar) spec <= xc_get_opcode_spec_count()) {
+		opspec = xc_get_opcode_spec((zend_uchar) spec);
+		if (opspec) {
+			array_init(return_value);
+			add_assoc_long_ex(return_value, ZEND_STRS("ext"), opspec->ext);
+			add_assoc_long_ex(return_value, ZEND_STRS("op1"), opspec->op1);
+			add_assoc_long_ex(return_value, ZEND_STRS("op2"), opspec->op2);
+			add_assoc_long_ex(return_value, ZEND_STRS("res"), opspec->res);
+			return;
+		}
+	}
+	RETURN_NULL();
+}
+/* }}} */
+#endif
+/* {{{ proto mixed xcache_get_special_value(zval value) */
+PHP_FUNCTION(xcache_get_special_value)
+{
+	zval *value;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
+		return;
+	}
+
+	if (value->type == 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) {
+		*return_value = *value;
+		zval_copy_ctor(return_value);
+		return_value->type = IS_ARRAY;
+		return;
+	}
+
+	RETURN_NULL();
+}
+/* }}} */
+/* {{{ proto string xcache_coredump(int op_type) */
+PHP_FUNCTION(xcache_coredump)
+{
+	if (xc_test) {
+		raise(SIGSEGV);
+	}
+	else {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "xcache.test must be enabled to test xcache_coredump()");
+	}
+}
+/* }}} */
+/* {{{ proto string xcache_is_autoglobal(string name) */
+PHP_FUNCTION(xcache_is_autoglobal)
+{
+	char *name;
+	int name_len;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
+		return;
+	}
+
+	RETURN_BOOL(zend_hash_exists(CG(auto_globals), name, name_len + 1));
+}
+/* }}} */
+static function_entry xcache_functions[] = /* {{{ */
+{
+	PHP_FE(xcache_count,             NULL)
+	PHP_FE(xcache_info,              NULL)
+	PHP_FE(xcache_list,              NULL)
+	PHP_FE(xcache_clear_cache,       NULL)
+	PHP_FE(xcache_coredump,          NULL)
+#ifdef HAVE_XCACHE_ASSEMBLER
+	PHP_FE(xcache_asm,               NULL)
+#endif
+#ifdef HAVE_XCACHE_DISASSEMBLER
+	PHP_FE(xcache_dasm_file,         NULL)
+	PHP_FE(xcache_dasm_string,       NULL)
+#endif
+#ifdef HAVE_XCACHE_ENCODER
+	PHP_FE(xcache_encode,            NULL)
+#endif
+#ifdef HAVE_XCACHE_DECODER
+	PHP_FE(xcache_decode_file,       NULL)
+	PHP_FE(xcache_decode_string,     NULL)
+#endif
+#ifdef HAVE_XCACHE_COVERAGER
+	PHP_FE(xcache_coverager_decode,  NULL)
+	PHP_FE(xcache_coverager_start,   NULL)
+	PHP_FE(xcache_coverager_stop,    NULL)
+	PHP_FE(xcache_coverager_get,     NULL)
+#endif
+	PHP_FE(xcache_get_special_value, NULL)
+	PHP_FE(xcache_get_op_type,       NULL)
+	PHP_FE(xcache_get_data_type,     NULL)
+	PHP_FE(xcache_get_opcode,        NULL)
+#ifdef HAVE_XCACHE_OPCODE_SPEC_DEF
+	PHP_FE(xcache_get_opcode_spec,   NULL)
+#endif
+	PHP_FE(xcache_is_autoglobal,     NULL)
+	PHP_FE(xcache_inc,               NULL)
+	PHP_FE(xcache_dec,               NULL)
+	PHP_FE(xcache_get,               NULL)
+	PHP_FE(xcache_set,               NULL)
+	PHP_FE(xcache_isset,             NULL)
+	PHP_FE(xcache_unset,             NULL)
+#ifdef HAVE_XCACHE_DPRINT
+	PHP_FE(xcache_dprint,            NULL)
+#endif
+	{NULL, NULL,                     NULL}
+};
+/* }}} */
+
+/* old signal handlers {{{ */
+typedef void (*xc_sighandler_t)(int);
+#define FOREACH_SIG(sig) static xc_sighandler_t old_##sig##_handler = NULL
+#include "foreachcoresig.h"
+#undef FOREACH_SIG
+/* }}} */
+static void xcache_signal_handler(int sig);
+static void xcache_restore_signal_handler() /* {{{ */
+{
+#define FOREACH_SIG(sig) do { \
+	if (old_##sig##_handler != xcache_signal_handler) { \
+		signal(sig, old_##sig##_handler); \
+	} \
+	else { \
+		signal(sig, SIG_DFL); \
+	} \
+} while (0)
+#include "foreachcoresig.h"
+#undef FOREACH_SIG
+}
+/* }}} */
+static void xcache_init_signal_handler() /* {{{ */
+{
+#define FOREACH_SIG(sig) \
+	old_##sig##_handler = signal(sig, xcache_signal_handler)
+#include "foreachcoresig.h"
+#undef FOREACH_SIG
+}
+/* }}} */
+static void xcache_signal_handler(int sig) /* {{{ */
+{
+	xcache_restore_signal_handler();
+	if (xc_coredump_dir && xc_coredump_dir[0]) {
+		chdir(xc_coredump_dir);
+	}
+	raise(sig);
+}
+/* }}} */
+
+/* {{{ PHP_INI */
+
+static PHP_INI_MH(xc_OnUpdateDummy)
+{
+	return SUCCESS;
+}
+
+static PHP_INI_MH(xc_OnUpdateULong)
+{
+	zend_ulong *p = (zend_ulong *) mh_arg1;
+
+	*p = (zend_ulong) atoi(new_value);
+	return SUCCESS;
+}
+
+static PHP_INI_MH(xc_OnUpdateBool)
+{
+	zend_bool *p = (zend_bool *)mh_arg1;
+
+	if (strncasecmp("on", new_value, sizeof("on"))) {
+		*p = (zend_bool) atoi(new_value);
+	}
+	else {
+		*p = (zend_bool) 1;
+	}
+	return SUCCESS;
+}
+
+static PHP_INI_MH(xc_OnUpdateString)
+{
+	char **p = (char**)mh_arg1;
+	if (*p) {
+		pefree(*p, 1);
+	}
+	*p = pemalloc(strlen(new_value) + 1, 1);
+	strcpy(*p, new_value);
+	return SUCCESS;
+}
+
+#ifndef ZEND_ENGINE_2
+#define OnUpdateLong OnUpdateInt
+#endif
+
+#ifdef ZEND_WIN32
+#	define DEFAULT_PATH "xcache"
+#else
+#	define DEFAULT_PATH "/dev/zero"
+#endif
+PHP_INI_BEGIN()
+	PHP_INI_ENTRY1     ("xcache.mmap_path",     DEFAULT_PATH, PHP_INI_SYSTEM, xc_OnUpdateString,   &xc_mmap_path)
+	PHP_INI_ENTRY1     ("xcache.coredump_directory",      "", PHP_INI_SYSTEM, xc_OnUpdateString,   &xc_coredump_dir)
+	PHP_INI_ENTRY1     ("xcache.test",                   "0", PHP_INI_SYSTEM, xc_OnUpdateBool,     &xc_test)
+	PHP_INI_ENTRY1     ("xcache.readonly_protection",    "0", PHP_INI_SYSTEM, xc_OnUpdateBool,     &xc_readonly_protection)
+	/* opcode cache */
+	PHP_INI_ENTRY1     ("xcache.size",                   "0", PHP_INI_SYSTEM, xc_OnUpdateDummy,    NULL)
+	PHP_INI_ENTRY1     ("xcache.count",                  "1", PHP_INI_SYSTEM, xc_OnUpdateDummy,    NULL)
+	PHP_INI_ENTRY1     ("xcache.slots",                 "8K", PHP_INI_SYSTEM, xc_OnUpdateDummy,    NULL)
+	PHP_INI_ENTRY1     ("xcache.shm_scheme",          "mmap", PHP_INI_SYSTEM, xc_OnUpdateString,   &xc_shm_scheme)
+	PHP_INI_ENTRY1     ("xcache.ttl",                    "0", PHP_INI_SYSTEM, xc_OnUpdateULong,    &xc_php_ttl)
+	PHP_INI_ENTRY1     ("xcache.gc_interval",            "0", PHP_INI_SYSTEM, xc_OnUpdateULong,    &xc_php_gc_interval)
+	/* var cache */
+	PHP_INI_ENTRY1     ("xcache.var_size",               "0", PHP_INI_SYSTEM, xc_OnUpdateDummy,    NULL)
+	PHP_INI_ENTRY1     ("xcache.var_count",              "1", PHP_INI_SYSTEM, xc_OnUpdateDummy,    NULL)
+	PHP_INI_ENTRY1     ("xcache.var_slots",             "8K", PHP_INI_SYSTEM, xc_OnUpdateDummy,    NULL)
+	PHP_INI_ENTRY1     ("xcache.var_maxttl",             "0", PHP_INI_SYSTEM, xc_OnUpdateULong,    &xc_var_maxttl)
+	PHP_INI_ENTRY1     ("xcache.var_gc_interval",      "120", PHP_INI_SYSTEM, xc_OnUpdateULong,    &xc_var_gc_interval)
+
+	STD_PHP_INI_BOOLEAN("xcache.cacher",                 "1", PHP_INI_ALL,    OnUpdateBool,        cacher,            zend_xcache_globals, xcache_globals)
+	STD_PHP_INI_BOOLEAN("xcache.stat",                   "1", PHP_INI_ALL,    OnUpdateBool,        stat,              zend_xcache_globals, xcache_globals)
+	STD_PHP_INI_BOOLEAN("xcache.admin.enable_auth",      "1", PHP_INI_SYSTEM, OnUpdateBool,        auth_enabled,      zend_xcache_globals, xcache_globals)
+#ifdef HAVE_XCACHE_OPTIMIZER
+	STD_PHP_INI_BOOLEAN("xcache.optimizer",              "0", PHP_INI_ALL,    OnUpdateBool,        optimizer,         zend_xcache_globals, xcache_globals)
+#endif
+	STD_PHP_INI_ENTRY  ("xcache.var_ttl",                "0", PHP_INI_ALL,    OnUpdateLong,        var_ttl,           zend_xcache_globals, xcache_globals)
+#ifdef HAVE_XCACHE_COVERAGER
+	STD_PHP_INI_BOOLEAN("xcache.coverager"      ,        "0", PHP_INI_ALL,    OnUpdateBool,        coverager,         zend_xcache_globals, xcache_globals)
+	PHP_INI_ENTRY1     ("xcache.coveragedump_directory",  "", PHP_INI_SYSTEM, xc_OnUpdateDummy,    NULL)
+#endif
+PHP_INI_END()
+/* }}} */
+/* {{{ PHP_MINFO_FUNCTION(xcache) */
+static PHP_MINFO_FUNCTION(xcache)
+{
+	char buf[100];
+	char *ptr;
+	int left, len;
+	xc_shm_scheme_t *scheme;
+	char *covdumpdir;
+
+	php_info_print_table_start();
+	php_info_print_table_header(2, "XCache Support", "enabled");
+	php_info_print_table_row(2, "Version", XCACHE_VERSION);
+	php_info_print_table_row(2, "Modules Built", XCACHE_MODULES);
+	php_info_print_table_row(2, "Readonly Protection", xc_readonly_protection ? "enabled" : "N/A");
+#ifdef ZEND_ENGINE_2_1
+	ptr = php_format_date("Y-m-d H:i:s", sizeof("Y-m-d H:i:s") - 1, xc_init_time, 1 TSRMLS_CC);
+	php_info_print_table_row(2, "Cache Init Time", ptr);
+	efree(ptr);
+#else
+	snprintf(buf, sizeof(buf), "%lu", (long unsigned) xc_init_time);
+	php_info_print_table_row(2, "Cache Init Time", buf);
+#endif
+
+#ifdef ZTS
+	snprintf(buf, sizeof(buf), "%lu.%lu", xc_init_instance_id, xc_init_instance_subid);
+#else
+	snprintf(buf, sizeof(buf), "%lu", xc_init_instance_id);
+#endif
+	php_info_print_table_row(2, "Cache Instance Id", buf);
+
+	if (xc_php_size) {
+		ptr = _php_math_number_format(xc_php_size, 0, '.', ',');
+		snprintf(buf, sizeof(buf), "enabled, %s bytes, %d split(s), with %d slots each", ptr, xc_php_hcache.size, xc_php_hentry.size);
+		php_info_print_table_row(2, "Opcode Cache", buf);
+		efree(ptr);
+	}
+	else {
+		php_info_print_table_row(2, "Opcode Cache", "disabled");
+	}
+	if (xc_var_size) {
+		ptr = _php_math_number_format(xc_var_size, 0, '.', ',');
+		snprintf(buf, sizeof(buf), "enabled, %s bytes, %d split(s), with %d slots each", ptr, xc_var_hcache.size, xc_var_hentry.size);
+		php_info_print_table_row(2, "Variable Cache", buf);
+		efree(ptr);
+	}
+	else {
+		php_info_print_table_row(2, "Variable Cache", "disabled");
+	}
+
+	left = sizeof(buf);
+	ptr = buf;
+	buf[0] = '\0';
+	for (scheme = xc_shm_scheme_first(); scheme; scheme = xc_shm_scheme_next(scheme)) {
+		len = snprintf(ptr, left, ptr == buf ? "%s" : ", %s", xc_shm_scheme_name(scheme));
+		left -= len;
+		ptr += len;
+	}
+	php_info_print_table_row(2, "Shared Memory Schemes", buf);
+
+#ifdef HAVE_XCACHE_COVERAGER
+	if (cfg_get_string("xcache.coveragedump_directory", &covdumpdir) != SUCCESS || !covdumpdir[0]) {
+		covdumpdir = NULL;
+	}
+	php_info_print_table_row(2, "Coverage Auto Dumper", XG(coverager) && covdumpdir ? "enabled" : "disabled");
+#endif
+	php_info_print_table_end();
+
+	DISPLAY_INI_ENTRIES();
+}
+/* }}} */
+/* {{{ extension startup */
+static void xc_zend_extension_register(zend_extension *new_extension, DL_HANDLE handle)
+{
+	zend_extension extension;
+
+	extension = *new_extension;
+	extension.handle = handle;
+
+	zend_extension_dispatch_message(ZEND_EXTMSG_NEW_EXTENSION, &extension);
+
+	zend_llist_prepend_element(&zend_extensions, &extension);
+	TRACE("%s", "registered");
+}
+
+static zend_llist_element *xc_llist_get_element_by_zend_extension(zend_llist *l, const char *extension_name)
+{
+	zend_llist_element *element;
+
+	for (element = zend_extensions.head; element; element = element->next) {
+		zend_extension *extension = (zend_extension *) element->data;
+
+		if (!strcmp(extension->name, extension_name)) {
+			return element;
+		}
+	}
+	return NULL;
+}
+
+static void xc_llist_prepend(zend_llist *l, zend_llist_element *element)
+{
+	element->next = l->head;
+	element->prev = NULL;
+	if (l->head) {
+		l->head->prev = element;
+	}
+	else {
+		l->tail = element;
+	}
+	l->head = element;
+	++l->count;
+}
+
+static void xc_llist_unlink(zend_llist *l, zend_llist_element *element)
+{
+	if ((element)->prev) {
+		(element)->prev->next = (element)->next;
+	}
+	else {
+		(l)->head = (element)->next;
+	}
+
+	if ((element)->next) {
+		(element)->next->prev = (element)->prev;
+	}
+	else {
+		(l)->tail = (element)->prev;
+	}
+
+	--l->count;
+}
+
+static int xc_zend_extension_startup(zend_extension *extension)
+{
+	if (extension->startup) {
+		if (extension->startup(extension) != SUCCESS) {
+			return FAILURE;
+		}
+	}
+	return SUCCESS;
+}
+/* }}} */
+static int xc_ptr_compare_func(void *p1, void *p2) /* {{{ */
+{
+	return p1 == p2;
+}
+/* }}} */
+static int xc_zend_remove_extension(zend_extension *extension) /* {{{ */
+{
+	llist_dtor_func_t dtor;
+
+	assert(extension);
+	dtor = zend_extensions.dtor; /* avoid dtor */
+	zend_extensions.dtor = NULL;
+	zend_llist_del_element(&zend_extensions, extension, xc_ptr_compare_func);
+	zend_extensions.dtor = dtor;
+	return SUCCESS;
+}
+/* }}} */
+static int xc_config_hash(xc_hash_t *p, char *name, char *default_value) /* {{{ */
+{
+	int bits, size;
+	char *value;
+
+	if (cfg_get_string(name, &value) != SUCCESS) {
+		value = default_value;
+	}
+
+	p->size = zend_atoi(value, strlen(value));
+	for (size = 1, bits = 1; size < p->size; bits ++, size <<= 1) {
+		/* empty body */
+	}
+	p->size = size;
+	p->bits = bits;
+	p->mask = size - 1;
+
+	return SUCCESS;
+}
+/* }}} */
+static int xc_config_long(zend_ulong *p, char *name, char *default_value) /* {{{ */
+{
+	char *value;
+
+	if (cfg_get_string(name, &value) != SUCCESS) {
+		value = default_value;
+	}
+
+	*p = zend_atoi(value, strlen(value));
+	return SUCCESS;
+}
+/* }}} */
+/* {{{ PHP_MINIT_FUNCTION(xcache) */
+static PHP_MINIT_FUNCTION(xcache)
+{
+	char *env;
+	zend_extension *ext;
+	zend_llist_position lpos;
+
+	xc_module_gotup = 1;
+	if (!xc_zend_extension_gotup) {
+		xc_zend_extension_register(&zend_extension_entry, 0);
+		xc_zend_extension_startup(&zend_extension_entry);
+		xc_zend_extension_faked = 1;
+	}
+
+	ext = zend_get_extension("Zend Optimizer");
+	if (ext) {
+		/* zend_optimizer.optimization_level>0 is not compatible with other cacher, disabling */
+		ext->op_array_handler = NULL;
+	}
+	/* cache if there's an op_array_ctor */
+	for (ext = zend_llist_get_first_ex(&zend_extensions, &lpos);
+			ext;
+			ext = zend_llist_get_next_ex(&zend_extensions, &lpos)) {
+		if (ext->op_array_ctor) {
+			xc_have_op_array_ctor = 1;
+			break;
+		}
+	}
+
+
+#ifndef PHP_GINIT
+	ZEND_INIT_MODULE_GLOBALS(xcache, xc_init_globals, xc_shutdown_globals);
+#endif
+	REGISTER_INI_ENTRIES();
+
+	xc_config_long(&xc_php_size,       "xcache.size",        "0");
+	xc_config_hash(&xc_php_hcache,     "xcache.count",       "1");
+	xc_config_hash(&xc_php_hentry,     "xcache.slots",      "8K");
+
+	xc_config_long(&xc_var_size,       "xcache.var_size",    "0");
+	xc_config_hash(&xc_var_hcache,     "xcache.var_count",   "1");
+	xc_config_hash(&xc_var_hentry,     "xcache.var_slots",  "8K");
+
+	if (strcmp(sapi_module.name, "cli") == 0) {
+		if ((env = getenv("XCACHE_TEST")) != NULL) {
+			zend_alter_ini_entry("xcache.test", sizeof("xcache.test"), env, strlen(env) + 1, PHP_INI_SYSTEM, PHP_INI_STAGE_STARTUP);
+		}
+		if (!xc_test) {
+			/* disable cache for cli except for testing */
+			xc_php_size = xc_var_size = 0;
+		}
+	}
+
+	if (xc_php_size <= 0) {
+		xc_php_size = xc_php_hcache.size = 0;
+	}
+	if (xc_var_size <= 0) {
+		xc_var_size = xc_var_hcache.size = 0;
+	}
+
+	if (xc_coredump_dir && xc_coredump_dir[0]) {
+		xcache_init_signal_handler();
+	}
+
+	xc_init_constant(module_number TSRMLS_CC);
+	xc_shm_init_modules();
+
+	if ((xc_php_size || xc_var_size) && xc_mmap_path && xc_mmap_path[0]) {
+		if (xc_init(module_number TSRMLS_CC) != SUCCESS) {
+			zend_error(E_ERROR, "XCache: Cannot init");
+			goto err_init;
+		}
+		xc_initized = 1;
+		xc_init_time = time(NULL);
+#ifdef PHP_WIN32
+		xc_init_instance_id = GetCurrentProcessId();
+#else
+		xc_init_instance_id = getpid();
+#endif
+#ifdef ZTS
+		xc_init_instance_subid = tsrm_thread_id();
+#endif
+	}
+
+#ifdef HAVE_XCACHE_COVERAGER
+	xc_coverager_init(module_number TSRMLS_CC);
+#endif
+
+	return SUCCESS;
+
+err_init:
+	return FAILURE;
+}
+/* }}} */
+/* {{{ PHP_MSHUTDOWN_FUNCTION(xcache) */
+static PHP_MSHUTDOWN_FUNCTION(xcache)
+{
+	if (xc_initized) {
+		xc_destroy();
+	}
+	if (xc_mmap_path) {
+		pefree(xc_mmap_path, 1);
+		xc_mmap_path = NULL;
+	}
+	if (xc_shm_scheme) {
+		pefree(xc_shm_scheme, 1);
+		xc_shm_scheme = NULL;
+	}
+
+#ifdef HAVE_XCACHE_COVERAGER
+	xc_coverager_destroy();
+#endif
+
+	if (xc_coredump_dir && xc_coredump_dir[0]) {
+		xcache_restore_signal_handler();
+	}
+	if (xc_coredump_dir) {
+		pefree(xc_coredump_dir, 1);
+		xc_coredump_dir = NULL;
+	}
+#ifndef PHP_GINIT
+#	ifdef ZTS
+	ts_free_id(xcache_globals_id);
+#	else
+	xc_shutdown_globals(&xcache_globals TSRMLS_CC);
+#	endif
+#endif
+
+	if (xc_zend_extension_faked) {
+		zend_extension *ext = zend_get_extension(XCACHE_NAME);
+		if (ext->shutdown) {
+			ext->shutdown(ext);
+		}
+		xc_zend_remove_extension(ext);
+	}
+	UNREGISTER_INI_ENTRIES();
+
+	xc_module_gotup = 0;
+	xc_zend_extension_gotup = 0;
+	xc_zend_extension_faked = 0;
+
+	return SUCCESS;
+}
+/* }}} */
+/* {{{ PHP_RINIT_FUNCTION(xcache) */
+static PHP_RINIT_FUNCTION(xcache)
+{
+	xc_request_init(TSRMLS_C);
+	return SUCCESS;
+}
+/* }}} */
+/* {{{ PHP_RSHUTDOWN_FUNCTION(xcache) */
+#ifndef ZEND_ENGINE_2
+static PHP_RSHUTDOWN_FUNCTION(xcache)
+#else
+static ZEND_MODULE_POST_ZEND_DEACTIVATE_D(xcache)
+#endif
+{
+#ifdef ZEND_ENGINE_2
+	TSRMLS_FETCH();
+#endif
+
+	xc_request_shutdown(TSRMLS_C);
+	return SUCCESS;
+}
+/* }}} */
+/* {{{ module dependencies */
+#if ZEND_MODULE_API_NO >= 20050922
+static const zend_module_dep xcache_module_deps[] = {
+	ZEND_MOD_REQUIRED("standard")
+	ZEND_MOD_CONFLICTS("apc")
+	ZEND_MOD_CONFLICTS("eAccelerator")
+	ZEND_MOD_CONFLICTS("Turck MMCache")
+	{NULL, NULL, NULL}
+};
+#endif
+/* }}} */ 
+/* {{{ module definition structure */
+
+zend_module_entry xcache_module_entry = {
+#if ZEND_MODULE_API_NO >= 20050922
+	STANDARD_MODULE_HEADER_EX,
+	NULL,
+	xcache_module_deps,
+#else
+	STANDARD_MODULE_HEADER,
+#endif
+	XCACHE_NAME,
+	xcache_functions,
+	PHP_MINIT(xcache),
+	PHP_MSHUTDOWN(xcache),
+	PHP_RINIT(xcache),
+#ifndef ZEND_ENGINE_2
+	PHP_RSHUTDOWN(xcache),
+#else
+	NULL,
+#endif
+	PHP_MINFO(xcache),
+	XCACHE_VERSION,
+#ifdef PHP_GINIT
+	PHP_MODULE_GLOBALS(xcache),
+	PHP_GINIT(xcache),
+	PHP_GSHUTDOWN(xcache),
+#endif
+#ifdef ZEND_ENGINE_2
+	ZEND_MODULE_POST_ZEND_DEACTIVATE_N(xcache),
+#else
+	NULL,
+	NULL,
+#endif
+	STANDARD_MODULE_PROPERTIES_EX
+};
+
+#ifdef COMPILE_DL_XCACHE
+ZEND_GET_MODULE(xcache)
+#endif
+/* }}} */
+static startup_func_t xc_last_ext_startup;
+static int xc_zend_startup_last(zend_extension *extension) /* {{{ */
+{
+	/* restore */
+	extension->startup = xc_last_ext_startup;
+	if (extension->startup) {
+		if (extension->startup(extension) != SUCCESS) {
+			return FAILURE;
+		}
+	}
+	assert(xc_llist_zend_extension);
+	xc_llist_prepend(&zend_extensions, xc_llist_zend_extension);
+	if (!xc_module_gotup) {
+		return zend_startup_module(&xcache_module_entry);
+	}
+	return SUCCESS;
+}
+/* }}} */
+ZEND_DLEXPORT int xcache_zend_startup(zend_extension *extension) /* {{{ */
+{
+	xc_zend_extension_gotup = 1;
+
+	if (!origin_compile_file) {
+		origin_compile_file = zend_compile_file;
+		zend_compile_file = xc_check_initial_compile_file;
+	}
+
+	if (zend_llist_count(&zend_extensions) > 1) {
+		zend_llist_position lpos;
+		zend_extension *ext;
+
+		xc_llist_zend_extension = xc_llist_get_element_by_zend_extension(&zend_extensions, XCACHE_NAME);
+		xc_llist_unlink(&zend_extensions, xc_llist_zend_extension);
+
+		ext = (zend_extension *) zend_llist_get_last_ex(&zend_extensions, &lpos);
+		assert(ext && ext != (zend_extension *) xc_llist_zend_extension->data);
+		xc_last_ext_startup = ext->startup;
+		ext->startup = xc_zend_startup_last;
+	}
+	else if (!xc_module_gotup) {
+		return zend_startup_module(&xcache_module_entry);
+	}
+	return SUCCESS;
+}
+/* }}} */
+ZEND_DLEXPORT void xcache_zend_shutdown(zend_extension *extension) /* {{{ */
+{
+	/* empty */
+}
+/* }}} */
+ZEND_DLEXPORT void xcache_statement_handler(zend_op_array *op_array) /* {{{ */
+{
+#ifdef HAVE_XCACHE_COVERAGER
+	xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_STMT);
+#endif
+}
+/* }}} */
+ZEND_DLEXPORT void xcache_fcall_begin_handler(zend_op_array *op_array) /* {{{ */
+{
+#if 0
+	xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_FCALL_BEGIN);
+#endif
+}
+/* }}} */
+ZEND_DLEXPORT void xcache_fcall_end_handler(zend_op_array *op_array) /* {{{ */
+{
+#if 0
+	xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_FCALL_END);
+#endif
+}
+/* }}} */
+/* {{{ zend extension definition structure */
+ZEND_DLEXPORT zend_extension zend_extension_entry = {
+	XCACHE_NAME,
+	XCACHE_VERSION,
+	XCACHE_AUTHOR,
+	XCACHE_URL,
+	XCACHE_COPYRIGHT,
+	xcache_zend_startup,
+	xcache_zend_shutdown,
+	NULL,           /* activate_func_t */
+	NULL,           /* deactivate_func_t */
+	NULL,           /* message_handler_func_t */
+	NULL,           /* op_array_handler_func_t */
+	xcache_statement_handler,
+	xcache_fcall_begin_handler,
+	xcache_fcall_end_handler,
+	NULL,           /* op_array_ctor_func_t */
+	NULL,           /* op_array_dtor_func_t */
+	STANDARD_ZEND_EXTENSION_PROPERTIES
+};
+
+#ifndef ZEND_EXT_API
+#	define ZEND_EXT_API ZEND_DLEXPORT
+#endif
+#if COMPILE_DL_XCACHE
+ZEND_EXTENSION();
+#endif
+/* }}} */
Index: /tags/1.3.0-rc1/Decompiler.class.php
===================================================================
--- /tags/1.3.0-rc1/Decompiler.class.php	(revision 623)
+++ /tags/1.3.0-rc1/Decompiler.class.php	(revision 623)
@@ -0,0 +1,1888 @@
+<?php
+
+define('INDENT', "\t");
+ini_set('error_reporting', E_ALL);
+
+function color($str, $color = 33)
+{
+	return "\x1B[{$color}m$str\x1B[0m";
+}
+
+function str($src, $indent = '') // {{{
+{
+	if (is_array($indent)) {
+		$indent = $indent['indent'];
+	}
+
+	/*
+	$e = xcache_get_special_value($src);
+	if (isset($e)) {
+		if (is_array($e)) {
+			$src = $e;
+		}
+		else {
+			return $e;
+		}
+	}
+	*/
+
+	if (is_array($src)) {
+		die_error('array str');
+		$src = new Decompiler_Array($src, false, $indent);
+		return $src->__toString();
+	}
+
+	if (is_object($src)) {
+		if (!method_exists($src, '__toString')) {
+			var_dump($src);
+			die_error('no __toString');
+		}
+		return $src->__toString($indent);
+	}
+
+	return $src;
+}
+// }}}
+function value($value) // {{{
+{
+	$spec = xcache_get_special_value($value);
+	if (isset($spec)) {
+		$value = $spec;
+		if (!is_array($value)) {
+			// constant
+			return $value;
+		}
+	}
+
+	if (is_array($value)) {
+		$value = new Decompiler_Array($value, true);
+	}
+	else {
+		$value = new Decompiler_Value($value, true);
+	}
+	return $value;
+}
+// }}}
+class Decompiler_Object // {{{
+{
+}
+// }}}
+class Decompiler_Value extends Decompiler_Object // {{{
+{
+	var $value;
+
+	function Decompiler_Value($value = null)
+	{
+		$this->value = $value;
+	}
+
+	function __toString()
+	{
+		return var_export($this->value, true);
+	}
+}
+// }}}
+class Decompiler_Code extends Decompiler_Object // {{{
+{
+	var $src;
+
+	function Decompiler_Code($src)
+	{
+		$this->src = $src;
+	}
+
+	function __toString()
+	{
+		return $this->src;
+	}
+}
+// }}}
+class Decompiler_Binop extends Decompiler_Code // {{{
+{
+	var $opc;
+	var $op1;
+	var $op2;
+	var $parent;
+
+	function Decompiler_Binop($parent, $op1, $opc, $op2)
+	{
+		$this->parent = &$parent;
+		$this->opc = $opc;
+		$this->op1 = $op1;
+		$this->op2 = $op2;
+	}
+
+	function __toString()
+	{
+		$op1 = str($this->op1);
+		if (is_a($this->op1, 'Decompiler_Binop') && $this->op1->opc != $this->opc) {
+			$op1 = "($op1)";
+		}
+		$opstr = $this->parent->binops[$this->opc];
+		if ($op1 == '0' && $this->opc == XC_SUB) {
+			return $opstr . str($this->op2);
+		}
+		return $op1 . ' ' . $opstr . ' ' . str($this->op2);
+	}
+}
+// }}}
+class Decompiler_Fetch extends Decompiler_Code // {{{
+{
+	var $src;
+	var $fetchType;
+
+	function Decompiler_Fetch($src, $type, $globalsrc)
+	{
+		$this->src = $src;
+		$this->fetchType = $type;
+		$this->globalsrc = $globalsrc;
+	}
+
+	function __toString()
+	{
+		switch ($this->fetchType) {
+		case ZEND_FETCH_LOCAL:
+			return '$' . substr($this->src, 1, -1);
+		case ZEND_FETCH_STATIC:
+			die('static fetch cant to string');
+		case ZEND_FETCH_GLOBAL:
+		case ZEND_FETCH_GLOBAL_LOCK:
+			return $this->globalsrc;
+		default:
+			var_dump($this->fetchType);
+			assert(0);
+		}
+	}
+}
+// }}}
+class Decompiler_Box // {{{
+{
+	var $obj;
+
+	function Decompiler_Box(&$obj)
+	{
+		$this->obj = &$obj;
+	}
+
+	function __toString()
+	{
+		return $this->obj->__toString();
+	}
+}
+// }}}
+class Decompiler_Dim extends Decompiler_Value // {{{
+{
+	var $offsets = array();
+	var $isLast = false;
+	var $assign = null;
+
+	function __toString()
+	{
+		if (is_a($this->value, 'Decompiler_ListBox')) {
+			$exp = str($this->value->obj->src);
+		}
+		else {
+			$exp = str($this->value);
+		}
+		foreach ($this->offsets as $dim) {
+			$exp .= '[' . str($dim) . ']';
+		}
+		return $exp;
+	}
+}
+// }}}
+class Decompiler_DimBox extends Decompiler_Box // {{{
+{
+}
+// }}}
+class Decompiler_List extends Decompiler_Code // {{{
+{
+	var $src;
+	var $dims = array();
+	var $everLocked = false;
+
+	function __toString()
+	{
+		if (count($this->dims) == 1 && !$this->everLocked) {
+			$dim = $this->dims[0];
+			unset($dim->value);
+			$dim->value = $this->src;
+			if (!isset($dim->assign)) {
+				return str($dim);
+			}
+			return str($this->dims[0]->assign) . ' = ' . str($dim);
+		}
+		/* flatten dims */
+		$assigns = array();
+		foreach ($this->dims as $dim) {
+			$assign = &$assigns;
+			foreach ($dim->offsets as $offset) {
+				$assign = &$assign[$offset];
+			}
+			$assign = str($dim->assign);
+		}
+		return $this->toList($assigns) . ' = ' . str($this->src);
+	}
+
+	function toList($assigns)
+	{
+		$keys = array_keys($assigns);
+		if (count($keys) < 2) {
+			$keys[] = 0;
+		}
+		$max = call_user_func_array('max', $keys);
+		$list = 'list(';
+		for ($i = 0; $i <= $max; $i ++) {
+			if ($i) {
+				$list .= ', ';
+			}
+			if (!isset($assigns[$i])) {
+				continue;
+			}
+			if (is_array($assigns[$i])) {
+				$list .= $this->toList($assigns[$i]);
+			}
+			else {
+				$list .= $assigns[$i];
+			}
+		}
+		return $list . ')';
+	}
+}
+// }}}
+class Decompiler_ListBox extends Decompiler_Box // {{{
+{
+}
+// }}}
+class Decompiler_Array extends Decompiler_Value // {{{
+{
+	var $needExport = false;
+	var $indent = '';
+
+	function Decompiler_Array($value = array(), $needexport = false, $indent = '')
+	{
+		$this->value = $value;
+		$this->needExport = $needexport;
+		$this->indent = $indent;
+	}
+
+	function __toString()
+	{
+		$exp = "array(";
+		$indent = $this->indent . INDENT;
+		$assoclen = 0;
+		$multiline = 0;
+		$i = 0;
+		foreach ($this->value as $k => $v) {
+			if ($i !== $k) {
+				$len = strlen($k);
+				if ($assoclen < $len) {
+					$assoclen = $len;
+				}
+			}
+			if (is_array($v)) {
+				$multiline ++;
+			}
+			++ $i;
+		}
+		if ($assoclen && $this->needExport) {
+			$assoclen += 2;
+		}
+
+		$i = 0;
+		$subindent = $indent . INDENT;
+		foreach ($this->value as $k => $v) {
+			if ($multiline) {
+				if ($i) {
+					$exp .= ",";
+				}
+				$exp .= "\n";
+				$exp .= $indent;
+			}
+			else {
+				if ($i) {
+					$exp .= ", ";
+				}
+			}
+
+			if ($this->needExport) {
+				$k = var_export($k, true);
+			}
+			if ($multiline) {
+				$exp .= sprintf("%{$assoclen}s => ", $k);
+			}
+			else if ($assoclen) {
+				$exp .= $k . ' => ';
+			}
+
+			if (is_array($v)) {
+				$v = new Decompiler_Array($v, $this->needExport);
+			}
+			$exp .= str($v, $subindent);
+
+			$i ++;
+		}
+		if ($multiline) {
+			$exp .= "$indent);";
+		}
+		else {
+			$exp .= ")";
+		}
+		return $exp;
+	}
+}
+// }}}
+class Decompiler_ForeachBox extends Decompiler_Box // {{{
+{
+	var $iskey;
+
+	function __toString()
+	{
+		return 'foreach (' . '';
+	}
+}
+// }}}
+
+class Decompiler
+{
+	var $rName = '!^[\\w_][\\w\\d_]*$!';
+	var $rQuotedName = "!^'[\\w_][\\w\\d_]*'\$!";
+
+	function Decompiler()
+	{
+		// {{{ opinfo
+		$this->unaryops = array(
+				XC_BW_NOT   => '~',
+				XC_BOOL_NOT => '!',
+				);
+		$this->binops = array(
+				XC_ADD                 => "+",
+				XC_ASSIGN_ADD          => "+=",
+				XC_SUB                 => "-",
+				XC_ASSIGN_SUB          => "-=",
+				XC_MUL                 => "*",
+				XC_ASSIGN_MUL          => "*=",
+				XC_DIV                 => "/",
+				XC_ASSIGN_DIV          => "/=",
+				XC_MOD                 => "%",
+				XC_ASSIGN_MOD          => "%=",
+				XC_SL                  => "<<",
+				XC_ASSIGN_SL           => "<<=",
+				XC_SR                  => ">>",
+				XC_ASSIGN_SR           => ">>=",
+				XC_CONCAT              => ".",
+				XC_ASSIGN_CONCAT       => ".=",
+				XC_IS_IDENTICAL        => "===",
+				XC_IS_NOT_IDENTICAL    => "!==",
+				XC_IS_EQUAL            => "==",
+				XC_IS_NOT_EQUAL        => "!=",
+				XC_IS_SMALLER          => "<",
+				XC_IS_SMALLER_OR_EQUAL => "<=",
+				XC_BW_OR               => "|",
+				XC_ASSIGN_BW_OR        => "|=",
+				XC_BW_AND              => "&",
+				XC_ASSIGN_BW_AND       => "&=",
+				XC_BW_XOR              => "^",
+				XC_ASSIGN_BW_XOR       => "^=",
+				XC_BOOL_XOR            => "xor",
+				);
+		// }}}
+		$this->includeTypes = array( // {{{
+				ZEND_EVAL         => 'eval',
+				ZEND_INCLUDE      => 'include',
+				ZEND_INCLUDE_ONCE => 'include_once',
+				ZEND_REQUIRE      => 'require',
+				ZEND_REQUIRE_ONCE => 'require_once',
+				);
+				// }}}
+	}
+	function outputPhp(&$opcodes, $opline, $last, $indent) // {{{
+	{
+		$origindent = $indent;
+		$curticks = 0;
+		for ($i = $opline; $i <= $last; $i ++) {
+			$op = $opcodes[$i];
+			if (isset($op['php'])) {
+				$toticks = isset($op['ticks']) ? $op['ticks'] : 0;
+				if ($curticks != $toticks) {
+					if (!$toticks) {
+						echo $origindent, "}\n";
+						$indent = $origindent;
+					}
+					else {
+						if ($curticks) {
+							echo $origindent, "}\n";
+						}
+						else if (!$curticks) {
+							$indent .= INDENT;
+						}
+						echo $origindent, "declare(ticks=$curticks) {\n";
+					}
+					$curticks = $toticks;
+				}
+				echo $indent, str($op['php']), ";\n";
+			}
+		}
+		if ($curticks) {
+			echo $origindent, "}\n";
+		}
+	}
+	// }}}
+	function getOpVal($op, &$EX, $tostr = true, $free = false) // {{{
+	{
+		switch ($op['op_type']) {
+		case XC_IS_CONST:
+			return str(value($op['u.constant']));
+
+		case XC_IS_VAR:
+		case XC_IS_TMP_VAR:
+			$T = &$EX['Ts'];
+			$ret = $T[$op['u.var']];
+			if ($tostr) {
+				$ret = str($ret, $EX);
+			}
+			if ($free) {
+				unset($T[$op['u.var']]);
+			}
+			return $ret;
+
+		case XC_IS_CV:
+			$var = $op['u.var'];
+			$var = $EX['op_array']['vars'][$var];
+			return '$' . $var['name'];
+
+		case XC_IS_UNUSED:
+			return null;
+		}
+	}
+	// }}}
+	function &dop_array($op_array, $indent = '') // {{{
+	{
+		$opcodes = &$op_array['opcodes'];
+		$last = count($opcodes) - 1;
+		if ($opcodes[$last]['opcode'] == XC_HANDLE_EXCEPTION) {
+			unset($opcodes[$last]);
+		}
+		$EX['indent'] = '';
+		//for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
+		//	$opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i);
+		//}
+		// {{{ build jmp array
+		for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
+			$op = &$opcodes[$i];
+			/*
+			if ($op['opcode'] == XC_JMPZ) {
+				$this->dumpop($op, $EX);
+				var_dump($op);
+			}
+			continue;
+			*/
+			$op['line'] = $i;
+			switch ($op['opcode']) {
+			case XC_JMP:
+				$target = $op['op1']['u.var'];
+				$op['jmpouts'] = array($target);
+				$opcodes[$target]['jmpins'][] = $i;
+				break;
+
+			case XC_JMPZNZ:
+				$jmpz = $op['op2']['u.opline_num'];
+				$jmpnz = $op['extended_value'];
+				$op['jmpouts'] = array($jmpz, $jmpnz);
+				$opcodes[$jmpz]['jmpins'][] = $i;
+				$opcodes[$jmpnz]['jmpins'][] = $i;
+				break;
+
+			case XC_JMPZ:
+			case XC_JMPNZ:
+			case XC_JMPZ_EX:
+			case XC_JMPNZ_EX:
+			// case XC_FE_RESET:
+			case XC_FE_FETCH:
+			// case XC_JMP_NO_CTOR:
+				$target = $op['op2']['u.opline_num'];
+				//if (!isset($target)) {
+				//	$this->dumpop($op, $EX);
+				//	var_dump($op); exit;
+				//}
+				$op['jmpouts'] = array($target);
+				$opcodes[$target]['jmpins'][] = $i;
+				break;
+
+			/*
+			case XC_RETURN:
+				$op['jmpouts'] = array();
+				break;
+			*/
+			}
+		}
+		unset($op);
+		// }}}
+		// build semi-basic blocks
+		$nextbbs = array();
+		$starti = 0;
+		for ($i = 1, $cnt = count($opcodes); $i < $cnt; $i ++) {
+			if (isset($opcodes[$i]['jmpins'])
+			 || isset($opcodes[$i - 1]['jmpouts'])) {
+				$nextbbs[$starti] = $i;
+				$starti = $i;
+			}
+		}
+		$nextbbs[$starti] = $cnt;
+
+		$EX = array();
+		$EX['Ts'] = array();
+		$EX['indent'] = $indent;
+		$EX['nextbbs'] = $nextbbs;
+		$EX['op_array'] = &$op_array;
+		$EX['opcodes'] = &$opcodes;
+		// func call
+		$EX['object'] = null;
+		$EX['fbc'] = null;
+		$EX['argstack'] = array();
+		$EX['arg_types_stack'] = array();
+		$EX['last'] = count($opcodes) - 1;
+		$EX['silence'] = 0;
+
+		for ($next = 0, $last = $EX['last'];
+				$loop = $this->outputCode($EX, $next, $last, $indent, true);
+				list($next, $last) = $loop) {
+			// empty
+		}
+		return $EX;
+	}
+	// }}}
+	function outputCode(&$EX, $opline, $last, $indent, $loop = false) // {{{
+	{
+		$op = &$EX['opcodes'][$opline];
+		$next = $EX['nextbbs'][$opline];
+
+		$end = $next - 1;
+		if ($end > $last) {
+			$end = $last;
+		}
+
+		if (isset($op['jmpins'])) {
+			echo "\nline", $op['line'], ":\n";
+		}
+		else {
+			// echo ";;;\n";
+		}
+		$this->dasmBasicBlock($EX, $opline, $end);
+		$this->outputPhp($EX['opcodes'], $opline, $end, $indent);
+		// jmpout op
+		$op = &$EX['opcodes'][$end];
+		$op1 = $op['op1'];
+		$op2 = $op['op2'];
+		$ext = $op['extended_value'];
+		$line = $op['line'];
+
+		if (isset($EX['opcodes'][$next])) {
+			if (isset($last) && $next > $last) {
+				$next = null;
+			}
+		}
+		else {
+			$next = null;
+		}
+		if ($op['opcode'] == XC_FE_FETCH) {
+			$opline = $next;
+			$next = $op['op2']['u.opline_num'];
+			$end = $next - 1;
+
+			ob_start();
+			$this->outputCode($EX, $opline, $end /* - 1 skip last jmp */, $indent . INDENT);
+			$body = ob_get_clean();
+
+			$as = str($op['fe_as']);
+			if (isset($op['fe_key'])) {
+				$as = str($op['fe_key']) . ' => ' . $as;
+			}
+			echo "{$indent}foreach (" . str($op['fe_src']) . " as $as) {\n";
+			echo $body;
+			echo "{$indent}}";
+			// $this->outputCode($EX, $next, $last, $indent);
+			// return;
+		}
+		/*
+		if ($op['opcode'] == XC_JMPZ) {
+			$target = $op2['u.opline_num'];
+			if ($line + 1) {
+				$nextblock = $EX['nextbbs'][$next];
+				$jmpop = end($nextblock);
+				if ($jmpop['opcode'] == XC_JMP) {
+					$ifendline = $op2['u.opline_num'];
+					if ($ifendline >= $line) {
+						$cond = $op['cond'];
+						echo "{$indent}if ($cond) {\n";
+						$this->outputCode($EX, $next, $last, INDENT . $indent);
+						echo "$indent}\n";
+						$this->outputCode($EX, $target, $last, $indent);
+						return;
+					}
+				}
+			}
+		}
+		*/
+		if (!isset($next)) {
+			return;
+		}
+		if (!empty($op['jmpouts']) && isset($op['isjmp'])) {
+			if (isset($op['cond'])) {
+				echo "{$indent}check ($op[cond]) {\n";
+				echo INDENT;
+			}
+			echo $indent;
+			echo xcache_get_opcode($op['opcode']), ' line', $op['jmpouts'][0];
+			if (isset($op['jmpouts'][1])) {
+				echo ', line', $op['jmpouts'][1];
+			}
+			echo ";";
+			// echo ' // <- line', $op['line'];
+			echo "\n";
+			if (isset($op['cond'])) echo "$indent}\n";
+		}
+
+		// proces JMPZ_EX/JMPNZ_EX for AND,OR
+		$op = &$EX['opcodes'][$next];
+		/*
+		if (isset($op['jmpins'])) {
+			foreach (array_reverse($op['jmpins']) as $fromline) {
+				$fromop = $EX['opcodes'][$fromline];
+				switch ($fromop['opcode']) {
+				case XC_JMPZ_EX: $opstr = 'and'; break;
+				case XC_JMPNZ_EX: $opstr = 'or'; break;
+				case XC_JMPZNZ: var_dump($fromop); exit;
+				default: continue 2;
+				}
+
+				$var = $fromop['result']['u.var'];
+				var_dump($EX['Ts'][$var]);
+				$EX['Ts'][$var] = '(' . $fromop['and_or'] . " $opstr " . $EX['Ts'][$var] . ')';
+			}
+			#$this->outputCode($EX, $next, $last, $indent);
+			#return;
+		}
+		*/
+		if (isset($op['cond_false'])) {
+			// $this->dumpop($op, $EX);
+			// any true comes here, so it's a "or"
+			$cond = implode(' and ', $op['cond_false']);
+			// var_dump($op['cond'] = $cond);
+			/*
+			$rvalue = implode(' or ', $op['cond_true']) . ' or ' . $rvalue;
+			unset($op['cond_true']);
+			*/
+		}
+
+		if ($loop) {
+			return array($next, $last);
+		}
+		$this->outputCode($EX, $next, $last, $indent);
+	}
+	// }}}
+	function unquoteName($str) // {{{
+	{
+		if (preg_match($this->rQuotedName, $str)) {
+			$str = substr($str, 1, -1);
+		}
+		return $str;
+	}
+	// }}}
+	function dasmBasicBlock(&$EX, $opline, $last) // {{{
+	{
+		$T = &$EX['Ts'];
+		$opcodes = &$EX['opcodes'];
+		$lastphpop = null;
+
+		for ($i = $opline, $ic = $last + 1; $i < $ic; $i ++) {
+			// {{{ prepair
+			$op = &$opcodes[$i];
+			$opc = $op['opcode'];
+			if ($opc == XC_NOP) {
+				continue;
+			}
+
+			$op1 = $op['op1'];
+			$op2 = $op['op2'];
+			$res = $op['result'];
+			$ext = $op['extended_value'];
+
+			$opname = xcache_get_opcode($opc);
+
+			if ($opname == 'UNDEF' || !isset($opname)) {
+				echo 'UNDEF OP:';
+				$this->dumpop($op, $EX);
+				continue;
+			}
+			// $this->dumpop($op, $EX); //var_dump($op);
+
+			$resvar = null;
+			if (($res['u.EA.type'] & EXT_TYPE_UNUSED) || $res['op_type'] == XC_IS_UNUSED) {
+				$istmpres = false;
+			}
+			else {
+				$istmpres = true;
+			}
+			// }}}
+			// echo $opname, "\n";
+
+			$call = array(&$this, $opname);
+			if (is_callable($call)) {
+				$this->{$opname}($op, $EX);
+			}
+			else if (isset($this->binops[$opc])) { // {{{
+				$op1val = $this->getOpVal($op1, $EX, false);
+				$op2val = $this->getOpVal($op2, $EX, false);
+				$rvalue = new Decompiler_Binop($this, $op1val, $opc, $op2val);
+				$resvar = $rvalue;
+				// }}}
+			}
+			else if (isset($this->unaryops[$opc])) { // {{{
+				$op1val = $this->getOpVal($op1, $EX);
+				$myop = $this->unaryops[$opc];
+				$rvalue = "$myop$op1val";
+				$resvar = $rvalue;
+				// }}}
+			}
+			else {
+				switch ($opc) {
+				case XC_NEW: // {{{
+					array_push($EX['arg_types_stack'], array($EX['object'], $EX['fbc']));
+					$EX['object'] = (int) $res['u.var'];
+					$EX['fbc'] = 'new ' . $this->unquoteName($this->getOpVal($op1, $EX));
+					if (PHP_VERSION < 5) {
+						$resvar = '$new object$';
+					}
+					break;
+					// }}}
+				case XC_FETCH_CLASS: // {{{
+					if ($op2['op_type'] == XC_IS_UNUSED) {
+						switch ($ext) {
+						case ZEND_FETCH_CLASS_SELF:
+							$class = 'self';
+							break;
+						case ZEND_FETCH_CLASS_PARENT:
+							$class = 'parent';
+						}
+					}
+					else {
+						$class = $op2['u.constant'];
+						if (is_object($class)) {
+							$class = get_class($class);
+						}
+					}
+					$resvar = $class;
+					break;
+					// }}}
+				case XC_FETCH_CONSTANT: // {{{
+					if ($op1['op_type'] == XC_IS_CONST) {
+						$resvar = $op1['u.constant'];
+					}
+					else if ($op1['op_type'] == XC_IS_UNUSED) {
+						$resvar = $op2['u.constant'];
+					}
+					else {
+						$class = $T[$op1['u.var']];
+						assert($class[0] == 'class');
+						$resvar = $class[1] . '::' . $op2['u.constant'];
+					}
+					break;
+					// }}}
+					// {{{ case XC_FETCH_*
+				case XC_FETCH_R:
+				case XC_FETCH_W:
+				case XC_FETCH_RW:
+				case XC_FETCH_FUNC_ARG:
+				case XC_FETCH_UNSET:
+				case XC_FETCH_IS:
+				case XC_UNSET_VAR:
+					$rvalue = $this->getOpVal($op1, $EX);
+					$fetchtype = $op2[PHP_VERSION < 5 ? 'u.fetch_type' : 'u.EA.type'];
+					switch ($fetchtype) {
+					case ZEND_FETCH_STATIC_MEMBER:
+						$class = $this->getOpVal($op2, $EX);
+						$rvalue = $class . '::$' . $this->unquoteName($rvalue);
+						break;
+					default:
+						$name = $this->unquoteName($rvalue);
+						$globalname = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[$rvalue]";
+						$rvalue = new Decompiler_Fetch($rvalue, $fetchtype, $globalname);
+						break;
+					}
+					if ($opc == XC_UNSET_VAR) {
+						$op['php'] = "unset(" . str($rvalue) . ")";
+						$lastphpop = &$op;
+					}
+					else if ($res['op_type'] != XC_IS_UNUSED) {
+						$resvar = $rvalue;
+					}
+					break;
+					// }}}
+					// {{{ case XC_FETCH_DIM_*
+				case XC_FETCH_DIM_TMP_VAR:
+				case XC_FETCH_DIM_R:
+				case XC_FETCH_DIM_W:
+				case XC_FETCH_DIM_RW:
+				case XC_FETCH_DIM_FUNC_ARG:
+				case XC_FETCH_DIM_UNSET:
+				case XC_FETCH_DIM_IS:
+				case XC_ASSIGN_DIM:
+				case XC_UNSET_DIM:
+				case XC_UNSET_DIM_OBJ:
+					$src = $this->getOpVal($op1, $EX, false);
+					if (is_a($src, "Decompiler_ForeachBox")) {
+						$src->iskey = $this->getOpVal($op2, $EX);
+						$resvar = $src;
+						break;
+					}
+					else if (is_a($src, "Decompiler_DimBox")) {
+						$dimbox = $src;
+					}
+					else {
+						if (!is_a($src, "Decompiler_ListBox")) {
+							$list = new Decompiler_List($this->getOpVal($op1, $EX, false));
+
+							$src = new Decompiler_ListBox($list);
+							if (!isset($op1['u.var'])) {
+								$this->dumpop($op, $EX);
+								var_dump($op);
+								die('missing u.var');
+							}
+							$T[$op1['u.var']] = $src;
+							unset($list);
+						}
+						$dim = new Decompiler_Dim($src);
+						$src->obj->dims[] = &$dim;
+
+						$dimbox = new Decompiler_DimBox($dim);
+					}
+					$dim = &$dimbox->obj;
+					$dim->offsets[] = $this->getOpVal($op2, $EX);
+					if ($ext == ZEND_FETCH_ADD_LOCK) {
+						$src->obj->everLocked = true;
+					}
+					else if ($ext == ZEND_FETCH_STANDARD) {
+						$dim->isLast = true;
+					}
+					unset($dim);
+					$rvalue = $dimbox;
+
+					if ($opc == XC_ASSIGN_DIM) {
+						$lvalue = $rvalue;
+						++ $i;
+						$rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX);
+						$resvar = str($lvalue) . ' = ' . $rvalue;
+					}
+					else if ($opc == XC_UNSET_DIM) {
+						$op['php'] = "unset(" . str($rvalue) . ")";
+						$lastphpop = &$op;
+					}
+					else if ($res['op_type'] != XC_IS_UNUSED) {
+						$resvar = $rvalue;
+					}
+					break;
+					// }}}
+				case XC_ASSIGN: // {{{
+					$lvalue = $this->getOpVal($op1, $EX);
+					$rvalue = $this->getOpVal($op2, $EX, false);
+					if (is_a($rvalue, 'Decompiler_ForeachBox')) {
+						$type = $rvalue->iskey ? 'fe_key' : 'fe_as';
+						$rvalue->obj[$type] = $lvalue;
+						unset($T[$op2['u.var']]);
+						break;
+					}
+					if (is_a($rvalue, "Decompiler_DimBox")) {
+						$dim = &$rvalue->obj;
+						$dim->assign = $lvalue;
+						if ($dim->isLast) {
+							$resvar = str($dim->value);
+						}
+						unset($dim);
+						break;
+					}
+					$resvar = "$lvalue = " . str($rvalue, $EX);
+					break;
+					// }}}
+				case XC_ASSIGN_REF: // {{{
+					$lvalue = $this->getOpVal($op1, $EX);
+					$rvalue = $this->getOpVal($op2, $EX, false);
+					if (is_a($rvalue, 'Decompiler_Fetch')) {
+						$src = str($rvalue->src);
+						if (substr($src, 1, -1) == substr($lvalue, 1)) {
+							switch ($rvalue->fetchType) {
+							case ZEND_FETCH_GLOBAL:
+								$resvar = 'global ' . $lvalue;
+								break 2;
+							case ZEND_FETCH_STATIC:
+								$statics = &$EX['op_array']['static_variables'];
+								$resvar = 'static ' . $lvalue;
+								$name = substr($src, 1, -1);
+								if (isset($statics[$name])) {
+									$var = $statics[$name];
+									$resvar .= ' = ';
+									$resvar .= str(value($var), $EX);
+								}
+								unset($statics);
+								break 2;
+							}
+						}
+					}
+					$rvalue = str($rvalue);
+					$resvar = "$lvalue = &$rvalue";
+					break;
+					// }}}
+				// {{{ case XC_FETCH_OBJ_*
+				case XC_FETCH_OBJ_R:
+				case XC_FETCH_OBJ_W:
+				case XC_FETCH_OBJ_RW:
+				case XC_FETCH_OBJ_FUNC_ARG:
+				case XC_FETCH_OBJ_UNSET:
+				case XC_FETCH_OBJ_IS:
+				case XC_ASSIGN_OBJ:
+					$obj = $this->getOpVal($op1, $EX);
+					if (!isset($obj)) {
+						$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}";
+					}
+					if ($res['op_type'] != XC_IS_UNUSED) {
+						$resvar = $rvalue;
+					}
+					if ($opc == XC_ASSIGN_OBJ) {
+						++ $i;
+						$lvalue = $rvalue;
+						$rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX);
+						$resvar = "$lvalue = $rvalue";
+					}
+					break;
+					// }}}
+				case XC_ISSET_ISEMPTY_DIM_OBJ:
+				case XC_ISSET_ISEMPTY_PROP_OBJ:
+				case XC_ISSET_ISEMPTY:
+				case XC_ISSET_ISEMPTY_VAR: // {{{
+					if ($opc == XC_ISSET_ISEMPTY_VAR) {
+						$rvalue = $this->getOpVal($op1, $EX);;
+						if (preg_match($this->rQuotedName, $rvalue)) {
+							$rvalue = '$' . substr($rvalue, 1, -1);
+						}
+						else {
+							$rvalue = "${" . $rvalue . "}";
+						}
+						if ($op2['u.EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
+							$class = $this->getOpVal($op2, $EX);
+							$rvalue = $class . '::' . $rvalue;
+						}
+					}
+					else if ($opc == XC_ISSET_ISEMPTY) {
+						$rvalue = $this->getOpVal($op1, $EX);
+					}
+					else {
+						$container = $this->getOpVal($op1, $EX);
+						$dim = $this->getOpVal($op2, $EX);
+						$rvalue = $container . "[$dim]";
+					}
+
+					switch (PHP_VERSION < 5 ? $op['op2']['u.var'] /* u.constant */ : $ext) {
+					case ZEND_ISSET:
+						$rvalue = "isset($rvalue)";
+						break;
+					case ZEND_ISEMPTY:
+						$rvalue = "empty($rvalue)";
+						break;
+					default:
+						$this->dumpop($op, $EX);
+						die_error('1');
+					}
+					$resvar = $rvalue;
+					break;
+					// }}}
+				case XC_SEND_VAR_NO_REF:
+				case XC_SEND_VAL:
+				case XC_SEND_REF:
+				case XC_SEND_VAR: // {{{
+					$ref = ($opc == XC_SEND_REF ? '&' : '');
+					$EX['argstack'][] = $ref . $this->getOpVal($op1, $EX);
+					break;
+					// }}}
+				case XC_INIT_METHOD_CALL:
+				case XC_INIT_FCALL_BY_FUNC:
+				case XC_INIT_FCALL_BY_NAME: // {{{
+					if (($ext & ZEND_CTOR_CALL)) {
+						break;
+					}
+					array_push($EX['arg_types_stack'], array($EX['object'], $EX['fbc']));
+					if ($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 ($res['op_type'] != XC_IS_UNUSED) {
+							$resvar = '$obj call$';
+						}
+					}
+					else {
+						$EX['object'] = null;
+					}
+
+					if ($opc == XC_INIT_FCALL_BY_FUNC) {
+						$which = $op1['u.var'];
+						$EX['fbc'] = $EX['op_array']['funcs'][$which]['name'];
+					}
+					else {
+						$EX['fbc'] = $this->getOpVal($op2, $EX, false);
+					}
+					break;
+					// }}}
+				case XC_DO_FCALL_BY_FUNC:
+					$which = $op1['u.var'];
+					$fname = $EX['op_array']['funcs'][$which]['name'];
+					$args = $this->popargs($EX, $ext);
+					$resvar = $fname . "($args)";
+					break;
+				case XC_DO_FCALL:
+					$fname = $this->unquoteName($this->getOpVal($op1, $EX, false));
+					$args = $this->popargs($EX, $ext);
+					$resvar = $fname . "($args)";
+					break;
+				case XC_DO_FCALL_BY_NAME: // {{{
+					$object = null;
+
+					$fname = $this->unquoteName($EX['fbc']);
+					if (!is_int($EX['object'])) {
+						$object = $EX['object'];
+					}
+
+					$args = $this->popargs($EX, $ext);
+
+					$resvar =
+						(isset($object) ? $object . '->' : '' )
+						. $fname . "($args)";
+					unset($args);
+
+					if (is_int($EX['object'])) {
+						$T[$EX['object']] = $resvar;
+						$resvar = null;
+					}
+					list($EX['object'], $EX['fbc']) = array_pop($EX['arg_types_stack']);
+					break;
+					// }}}
+				case XC_VERIFY_ABSTRACT_CLASS: // {{{
+					//unset($T[$op1['u.var']]);
+					break;
+					// }}}
+				case XC_DECLARE_CLASS: 
+				case XC_DECLARE_INHERITED_CLASS: // {{{
+					$key = $op1['u.constant'];
+					$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) {
+						$ext /= XC_SIZEOF_TEMP_VARIABLE;
+						$class['parent'] = $T[$ext];
+						unset($T[$ext]);
+					}
+					else {
+						$class['parent'] = null;
+					}
+
+					while ($i + 2 < $ic
+					 && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE
+					 && $opcodes[$i + 2]['op1']['u.var'] == $res['u.var']
+					 && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) {
+						$fetchop = &$opcodes[$i + 1];
+						$impl = $this->unquoteName($this->getOpVal($fetchop['op2'], $EX));
+						$addop = &$opcodes[$i + 2];
+						$class['interfaces'][$addop['extended_value']] = $impl;
+						unset($fetchop, $addop);
+						$i += 2;
+					}
+					$this->dclass($class);
+					unset($class);
+					break;
+					// }}}
+				case XC_INIT_STRING: // {{{
+					$resvar = "''";
+					break;
+					// }}}
+				case XC_ADD_CHAR:
+				case XC_ADD_STRING:
+				case XC_ADD_VAR: // {{{
+					$op1val = $this->getOpVal($op1, $EX);
+					$op2val = $this->getOpVal($op2, $EX);
+					switch ($opc) {
+					case XC_ADD_CHAR:
+						$op2val = str(chr($op2val), $EX);
+						break;
+					case XC_ADD_STRING:
+						$op2val = str($op2val, $EX);
+						break;
+					case XC_ADD_VAR:
+						break;
+					}
+					if ($op1val == "''") {
+						$rvalue = $op2val;
+					}
+					else if ($op2val == "''") {
+						$rvalue = $op1val;
+					}
+					else {
+						$rvalue = $op1val . ' . ' . $op2val;
+					}
+					$resvar = $rvalue;
+					// }}}
+					break;
+				case XC_PRINT: // {{{
+					$op1val = $this->getOpVal($op1, $EX);
+					$resvar = "print($op1val)";
+					break;
+					// }}}
+				case XC_ECHO: // {{{
+					$op1val = $this->getOpVal($op1, $EX);
+					$resvar = "echo $op1val";
+					break;
+					// }}}
+				case XC_EXIT: // {{{
+					$op1val = $this->getOpVal($op1, $EX);
+					$resvar = "exit($op1val)";
+					break;
+					// }}}
+				case XC_INIT_ARRAY:
+				case XC_ADD_ARRAY_ELEMENT: // {{{
+					$rvalue = $this->getOpVal($op1, $EX, false, true);
+
+					if ($opc == XC_ADD_ARRAY_ELEMENT) {
+						$offset = $this->getOpVal($op2, $EX);
+						if (isset($offset)) {
+							$T[$res['u.var']]->value[$offset] = $rvalue;
+						}
+						else {
+							$T[$res['u.var']]->value[] = $rvalue;
+						}
+					}
+					else {
+						if ($opc == XC_INIT_ARRAY) {
+							$resvar = new Decompiler_Array();
+							if (!isset($rvalue)) {
+								continue;
+							}
+						}
+
+						$offset = $this->getOpVal($op2, $EX);
+						if (isset($offset)) {
+							$resvar->value[$offset] = $rvalue;
+						}
+						else {
+							$resvar->value[] = $rvalue;
+						}
+					}
+					break;
+					// }}}
+				case XC_QM_ASSIGN: // {{{
+					$resvar = $this->getOpVal($op1, $EX);
+					break;
+					// }}}
+				case XC_BOOL: // {{{
+					$resvar = /*'(bool) ' .*/ $this->getOpVal($op1, $EX);
+					break;
+					// }}}
+				case XC_RETURN: // {{{
+					$resvar = "return " . $this->getOpVal($op1, $EX);
+					break;
+					// }}}
+				case XC_INCLUDE_OR_EVAL: // {{{
+					$type = $op2['u.var']; // hack
+					$keyword = $this->includeTypes[$type];
+					$resvar = "$keyword(" . $this->getOpVal($op1, $EX) . ")";
+					break;
+					// }}}
+				case XC_FE_RESET: // {{{
+					$resvar = $this->getOpVal($op1, $EX);
+					break;
+					// }}}
+				case XC_FE_FETCH: // {{{
+					$op['fe_src'] = $this->getOpVal($op1, $EX);
+					$fe = new Decompiler_ForeachBox($op);
+					$fe->iskey = false;
+					$T[$res['u.var']] = $fe;
+
+					++ $i;
+					if (($ext & ZEND_FE_FETCH_WITH_KEY)) {
+						$fe = new Decompiler_ForeachBox($op);
+						$fe->iskey = true;
+
+						$res = $opcodes[$i]['result'];
+						$T[$res['u.var']] = $fe;
+					}
+					break;
+					// }}}
+				case XC_SWITCH_FREE: // {{{
+					// unset($T[$op1['u.var']]);
+					break;
+					// }}}
+				case XC_FREE: // {{{
+					$free = $T[$op1['u.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);
+					break;
+					// }}}
+				case XC_JMP_NO_CTOR:
+					break;
+				case XC_JMPNZ: // while
+				case XC_JMPZNZ: // for
+				case XC_JMPZ_EX: // and
+				case XC_JMPNZ_EX: // or
+				case XC_JMPZ: // {{{
+					if ($opc == XC_JMP_NO_CTOR && $EX['object']) {
+						$rvalue = $EX['object'];
+					}
+					else {
+						$rvalue = $this->getOpVal($op1, $EX);
+					}
+
+					if (isset($op['cond_true'])) {
+						// any true comes here, so it's a "or"
+						$rvalue = implode(' or ', $op['cond_true']) . ' or ' . $rvalue;
+						unset($op['cond_true']);
+					}
+					if (isset($op['cond_false'])) {
+						var_dump($op);// exit;
+					}
+					if ($opc == XC_JMPZ_EX || $opc == XC_JMPNZ_EX || $opc == XC_JMPZ) {
+						$targetop = &$EX['opcodes'][$op2['u.opline_num']];
+						if ($opc == XC_JMPNZ_EX) {
+							$targetop['cond_true'][] = str($rvalue);
+						}
+						else {
+							$targetop['cond_false'][] = str($rvalue);
+						}
+						unset($targetop);
+					}
+					else {
+						$op['cond'] = $rvalue; 
+						$op['isjmp'] = true;
+					}
+					break;
+					// }}}
+				case XC_JMP: // {{{
+					$op['cond'] = null;
+					$op['isjmp'] = true;
+					break;
+					// }}}
+				case XC_CASE:
+				case XC_BRK:
+					break;
+				case XC_RECV_INIT:
+				case XC_RECV:
+					$offset = $this->getOpVal($op1, $EX);
+					$lvalue = $this->getOpVal($op['result'], $EX);
+					if ($opc == XC_RECV_INIT) {
+						$default = value($op['op2']['u.constant']);
+					}
+					else {
+						$default = null;
+					}
+					$EX['recvs'][$offset] = array($lvalue, $default);
+					break;
+				case XC_POST_DEC:
+				case XC_POST_INC:
+				case XC_POST_DEC_OBJ:
+				case XC_POST_INC_OBJ:
+				case XC_PRE_DEC:
+				case XC_PRE_INC:
+				case XC_PRE_DEC_OBJ:
+				case XC_PRE_INC_OBJ: // {{{
+					$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;
+						}
+					}
+					else {
+						$resvar = $this->getOpVal($op1, $EX);
+					}
+					$opstr = isset($flags['DEC']) ? '--' : '++';
+					if (isset($flags['POST'])) {
+						$resvar .= ' ' . $opstr;
+					}
+					else {
+						$resvar = "$opstr $resvar";
+					}
+					break;
+					// }}}
+
+				case XC_BEGIN_SILENCE: // {{{
+					$EX['silence'] ++;
+					break;
+					// }}}
+				case XC_END_SILENCE: // {{{
+					$EX['silence'] --;
+					$lastresvar = '@' . str($lastresvar);
+					break;
+					// }}}
+				case XC_CONT: // {{{
+					break;
+					// }}}
+				case XC_CAST: // {{{
+					$type = $ext;
+					static $type2cast = array(
+							IS_LONG   => '(int)',
+							IS_DOUBLE => '(double)',
+							IS_STRING => '(string)',
+							IS_ARRAY  => '(array)',
+							IS_OBJECT => '(object)',
+							IS_BOOL   => '(bool)',
+							IS_NULL   => '(unset)',
+							);
+					assert(isset($type2cast[$type]));
+					$cast = $type2cast[$type];
+					$resvar = $cast . ' ' . $this->getOpVal($op1, $EX);
+					break;
+					// }}}
+				case XC_EXT_STMT:
+				case XC_EXT_FCALL_BEGIN:
+				case XC_EXT_FCALL_END:
+				case XC_EXT_NOP:
+					break;
+				case XC_DECLARE_FUNCTION_OR_CLASS:
+					/* always removed by compiler */
+					break;
+				case XC_TICKS:
+					$lastphpop['ticks'] = $this->getOpVal($op1, $EX);
+					// $EX['tickschanged'] = true;
+					break;
+				default: // {{{
+					echo "\x1B[31m * TODO ", $opname, "\x1B[0m\n";
+					// }}}
+				}
+			}
+			if (isset($resvar)) {
+				if ($istmpres) {
+					$T[$res['u.var']] = $resvar;
+					$lastresvar = &$T[$res['u.var']];
+				}
+				else {
+					$op['php'] = $resvar;
+					$lastphpop = &$op;
+					$lastresvar = &$op['php'];
+				}
+			}
+		}
+		return $T;
+	}
+	// }}}
+	function unquote($str, $st, $ed) // {{{
+	{
+		$l1 = strlen($st);
+		$l2 = strlen($ed);
+		if (substr($str, 0, $l1) === $st && substr($str, -$l2) === $ed) {
+			$str = substr($str, $l1, -$l2);
+		}
+		return $str;
+	}
+	// }}}
+	function popargs(&$EX, $n) // {{{
+	{
+		$args = array();
+		for ($i = 0; $i < $n; $i ++) {
+			$a = array_pop($EX['argstack']);
+			if (is_array($a)) {
+				array_unshift($args, str($a, $EX));
+			}
+			else {
+				array_unshift($args, $a);
+			}
+		}
+		return implode(', ', $args);
+	}
+	// }}}
+	function dumpop($op, &$EX) // {{{
+	{
+		$op1 = $op['op1'];
+		$op2 = $op['op2'];
+		$d = array('opname' => xcache_get_opcode($op['opcode']), 'opcode' => $op['opcode']);
+
+		foreach (array('op1' => 'op1', 'op2' => 'op2', 'result' => 'res') as $k => $kk) {
+			switch ($op[$k]['op_type']) {
+			case XC_IS_UNUSED:
+				$d[$kk] = '*UNUSED* ' . $op[$k]['u.opline_num'];
+				break;
+
+			case XC_IS_VAR:
+				$d[$kk] = '$' . $op[$k]['u.var'];
+				if ($kk != 'res') {
+					$d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
+				}
+				break;
+
+			case XC_IS_TMP_VAR:
+				$d[$kk] = '#' . $op[$k]['u.var'];
+				if ($kk != 'res') {
+					$d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
+				}
+				break;
+
+			case XC_IS_CV:
+				$d[$kk] = $this->getOpVal($op[$k], $EX);
+				break;
+
+			default:
+				if ($kk == 'res') {
+					assert(0);
+				}
+				else {
+					$d[$kk] = $this->getOpVal($op[$k], $EX);
+				}
+			}
+		}
+		$d['ext'] = $op['extended_value'];
+
+		var_dump($d);
+	}
+	// }}}
+	function dargs(&$EX, $indent) // {{{
+	{
+		$EX['indent'] = $indent;
+		$op_array = &$EX['op_array'];
+
+		if (isset($op_array['num_args'])) {
+			$c = $op_array['num_args'];
+		}
+		else if ($op_array['arg_types']) {
+			$c = count($op_array['arg_types']);
+		}
+		else {
+			// php4
+			$c = count($EX['recvs']);
+		}
+
+		$refrest = false;
+		for ($i = 0; $i < $c; $i ++) {
+			if ($i) {
+				echo ', ';
+			}
+			if (isset($op_array['arg_info'])) {
+				$ai = $op_array['arg_info'][$i];
+				if (!empty($ai['class_name'])) {
+					echo $ai['class_name'], ' ';
+					if ($ai['allow_null']) {
+						echo 'or NULL ';
+					}
+				}
+				else if (!empty($ai['array_type_hint'])) {
+					echo 'array ';
+					if ($ai['allow_null']) {
+						echo 'or NULL ';
+					}
+				}
+				if ($ai['pass_by_reference']) {
+					echo '&';
+				}
+				printf("\$%s", $ai['name']);
+			}
+			else {
+				if ($refrest) {
+					echo '&';
+				}
+				else if (isset($op_array['arg_types'][$i])) {
+					switch ($op_array['arg_types'][$i]) {
+					case BYREF_FORCE_REST:
+						$refrest = true;
+						/* fall */
+					case BYREF_FORCE:
+						echo '&';
+						break;
+
+					case BYREF_NONE:
+					case BYREF_ALLOW:
+						break;
+					default:
+						assert(0);
+					}
+				}
+				$arg = $EX['recvs'][$i + 1];
+				echo str($arg[0]);
+				if (isset($arg[1])) {
+					echo ' = ', str($arg[1]);
+				}
+			}
+		}
+	}
+	// }}}
+	function dfunction($func, $indent = '', $nobody = false) // {{{
+	{
+		if ($nobody) {
+			$body = ";\n";
+			$EX = array();
+			$EX['op_array'] = &$func['op_array'];
+			$EX['recvs'] = array();
+		}
+		else {
+			ob_start();
+			$newindent = INDENT . $indent;
+			$EX = &$this->dop_array($func['op_array'], $newindent);
+			$body = ob_get_clean();
+			if (!isset($EX['recvs'])) {
+				$EX['recvs'] = array();
+			}
+		}
+
+		echo 'function ', $func['op_array']['function_name'], '(';
+		$this->dargs($EX, $indent);
+		echo ")\n";
+		echo $indent, "{\n";
+		echo $body;
+		echo "$indent}\n";
+	}
+	// }}}
+	function dclass($class, $indent = '') // {{{
+	{
+		// {{{ class decl
+		if (!empty($class['doc_comment'])) {
+			echo $indent;
+			echo $class['doc_comment'];
+			echo "\n";
+		}
+		$isinterface = false;
+		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) {
+					echo "abstract ";
+				}
+				if ($class['ce_flags'] & ZEND_ACC_FINAL) {
+					echo "final ";
+				}
+			}
+		}
+		echo 'class ', $class['name'];
+		if ($class['parent']) {
+			echo ' extends ', $class['parent'];
+		}
+		/* TODO */
+		if (!empty($class['interfaces'])) {
+			echo ' implements ';
+			echo implode(', ', $class['interfaces']);
+		}
+		echo "\n";
+		echo $indent, "{";
+		// }}}
+		$newindent = INDENT . $indent;
+		// {{{ const, static
+		foreach (array('constants_table' => 'const '
+					, 'static_members' => 'static $') as $type => $prefix) {
+			if (!empty($class[$type])) {
+				echo "\n";
+				// TODO: skip shadow?
+				foreach ($class[$type] as $name => $v) {
+					echo $newindent;
+					echo $prefix, $name, ' = ';
+					echo str(value($v), $EX);
+					echo ";\n";
+				}
+			}
+		}
+		// }}}
+		// {{{ properties
+		if (!empty($class['default_properties'])) {
+			echo "\n";
+			$infos = empty($class['properties_info']) ? null : $class['properties_info'];
+			foreach ($class['default_properties'] as $name => $v) {
+				$info = (isset($infos) && isset($infos[$name])) ? $infos[$name] : null;
+				if (isset($info)) {
+					if (!empty($info['doc_comment'])) {
+						echo $newindent;
+						echo $info['doc_comment'];
+						echo "\n";
+					}
+				}
+
+				echo $newindent;
+				if (PHP_VERSION < 5) {
+					echo 'var ';
+				}
+				else if (!isset($info)) {
+					echo 'public ';
+				}
+				else {
+					if ($info['flags'] & ZEND_ACC_SHADOW) {
+						continue;
+					}
+					switch ($info['flags'] & ZEND_ACC_PPP_MASK) {
+					case ZEND_ACC_PUBLIC:
+						echo "public ";
+						break;
+					case ZEND_ACC_PRIVATE:
+						echo "private ";
+						break;
+					case ZEND_ACC_PROTECTED:
+						echo "protected ";
+						break;
+					}
+					if ($info['flags'] & ZEND_ACC_STATIC) {
+						echo "static ";
+					}
+				}
+
+				echo '$', $name;
+				if (isset($v)) {
+					echo ' = ';
+					echo str(value($v));
+				}
+				echo ";\n";
+			}
+		}
+		// }}}
+		// {{{ function_table
+		if (isset($class['function_table'])) {
+			foreach ($class['function_table'] as $func) {
+				if (!isset($func['scope']) || $func['scope'] == $class['name']) {
+					// TODO: skip shadow here
+					echo "\n";
+					$opa = $func['op_array'];
+					if (!empty($opa['doc_comment'])) {
+						echo $newindent;
+						echo $opa['doc_comment'];
+						echo "\n";
+					}
+					echo $newindent;
+					if (isset($opa['fn_flags'])) {
+						if ($opa['fn_flags'] & ZEND_ACC_ABSTRACT) {
+							echo "abstract ";
+						}
+						if ($opa['fn_flags'] & ZEND_ACC_FINAL) {
+							echo "final ";
+						}
+						if ($opa['fn_flags'] & ZEND_ACC_STATIC) {
+							echo "static ";
+						}
+
+						switch ($opa['fn_flags'] & ZEND_ACC_PPP_MASK) {
+							case ZEND_ACC_PUBLIC:
+								echo "public ";
+								break;
+							case ZEND_ACC_PRIVATE:
+								echo "private ";
+								break;
+							case ZEND_ACC_PROTECTED:
+								echo "protected ";
+								break;
+							default:
+								echo "<visibility error> ";
+								break;
+						}
+					}
+					$this->dfunction($func, $newindent, $isinterface);
+					if ($opa['function_name'] == 'Decompiler') {
+						//exit;
+					}
+				}
+			}
+		}
+		// }}}
+		echo $indent, "}\n";
+	}
+	// }}}
+	function decompileString($string) // {{{
+	{
+		$this->dc = xcache_dasm_string($string);
+		if ($this->dc === false) {
+			echo "error compling string\n";
+			return false;
+		}
+	}
+	// }}}
+	function decompileFile($file) // {{{
+	{
+		$this->dc = xcache_dasm_file($file);
+		if ($this->dc === false) {
+			echo "error compling $file\n";
+			return false;
+		}
+	}
+	// }}}
+	function output() // {{{
+	{
+		echo "<?". "php\n";
+		foreach ($this->dc['class_table'] as $key => $class) {
+			if ($key{0} != "\0") {
+				echo "\n";
+				$this->dclass($class);
+			}
+		}
+
+		foreach ($this->dc['function_table'] as $key => $func) {
+			if ($key{0} != "\0") {
+				echo "\n";
+				$this->dfunction($func);
+			}
+		}
+
+		echo "\n";
+		$this->dop_array($this->dc['op_array']);
+		echo "\n?" . ">\n";
+		return true;
+	}
+	// }}}
+}
+
+// {{{ 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_FETCH_GLOBAL',           0);
+define('ZEND_FETCH_LOCAL',            1);
+define('ZEND_FETCH_STATIC',           2);
+define('ZEND_FETCH_STATIC_MEMBER',    3);
+define('ZEND_FETCH_GLOBAL_LOCK',      4);
+
+define('ZEND_FETCH_CLASS_DEFAULT',    0);
+define('ZEND_FETCH_CLASS_SELF',       1);
+define('ZEND_FETCH_CLASS_PARENT',     2);
+define('ZEND_FETCH_CLASS_MAIN',       3);
+define('ZEND_FETCH_CLASS_GLOBAL',     4);
+define('ZEND_FETCH_CLASS_AUTO',       5);
+define('ZEND_FETCH_CLASS_INTERFACE',  6);
+
+define('ZEND_EVAL',               (1<<0));
+define('ZEND_INCLUDE',            (1<<1));
+define('ZEND_INCLUDE_ONCE',       (1<<2));
+define('ZEND_REQUIRE',            (1<<3));
+define('ZEND_REQUIRE_ONCE',       (1<<4));
+
+define('ZEND_ISSET',              (1<<0));
+define('ZEND_ISEMPTY',            (1<<1));
+define('EXT_TYPE_UNUSED',         (1<<0));
+
+define('ZEND_FETCH_STANDARD',     0);
+define('ZEND_FETCH_ADD_LOCK',     1);
+
+define('ZEND_FE_FETCH_BYREF',     1);
+define('ZEND_FE_FETCH_WITH_KEY',  2);
+
+define('ZEND_MEMBER_FUNC_CALL',   1<<0);
+define('ZEND_CTOR_CALL',          1<<1);
+
+define('ZEND_ARG_SEND_BY_REF',        (1<<0));
+define('ZEND_ARG_COMPILE_TIME_BOUND', (1<<1));
+define('ZEND_ARG_SEND_FUNCTION',      (1<<2));
+
+define('BYREF_NONE',       0);
+define('BYREF_FORCE',      1);
+define('BYREF_ALLOW',      2);
+define('BYREF_FORCE_REST', 3);
+define('IS_NULL',     0);
+define('IS_LONG',     1);
+define('IS_DOUBLE',   2);
+define('IS_STRING',   3);
+define('IS_ARRAY',    4);
+define('IS_OBJECT',   5);
+define('IS_BOOL',     6);
+define('IS_RESOURCE', 7);
+define('IS_CONSTANT', 8);
+define('IS_CONSTANT_ARRAY',   9);
+
+@define('XC_IS_CV', 16);
+
+/*
+if (preg_match_all('!XC_[A-Z_]+!', file_get_contents(__FILE__), $ms)) {
+	$verdiff = array();
+	foreach ($ms[0] as $k) {
+		if (!defined($k)) {
+			$verdiff[$k] = -1;
+			define($k, -1);
+		}
+	}
+	var_export($verdiff);
+}
+/*/
+foreach (array (
+	'XC_HANDLE_EXCEPTION' => -1,
+	'XC_FETCH_CLASS' => -1,
+	'XC_FETCH_' => -1,
+	'XC_FETCH_DIM_' => -1,
+	'XC_ASSIGN_DIM' => -1,
+	'XC_UNSET_DIM' => -1,
+	'XC_FETCH_OBJ_' => -1,
+	'XC_ASSIGN_OBJ' => -1,
+	'XC_ISSET_ISEMPTY_DIM_OBJ' => -1,
+	'XC_ISSET_ISEMPTY_PROP_OBJ' => -1,
+	'XC_ISSET_ISEMPTY_VAR' => -1,
+	'XC_INIT_METHOD_CALL' => -1,
+	'XC_VERIFY_ABSTRACT_CLASS' => -1,
+	'XC_DECLARE_CLASS' => -1,
+	'XC_DECLARE_INHERITED_CLASS' => -1,
+	'XC_ADD_INTERFACE' => -1,
+	'XC_POST_DEC_OBJ' => -1,
+	'XC_POST_INC_OBJ' => -1,
+	'XC_PRE_DEC_OBJ' => -1,
+	'XC_PRE_INC_OBJ' => -1,
+	'XC_UNSET_OBJ' => -1,
+	'XC_JMP_NO_CTOR' => -1,
+	'XC_FETCH_' => -1,
+	'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,
+) as $k => $v) {
+	if (!defined($k)) {
+		define($k, $v);
+	}
+}
+
+/* XC_UNDEF XC_OP_DATA
+$content = file_get_contents(__FILE__);
+for ($i = 0; $opname = xcache_get_opcode($i); $i ++) {
+	if (!preg_match("/\\bXC_" . $opname . "\\b(?!')/", $content)) {
+		echo "not done ", $opname, "\n";
+	}
+}
+// */
+// }}}
+
Index: /tags/1.3.0-rc1/lock.h
===================================================================
--- /tags/1.3.0-rc1/lock.h	(revision 394)
+++ /tags/1.3.0-rc1/lock.h	(revision 394)
@@ -0,0 +1,11 @@
+typedef struct _xc_lock_t xc_lock_t;
+
+xc_lock_t *xc_fcntl_init(const char *pathname);
+void xc_fcntl_destroy(xc_lock_t *lck);
+void xc_fcntl_lock(xc_lock_t *lck);
+void xc_fcntl_unlock(xc_lock_t *lck);
+
+#define xc_lock_init(name)  xc_fcntl_init(name)
+#define xc_lock_destroy(fd) xc_fcntl_destroy(fd)
+#define xc_lock(fd)         xc_fcntl_lock(fd)
+#define xc_unlock(fd)       xc_fcntl_unlock(fd)
Index: /tags/1.3.0-rc1/xcache.h
===================================================================
--- /tags/1.3.0-rc1/xcache.h	(revision 650)
+++ /tags/1.3.0-rc1/xcache.h	(revision 650)
@@ -0,0 +1,360 @@
+#ifndef __XCACHE_H
+#define __XCACHE_H
+#define XCACHE_NAME       "XCache"
+#define XCACHE_VERSION    "1.3.0-dev"
+#define XCACHE_AUTHOR     "mOo"
+#define XCACHE_COPYRIGHT  "Copyright (c) 2005-2009"
+#define XCACHE_URL        "http://xcache.lighttpd.net"
+#define XCACHE_WIKI_URL   XCACHE_URL "/wiki"
+
+#include <php.h>
+#include <zend_compile.h>
+#include <zend_API.h>
+#include <zend.h>
+#include "php_ini.h"
+#include "zend_hash.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "xc_shm.h"
+#include "lock.h"
+
+#define HAVE_INODE
+#if !defined(ZEND_ENGINE_2_1) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1 || PHP_MAJOR_VERSION > 5)
+#	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
+
+#define NOTHING
+/* ZendEngine code Switcher */
+#ifndef ZEND_ENGINE_2
+#	define ZESW(v1, v2) v1
+#else
+#	define ZESW(v1, v2) v2
+#endif
+
+#ifdef do_alloca_with_limit
+#	define my_do_alloca(size, use_heap) do_alloca_with_limit(size, use_heap)
+#	define my_free_alloca(size, use_heap) free_alloca_with_limit(size, use_heap)
+#elif defined(ALLOCA_FLAG)
+#	define my_do_alloca(size, use_heap) do_alloca(size, use_heap)
+#	define my_free_alloca(size, use_heap) free_alloca(size, use_heap)
+#else
+#	define my_do_alloca(size, use_heap) do_alloca(size)
+#	define my_free_alloca(size, use_heap) free_alloca(size)
+#	define ALLOCA_FLAG(x)
+#endif
+#ifndef Z_SET_ISREF
+#	define Z_SET_ISREF(z) (z).is_ref = 1
+#endif
+#ifndef Z_UNSET_ISREF
+#	define Z_UNSET_ISREF(z) (z).is_ref = 0
+#endif
+#ifndef Z_SET_REFCOUNT
+#	define Z_SET_REFCOUNT(z, rc) (z).refcount = rc
+#endif
+#ifndef IS_CONSTANT_TYPE_MASK
+#	define IS_CONSTANT_TYPE_MASK (~IS_CONSTANT_INDEX)
+#endif
+
+/* {{{ dirty fix for PHP 6 */
+#ifdef add_assoc_long_ex
+static inline void my_add_assoc_long_ex(zval *arg, char *key, uint key_len, long value)
+{
+	add_assoc_long_ex(arg, key, key_len, value);
+}
+#	undef add_assoc_long_ex
+#	define add_assoc_long_ex my_add_assoc_long_ex
+#endif
+#ifdef add_assoc_bool_ex
+static inline void my_add_assoc_bool_ex(zval *arg, char *key, uint key_len, zend_bool value)
+{
+	add_assoc_bool_ex(arg, key, key_len, value);
+}
+#	undef add_assoc_bool_ex
+#	define add_assoc_bool_ex my_add_assoc_bool_ex
+#endif
+#ifdef add_assoc_null_ex
+static inline void my_add_assoc_null_ex(zval *arg, char *key, uint key_len)
+{
+	add_assoc_null_ex(arg, key, key_len);
+}
+#	undef add_assoc_null_ex
+#	define add_assoc_null_ex my_add_assoc_null_ex
+#endif
+/* }}} */
+
+/* unicode */
+#ifdef IS_UNICODE
+#	define UNISW(text, unicode) unicode
+#else
+#	define UNISW(text, unicode) text
+#endif
+#define BUCKET_KEY_SIZE(b) \
+		(UNISW( \
+			(b)->nKeyLength, \
+				((b)->key.type == IS_UNICODE) \
+				? UBYTES(b->nKeyLength) \
+				: b->nKeyLength \
+				))
+#define BUCKET_KEY_S(b)    (UNISW((b)->arKey, (b)->key.arKey.s))
+#define BUCKET_KEY_U(b)    (UNISW((b)->arKey, (b)->key.arKey.u))
+#define BUCKET_KEY_TYPE(b) (UNISW(IS_STRING,  (b)->key.type))
+#ifdef IS_UNICODE
+#	define BUCKET_HEAD_SIZE(b) XtOffsetOf(Bucket, key.arKey)
+#else
+#	define BUCKET_HEAD_SIZE(b) XtOffsetOf(Bucket, arKey)
+#endif
+#define BUCKET_SIZE(b) (BUCKET_HEAD_SIZE(b) + BUCKET_KEY_SIZE(b))
+
+#ifndef IS_UNICODE
+typedef char *zstr;
+#	define ZSTR_S(s)     (s)
+#	define ZSTR_U(s)     (s)
+#	define ZSTR_V(s)     (s)
+#	define ZSTR_PS(s)    (s)
+#	define ZSTR_PU(s)    (s)
+#	define ZSTR_PV(s)    (s)
+#else
+#	define ZSTR_S(zs)    ((zs).s)
+#	define ZSTR_U(zs)    ((zs).u)
+#	define ZSTR_V(zs)    ((zs).v)
+#	define ZSTR_PS(pzs)  ((pzs)->s)
+#	define ZSTR_PU(pzs)  ((pzs)->u)
+#	define ZSTR_PV(pzs)  ((pzs)->v)
+#endif
+
+#ifndef ZSTR
+#	define ZSTR(s)      (s)
+#endif
+
+#ifndef Z_UNIVAL
+#	define Z_UNIVAL(zval) (zval).value.str.val
+#	define Z_UNILEN(zval) (zval).value.str.len
+#endif
+
+/* {{{ u hash wrapper */
+#ifndef IS_UNICODE
+#	define zend_u_hash_add(ht, type, arKey, nKeyLength, pData, nDataSize, pDest) \
+ 	   zend_hash_add(ht, arKey, nKeyLength, pData, nDataSize, pDest)
+
+#	define zend_u_hash_quick_add(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest) \
+ 	   zend_hash_quick_add(ht, arKey, nKeyLength, h, pData, nDataSize, pDest)
+
+#	define zend_u_hash_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest) \
+ 	   zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest)
+
+#	define zend_u_hash_quick_update(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest) \
+ 	   zend_hash_quick_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest)
+
+#	define zend_u_hash_find(ht, type, arKey, nKeyLength, pData) \
+ 	   zend_hash_find(ht, arKey, nKeyLength, pData)
+
+#	define zend_u_hash_quick_find(ht, type, arKey, nKeyLength, h, pData) \
+ 	   zend_hash_quick_find(ht, arKey, nKeyLength, h, pData)
+
+#	define add_u_assoc_zval_ex(arg, type, key, key_len, value) \
+		add_assoc_zval_ex(arg, key, key_len, value)
+
+#	define zend_u_is_auto_global(type, name, name_len) \
+		zend_is_auto_global(name, name_len)
+#endif
+/* }}} */
+
+
+#define ECALLOC_N(x, n) ((x) = ecalloc(n, sizeof((x)[0])))
+#define ECALLOC_ONE(x) ECALLOC_N(x, 1)
+
+
+
+typedef ulong xc_hash_value_t;
+typedef struct {
+	int bits;
+	int size;
+	int mask;
+} xc_hash_t;
+
+/* the class entry type to be stored in class_table */
+typedef ZESW(zend_class_entry, zend_class_entry*) xc_cest_t;
+
+/* xc_cest_t to (zend_class_entry*) */
+#define CestToCePtr(st) (ZESW(\
+			&(st), \
+			st \
+			) )
+
+/* ZCEP=zend class entry ptr */
+#define ZCEP_REFCOUNT_PTR(pce) (ZESW( \
+			(pce)->refcount, \
+			&((pce)->refcount) \
+			))
+
+#define ZCE_REFCOUNT_PTR(ce) ZCE_REFCOUNT_PTR(&ce)
+
+typedef zend_op_array *(zend_compile_file_t)(zend_file_handle *h, int type TSRMLS_DC);
+
+/* {{{ xc_cache_t */
+typedef struct _xc_entry_t xc_entry_t;
+typedef struct {
+	int cacheid;
+	xc_hash_t  *hcache; /* hash to cacheid */
+
+	time_t     compiling;
+	zend_ulong misses;
+	zend_ulong hits;
+	zend_ulong clogs;
+	zend_ulong ooms;
+	zend_ulong errors;
+	xc_lock_t  *lck;
+	xc_shm_t   *shm; /* to which shm contains us */
+	xc_mem_t   *mem; /* to which mem contains us */
+
+	xc_entry_t **entries;
+	int entries_count;
+	xc_entry_t *deletes;
+	int deletes_count;
+	xc_hash_t  *hentry; /* hash to entry */
+
+	time_t     last_gc_deletes;
+	time_t     last_gc_expires;
+
+	time_t     hits_by_hour_cur_time;
+	zend_uint  hits_by_hour_cur_slot;
+	zend_ulong hits_by_hour[24];
+	time_t     hits_by_second_cur_time;
+	zend_uint  hits_by_second_cur_slot;
+	zend_ulong hits_by_second[5];
+} xc_cache_t;
+/* }}} */
+/* {{{ xc_classinfo_t */
+typedef struct {
+#ifdef IS_UNICODE
+	zend_uchar type;
+#endif
+	zstr      key;
+	zend_uint key_size;
+	ulong     h;
+	xc_cest_t cest;
+#ifndef ZEND_COMPILE_DELAYED_BINDING
+	int       oplineno;
+#endif
+} xc_classinfo_t;
+/* }}} */
+#ifdef HAVE_XCACHE_CONSTANT
+/* {{{ xc_constinfo_t */
+typedef struct {
+#ifdef IS_UNICODE
+	zend_uchar type;
+#endif
+	zstr      key;
+	zend_uint key_size;
+	ulong     h;
+	zend_constant constant;
+} xc_constinfo_t;
+/* }}} */
+#endif
+/* {{{ xc_funcinfo_t */
+typedef struct {
+#ifdef IS_UNICODE
+	zend_uchar type;
+#endif
+	zstr      key;
+	zend_uint key_size;
+	ulong     h;
+	zend_function func;
+} xc_funcinfo_t;
+/* }}} */
+#ifdef ZEND_ENGINE_2_1
+/* {{{ xc_autoglobal_t */
+typedef struct {
+#ifdef IS_UNICODE
+	zend_uchar type;
+#endif
+	zstr       key;
+	zend_uint  key_len;
+	ulong      h;
+} xc_autoglobal_t;
+/* }}} */
+#endif
+typedef enum { XC_TYPE_PHP, XC_TYPE_VAR } xc_entry_type_t;
+/* {{{ xc_entry_data_php_t */
+typedef struct {
+	size_t sourcesize;
+#ifdef HAVE_INODE
+	int device;             /* the filesystem device */
+	int inode;              /* the filesystem inode */
+#endif
+	time_t mtime;           /* the mtime of origin source file */
+
+	zend_op_array *op_array;
+
+#ifdef HAVE_XCACHE_CONSTANT
+	zend_uint constinfo_cnt;
+	xc_constinfo_t *constinfos;
+#endif
+
+	zend_uint funcinfo_cnt;
+	xc_funcinfo_t *funcinfos;
+
+	zend_uint classinfo_cnt;
+	xc_classinfo_t *classinfos;
+#ifndef ZEND_COMPILE_DELAYED_BINDING
+	zend_bool have_early_binding;
+#endif
+
+#ifdef ZEND_ENGINE_2_1
+	zend_uint autoglobal_cnt;
+	xc_autoglobal_t *autoglobals;
+#endif
+} xc_entry_data_php_t;
+/* }}} */
+/* {{{ xc_entry_data_var_t */
+typedef struct {
+	zval   *value;
+} xc_entry_data_var_t;
+/* }}} */
+typedef zvalue_value xc_entry_name_t;
+/* {{{ xc_entry_t */
+struct _xc_entry_t {
+	xc_entry_type_t type;
+	xc_hash_value_t hvalue;
+	xc_entry_t *next;
+	xc_cache_t *cache;      /* which cache it's on */
+
+	size_t     size;
+	zend_ulong refcount;
+	zend_ulong hits;
+	time_t     ctime;           /* the ctime of this entry */
+	time_t     atime;           /* the atime of this entry */
+	time_t     dtime;           /* the deletion time of this entry */
+	long       ttl;             /* ttl of time entry, var only */
+
+#ifdef IS_UNICODE
+	zend_uchar name_type;
+#endif
+	xc_entry_name_t name;
+
+	union {
+		xc_entry_data_php_t *php;
+		xc_entry_data_var_t *var;
+	} data;
+
+	zend_bool  have_references;
+};
+/* }}} */
+
+extern zend_module_entry xcache_module_entry;
+#define phpext_xcache_ptr &xcache_module_entry
+
+int xc_is_rw(const void *p);
+int xc_is_ro(const void *p);
+int xc_is_shm(const void *p);
+void xc_gc_add_op_array(zend_op_array *op_array TSRMLS_DC);
+
+#endif /* __XCACHE_H */
Index: /tags/1.3.0-rc1/xc_malloc.c
===================================================================
--- /tags/1.3.0-rc1/xc_malloc.c	(revision 603)
+++ /tags/1.3.0-rc1/xc_malloc.c	(revision 603)
@@ -0,0 +1,250 @@
+#define XC_SHM_IMPL _xc_malloc_shm_t
+#define XC_MEM_IMPL _xc_malloc_mem_t
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "xc_shm.h"
+#include "php.h"
+#include "align.h"
+#include "utils.h"
+
+struct _xc_malloc_mem_t {
+	const xc_mem_handlers_t *handlers;
+	xc_shm_t                *shm;
+	xc_memsize_t size;
+	xc_memsize_t avail;       /* total free */
+};
+
+/* {{{ _xc_malloc_shm_t */
+struct _xc_malloc_shm_t {
+	xc_shm_handlers_t *handlers;
+	xc_shmsize_t       size;
+	xc_shmsize_t       memoffset;
+#ifdef HAVE_XCACHE_TEST
+	HashTable blocks;
+#endif
+};
+/* }}} */
+
+#define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0)
+
+static void *xc_add_to_blocks(xc_mem_t *mem, void *p, size_t size) /* {{{ */
+{
+#ifdef HAVE_XCACHE_TEST
+	if (p) {
+		zend_hash_add(&mem->shm->blocks, (void *) &p, sizeof(p), (void *) &size, sizeof(size), NULL);
+	}
+#endif
+	return p;
+}
+/* }}} */
+static void xc_del_from_blocks(xc_mem_t *mem, void *p) /* {{{ */
+{
+#ifdef HAVE_XCACHE_TEST
+	zend_hash_del(&mem->shm->blocks, (void *) &p, sizeof(p));
+#endif
+}
+/* }}} */
+
+static XC_MEM_MALLOC(xc_malloc_malloc) /* {{{ */
+{
+	return xc_add_to_blocks(mem, malloc(size), size);
+}
+/* }}} */
+static XC_MEM_FREE(xc_malloc_free) /* {{{ return block size freed */
+{
+	xc_del_from_blocks(mem, (void *) p);
+	free((void *) p);
+	return 0;
+}
+/* }}} */
+static XC_MEM_CALLOC(xc_malloc_calloc) /* {{{ */
+{
+	return xc_add_to_blocks(mem, calloc(memb, size), size);
+}
+/* }}} */
+static XC_MEM_REALLOC(xc_malloc_realloc) /* {{{ */
+{
+	return xc_add_to_blocks(mem, realloc((void *) p, size), size);
+}
+/* }}} */
+static XC_MEM_STRNDUP(xc_malloc_strndup) /* {{{ */
+{
+	char *p = xc_add_to_blocks(mem, malloc(len), len);
+	if (!p) {
+		return NULL;
+	}
+	return memcpy(p, str, len);
+}
+/* }}} */
+static XC_MEM_STRDUP(xc_malloc_strdup) /* {{{ */
+{
+	return xc_malloc_strndup(mem, str, strlen(str) + 1);
+}
+/* }}} */
+
+static XC_MEM_AVAIL(xc_malloc_avail) /* {{{ */
+{
+	return mem->avail;
+}
+/* }}} */
+static XC_MEM_SIZE(xc_malloc_size) /* {{{ */
+{
+	return mem->size;
+}
+/* }}} */
+
+static XC_MEM_FREEBLOCK_FIRST(xc_malloc_freeblock_first) /* {{{ */
+{
+	return (void *) -1;
+}
+/* }}} */
+XC_MEM_FREEBLOCK_NEXT(xc_malloc_freeblock_next) /* {{{ */
+{
+	return NULL;
+}
+/* }}} */
+XC_MEM_BLOCK_SIZE(xc_malloc_block_size) /* {{{ */
+{
+	return 0;
+}
+/* }}} */
+XC_MEM_BLOCK_OFFSET(xc_malloc_block_offset) /* {{{ */
+{
+	return 0;
+}
+/* }}} */
+
+static XC_MEM_INIT(xc_mem_malloc_init) /* {{{ */
+{
+#define MINSIZE (ALIGN(sizeof(xc_mem_t)))
+	/* requires at least the header and 1 tail block */
+	if (size < MINSIZE) {
+		fprintf(stderr, "xc_mem_malloc_init requires %lu bytes at least\n", (unsigned long) MINSIZE);
+		return NULL;
+	}
+	mem->shm = shm;
+	mem->size = size;
+	mem->avail = size - MINSIZE;
+#undef MINSIZE
+
+	return mem;
+}
+/* }}} */
+static XC_MEM_DESTROY(xc_mem_malloc_destroy) /* {{{ */
+{
+}
+/* }}} */
+
+static XC_SHM_CAN_READONLY(xc_malloc_can_readonly) /* {{{ */
+{
+	return 0;
+}
+/* }}} */
+static XC_SHM_IS_READWRITE(xc_malloc_is_readwrite) /* {{{ */
+{
+#ifdef HAVE_XCACHE_TEST
+	HashPosition pos;
+	size_t *psize;
+	char **ptr;
+
+	zend_hash_internal_pointer_reset_ex(&shm->blocks, &pos);
+	while (zend_hash_get_current_data_ex(&shm->blocks, (void **) &psize, &pos) == SUCCESS) {
+		zend_hash_get_current_key_ex(&shm->blocks, (void *) &ptr, NULL, NULL, 0, &pos);
+		if ((char *) p >= *ptr && (char *) p < *ptr + *psize) {
+			return 1;
+		}
+		zend_hash_move_forward_ex(&shm->blocks, &pos);
+	}
+#endif
+
+	return 0;
+}
+/* }}} */
+static XC_SHM_IS_READONLY(xc_malloc_is_readonly) /* {{{ */
+{
+	return 0;
+}
+/* }}} */
+static XC_SHM_TO_READWRITE(xc_malloc_to_readwrite) /* {{{ */
+{
+	return p;
+}
+/* }}} */
+static XC_SHM_TO_READONLY(xc_malloc_to_readonly) /* {{{ */
+{
+	return p;
+}
+/* }}} */
+
+static XC_SHM_DESTROY(xc_malloc_destroy) /* {{{ */
+{
+#ifdef HAVE_XCACHE_TEST
+	zend_hash_destroy(&shm->blocks);
+#endif
+	free(shm);
+	return;
+}
+/* }}} */
+static XC_SHM_INIT(xc_malloc_init) /* {{{ */
+{
+	xc_shm_t *shm;
+	CHECK(shm = calloc(1, sizeof(xc_shm_t)), "shm OOM");
+	shm->size = size;
+
+#ifdef HAVE_XCACHE_TEST
+	zend_hash_init(&shm->blocks, 64, NULL, NULL, 1);
+#endif
+	return shm;
+err:
+	return NULL;
+}
+/* }}} */
+
+static XC_SHM_MEMINIT(xc_malloc_meminit) /* {{{ */
+{
+	xc_mem_t *mem;
+	if (shm->memoffset + size > shm->size) {
+		zend_error(E_ERROR, "XCache: internal error at %s#%d", __FILE__, __LINE__);
+		return NULL;
+	}
+	shm->memoffset += size;
+	CHECK(mem = calloc(1, sizeof(xc_mem_t)), "mem OOM");
+	mem->handlers = shm->handlers->memhandlers;
+	mem->handlers->init(shm, mem, size);
+	return mem;
+err:
+	return NULL;
+}
+/* }}} */
+static XC_SHM_MEMDESTROY(xc_malloc_memdestroy) /* {{{ */
+{
+	mem->handlers->destroy(mem);
+	free(mem);
+}
+/* }}} */
+
+#define xc_malloc_destroy xc_mem_malloc_destroy
+#define xc_malloc_init xc_mem_malloc_init
+static xc_mem_handlers_t xc_mem_malloc_handlers = XC_MEM_HANDLERS(malloc);
+#undef xc_malloc_init
+#undef xc_malloc_destroy
+static xc_shm_handlers_t xc_shm_malloc_handlers = XC_SHM_HANDLERS(malloc);
+void xc_shm_malloc_register() /* {{{ */
+{
+	if (xc_mem_scheme_register("malloc", &xc_mem_malloc_handlers) == 0) {
+		zend_error(E_ERROR, "XCache: failed to register malloc mem_scheme");
+	}
+
+	CHECK(xc_shm_malloc_handlers.memhandlers = xc_mem_scheme_find("malloc"), "cannot find malloc handlers");
+	if (xc_shm_scheme_register("malloc", &xc_shm_malloc_handlers) == 0) {
+		zend_error(E_ERROR, "XCache: failed to register malloc shm_scheme");
+	}
+err:
+	return;
+}
+/* }}} */
Index: /tags/1.3.0-rc1/config.m4
===================================================================
--- /tags/1.3.0-rc1/config.m4	(revision 479)
+++ /tags/1.3.0-rc1/config.m4	(revision 479)
@@ -0,0 +1,132 @@
+dnl vim:ts=2:sw=2:expandtab
+
+AC_DEFUN([XCACHE_OPTION], [
+  PHP_ARG_ENABLE(xcache-$1, for XCache $1,
+  [  --enable-xcache-$2    XCache: $4], no, no)
+  if test "$PHP_$3" != "no"; then
+    xcache_sources="$xcache_sources $1.c"
+    XCACHE_MODULES="$XCACHE_MODULES $1"
+    HAVE_$3=1
+    AC_DEFINE([HAVE_$3], 1, [Define for XCache: $4])
+  else
+    HAVE_$3=
+  fi
+])dnl
+
+PHP_ARG_ENABLE(xcache, for XCache support,
+[  --enable-xcache         Include XCache support.])
+
+if test "$PHP_XCACHE" != "no"; then
+	PHP_ARG_ENABLE(xcache-constant, for XCache handle of compile time constant,
+  [  --enable-xcache-constant        XCache: Handle new constants made by php compiler (e.g.: for __halt_compiler)], yes, no)
+	if test "$PHP_XCACHE_CONSTANT" != "no"; then
+		AC_DEFINE([HAVE_XCACHE_CONSTANT], 1, [Define to enable XCache handling of compile time constants])
+	fi
+
+  xcache_sources="processor.c \
+                  xcache.c \
+                  mmap.c \
+                  mem.c \
+                  xc_shm.c \
+                  const_string.c \
+                  opcode_spec.c \
+                  stack.c \
+                  utils.c \
+                  lock.c \
+                  "
+  XCACHE_MODULES="cacher"
+  XCACHE_OPTION([optimizer],    [optimizer   ], [XCACHE_OPTIMIZER],    [(N/A)])
+  XCACHE_OPTION([coverager],    [coverager   ], [XCACHE_COVERAGER],    [Enable code coverage dumper, useful for testing php scripts])
+  XCACHE_OPTION([assembler],    [assembler   ], [XCACHE_ASSEMBLER],    [(N/A)])
+  XCACHE_OPTION([disassembler], [disassembler], [XCACHE_DISASSEMBLER], [Enable opcode to php variable dumper, NOT for production server])
+  XCACHE_OPTION([encoder],      [encoder     ], [XCACHE_ENCODER],      [(N/A)])
+  XCACHE_OPTION([decoder],      [decoder     ], [XCACHE_DECODER],      [(N/A)])
+  AC_DEFINE_UNQUOTED([XCACHE_MODULES], "$XCACHE_MODULES", [Define what modules is built with XCache])
+
+  PHP_ARG_ENABLE(xcache-test, for XCache self test,
+  [  --enable-xcache-test            XCache: Enable self test - FOR DEVELOPERS ONLY!!], no, no)
+  if test "$PHP_XCACHE_TEST" != "no"; then
+    XCACHE_ENABLE_TEST=-DXCACHE_ENABLE_TEST
+    xcache_sources="$xcache_sources xc_malloc.c"
+    AC_DEFINE([HAVE_XCACHE_TEST], 1, [Define to enable XCache self test])
+  else
+    XCACHE_ENABLE_TEST=
+  fi
+  PHP_SUBST([XCACHE_ENABLE_TEST])
+
+  PHP_ARG_ENABLE(xcache-dprint, for XCache self test,
+  [  --enable-xcache-dprint          XCache: Enable debug print functions - FOR DEVELOPERS ONLY!!], no, no)
+  if test "$PHP_XCACHE_DPRINT" != "no"; then
+    AC_DEFINE([HAVE_XCACHE_DPRINT], 1, [Define to enable XCache debug print functions])
+  fi
+
+  PHP_NEW_EXTENSION(xcache, $xcache_sources, $ext_shared)
+  PHP_ADD_MAKEFILE_FRAGMENT()
+
+  AC_PATH_PROGS([XCACHE_AWK], [gawk awk])
+  dnl clean locale for gawk 3.1.5 assertion bug
+  if echo | LANG=C "$XCACHE_AWK" -- '' > /dev/null 2>&1 ; then
+    XCACHE_AWK="LANG=C $XCACHE_AWK"
+  else
+    if echo | /usr/bin/env - "$XCACHE_AWK" -- '' > /dev/null 2>&1 ; then
+      XCACHE_AWK="/usr/bin/env - $XCACHE_AWK"
+    fi
+  fi
+  PHP_SUBST([XCACHE_AWK])
+  AC_PATH_PROGS([M4], [m4])
+  if test "$PHP_XCACHE_TEST" != "no"; then
+    if echo | "$M4" -E > /dev/null 2>&1 ; then
+      M4="$M4 -E"
+    fi
+  fi
+   dnl fix for solaris m4: size of the push-back and argument
+  if echo | "$M4" -B 102400 > /dev/null 2>&1 ; then
+    M4="$M4 -B 102400"
+  fi
+  PHP_SUBST([M4])
+  AC_PATH_PROGS([GREP], [grep])
+  PHP_SUBST([GREP])
+  AC_PATH_PROGS([SED], [sed])
+  PHP_SUBST([SED])
+
+  AC_PATH_PROGS([INDENT], [indent cat])
+  XCACHE_INDENT=cat
+  case $INDENT in
+  */indent[)]
+    opts="-kr --use-tabs --tab-size 4 -sob -nce"
+    if echo | $INDENT $opts > /dev/null 2>&1 ; then
+      XCACHE_INDENT="$INDENT $opts"
+    else
+      opts="-sob -nce"
+      if echo | $INDENT $opts > /dev/null 2>&1 ; then
+        XCACHE_INDENT="$INDENT $opts"
+      else
+        if echo | $INDENT > /dev/null 2>&1 ; then
+          XCACHE_INDENT="$INDENT"
+        fi
+      fi
+    fi
+    ;;
+  esac
+  PHP_SUBST([XCACHE_INDENT])
+
+  dnl $ac_srcdir etc require PHP_NEW_EXTENSION
+  XCACHE_PROC_SOURCES=`ls $ac_srcdir/processor/*.m4`
+  PHP_SUBST([XCACHE_PROC_SOURCES])
+
+  AC_MSG_CHECKING(if you have opcode_spec_def.h for XCache)
+  if test -e "$ac_srcdir/opcode_spec_def.h" ; then
+    AC_DEFINE([HAVE_XCACHE_OPCODE_SPEC_DEF], 1, [Define if you have opcode_spec_def.h for XCache])
+    AC_MSG_RESULT(yes)
+  else
+    dnl check for features depend on opcode_spec_def.h
+    AC_MSG_RESULT(no)
+    define([ERROR], [
+      AC_MSG_ERROR([cannot build with $1, $ac_srcdir/opcode_spec_def.h required])
+    ])
+    if test "$PHP_XCACHE_DISASSEMBLER" != "no" ; then
+      ERROR(disassembler)
+    fi
+    undefine([ERROR])
+  fi
+fi
Index: /tags/1.3.0-rc1/xcache-zh-gb2312.ini
===================================================================
--- /tags/1.3.0-rc1/xcache-zh-gb2312.ini	(revision 604)
+++ /tags/1.3.0-rc1/xcache-zh-gb2312.ini	(revision 604)
@@ -0,0 +1,72 @@
+;; ���ļ�ֻ������, ���� php.ini �������Ա���Ч
+[xcache-common]
+;; ��װ�� zend extension (�Ƽ�), ·��һ���� "$extension_dir/xcache.so"
+zend_extension = /usr/local/lib/php/extensions/non-debug-non-zts-xxx/xcache.so
+;; Windows ϵͳ����:
+zend_extension_ts = c:/php/extensions/php_xcache.dll
+;; ������Ҳ�ɰ� XCache ��װ�� extension, ע��ȷ������ extension_dir ������ȷ, ���� xcache.so ���� php_xcache.dll �ŵ���Ŀ¼����
+; extension = xcache.so
+;; ���� Win32 ϵͳ:
+; extension = php_xcache.dll
+
+[xcache.admin]
+xcache.admin.enable_auth = On
+xcache.admin.user = "mOo"
+; xcache.admin.pass = md5($��������)
+xcache.admin.pass = ""
+
+[xcache]
+; ����Ķ���ѡ����� ini ������޸�, �����г��Ķ���Ĭ��ֵ, ��������˵��
+
+; select low level shm/allocator scheme implemenation
+xcache.shm_scheme =        "mmap"
+; ����: xcache.size=0
+; ����: xcache.size=64M ֮�� (����>0��ֵ) ͬʱ��ע������ϵͳ mmap ����
+xcache.size  =                0M
+; ��������Ϊ cpu �� (cat /proc/cpuinfo |grep -c processor)
+xcache.count =                 1
+; ֻ�Ǹ��ο�ֵ, �����Է��ĵش洢���ڴ���������Ŀ(php�ű�/����)
+xcache.slots =                8K
+; ������Ŀ�� ttl, 0=����
+xcache.ttl   =                 0
+; ɨ�������Ŀ��ʱ����, 0=��ɨ��, ����ֵ����Ϊ��λ
+xcache.gc_interval =           0
+
+; ͬ��, ֻ����Ա�����������
+xcache.var_size  =            0M
+xcache.var_count =             1
+xcache.var_slots =            8K
+; Ĭ��, ���� ini_set()
+xcache.var_ttl   =             0
+; ���ttlֵ
+xcache.var_maxttl   =          0
+xcache.var_gc_interval =     300
+
+; ��������
+xcache.test =                Off
+; /dev/zero ʱ��Ч
+xcache.readonly_protection = Off
+; ���� *nix ϵͳ, xcache.mmap_path ���ļ�·��������Ŀ¼, (���Բ����� ���Ǳ����ܴ���).
+; ������������� ReadonlyProtection, ����ʹ������ "/tmp/xcache"
+; 2 �� php �鲻�Ṳ��ͬһ�� /tmp/xcache
+; ���� Win32 ϵͳ, xcache.mmap_path=����MAP����, �����ļ�·��. ����ʹ�� XCache ���۱�������������ͻ
+xcache.mmap_path =    "/dev/zero"
+
+
+; ������ *nix ϵͳ
+; ����Ϊ��(����) �������� "/tmp/phpcore/"
+; ע���Ŀ¼Ӧ���ܱ� php д���ļ� (�� open_basedir �޹�)
+xcache.coredump_directory =   ""
+
+xcache.cacher =               On
+xcache.stat   =               On
+xcache.optimizer =           Off
+
+[xcache.coverager]
+
+; ��� xcache.coveragedump_directory ����Ϊ���������Զ�Ϊ Off
+xcache.coverager =          Off
+
+; ��ȷ����Ŀ¼�ܱ� coverage viewer �ű���ȡ (ע�� open_basedir)
+; ������ xcache.coverager=On
+xcache.coveragedump_directory = ""
Index: /tags/1.3.0-rc1/test.mak
===================================================================
--- /tags/1.3.0-rc1/test.mak	(revision 604)
+++ /tags/1.3.0-rc1/test.mak	(revision 604)
@@ -0,0 +1,21 @@
+#! /usr/bin/make -f
+
+EXES=mem_test
+OBJS=mem.o
+CC=gcc
+CFLAGS=-g -O0 -D TEST -Wall
+TEST=valgrind
+
+all: mem
+
+mem_test: mem.c
+	$(CC) $(CFLAGS) -o mem_test mem.c
+	
+mem: mem_test
+	$(TEST) ./mem_test
+
+clean:
+	rm -f $(OBJS) $(EXES)
+
+leakcheck:
+	valgrind php -c test.ini test.ini
Index: /tags/1.3.0-rc1/opcode_spec_def.h
===================================================================
--- /tags/1.3.0-rc1/opcode_spec_def.h	(revision 626)
+++ /tags/1.3.0-rc1/opcode_spec_def.h	(revision 626)
@@ -0,0 +1,217 @@
+static const xc_opcode_spec_t xc_opcode_spec[] = {
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 0 NOP                            */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 1 ADD                            */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 2 SUB                            */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 3 MUL                            */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 4 DIV                            */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 5 MOD                            */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 6 SL                             */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 7 SR                             */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 8 CONCAT                         */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 9 BW_OR                          */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 10 BW_AND                         */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 11 BW_XOR                         */
+	OPSPEC(    UNUSED,        STD,     UNUSED,        TMP) /* 12 BW_NOT                         */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 13 BOOL_NOT                       */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 14 BOOL_XOR                       */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 15 IS_IDENTICAL                   */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 16 IS_NOT_IDENTICAL               */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 17 IS_EQUAL                       */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 18 IS_NOT_EQUAL                   */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 19 IS_SMALLER                     */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 20 IS_SMALLER_OR_EQUAL            */
+	OPSPEC(      CAST,        STD,     UNUSED,        TMP) /* 21 CAST                           */
+	OPSPEC(    UNUSED,        STD,     UNUSED,        TMP) /* 22 QM_ASSIGN                      */
+#ifdef ZEND_ENGINE_2
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 23 ASSIGN_ADD                     */
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 24 ASSIGN_SUB                     */
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 25 ASSIGN_MUL                     */
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 26 ASSIGN_DIV                     */
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 27 ASSIGN_MOD                     */
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 28 ASSIGN_SL                      */
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 29 ASSIGN_SR                      */
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 30 ASSIGN_CONCAT                  */
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 31 ASSIGN_BW_OR                   */
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 32 ASSIGN_BW_AND                  */
+	OPSPEC(    ASSIGN,        STD,        STD,        VAR) /* 33 ASSIGN_BW_XOR                  */
+#else
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR)
+#endif
+	OPSPEC(    UNUSED,        VAR,     UNUSED,        VAR) /* 34 PRE_INC                        */
+	OPSPEC(    UNUSED,        VAR,     UNUSED,        VAR) /* 35 PRE_DEC                        */
+	OPSPEC(    UNUSED,        VAR,     UNUSED,        TMP) /* 36 POST_INC                       */
+	OPSPEC(    UNUSED,        VAR,     UNUSED,        TMP) /* 37 POST_DEC                       */
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR) /* 38 ASSIGN                         */
+	OPSPEC(    UNUSED,        VAR,        VAR,        VAR) /* 39 ASSIGN_REF                     */
+	OPSPEC(    UNUSED,        STD,     UNUSED,     UNUSED) /* 40 ECHO                           */
+	OPSPEC(    UNUSED,        STD,     UNUSED,        TMP) /* 41 PRINT                          */
+#ifdef ZEND_ENGINE_2
+	OPSPEC(    UNUSED,    JMPADDR,     UNUSED,     UNUSED) /* 42 JMP                            */
+	OPSPEC(    UNUSED,        STD,    JMPADDR,     UNUSED) /* 43 JMPZ                           */
+	OPSPEC(    UNUSED,        STD,    JMPADDR,     UNUSED) /* 44 JMPNZ                          */
+#else
+	OPSPEC(    UNUSED,     OPLINE,     UNUSED,     UNUSED)
+	OPSPEC(    UNUSED,        STD,     OPLINE,     UNUSED)
+	OPSPEC(    UNUSED,        STD,     OPLINE,     UNUSED)
+#endif
+	OPSPEC(    OPLINE,        STD,     OPLINE,     UNUSED) /* 45 JMPZNZ                         */
+#ifdef ZEND_ENGINE_2
+	OPSPEC(    UNUSED,        STD,    JMPADDR,        TMP) /* 46 JMPZ_EX                        */
+	OPSPEC(    UNUSED,        STD,    JMPADDR,        TMP) /* 47 JMPNZ_EX                       */
+#else
+	OPSPEC(    UNUSED,        STD,     OPLINE,        TMP)
+	OPSPEC(    UNUSED,        STD,     OPLINE,        TMP)
+#endif
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 48 CASE                           */
+	OPSPEC(       BIT,        STD,     UNUSED,     UNUSED) /* 49 SWITCH_FREE                    */
+	OPSPEC(    UNUSED,        BRK,        STD,     UNUSED) /* 50 BRK                            */
+	OPSPEC(    UNUSED,       CONT,        STD,     UNUSED) /* 51 CONT                           */
+	OPSPEC(    UNUSED,        STD,     UNUSED,        TMP) /* 52 BOOL                           */
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,        TMP) /* 53 INIT_STRING                    */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 54 ADD_CHAR                       */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 55 ADD_STRING                     */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 56 ADD_VAR                        */
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,        TMP) /* 57 BEGIN_SILENCE                  */
+	OPSPEC(    UNUSED,        TMP,     UNUSED,     UNUSED) /* 58 END_SILENCE                    */
+	OPSPEC(INIT_FCALL,        STD,        STD,     UNUSED) /* 59 INIT_FCALL_BY_NAME             */
+#ifdef ZEND_ENGINE_2
+	OPSPEC(     FCALL,        STD,     OPLINE,        VAR) /* 60 DO_FCALL                       */
+	OPSPEC(     FCALL,        STD,     OPLINE,        VAR) /* 61 DO_FCALL_BY_NAME               */
+#else
+	OPSPEC(     FCALL,        STD,     UNUSED,        VAR)
+	OPSPEC(     FCALL,        STD,     UNUSED,        VAR)
+#endif
+	OPSPEC(    UNUSED,        STD,     UNUSED,     UNUSED) /* 62 RETURN                         */
+	OPSPEC(    UNUSED,        ARG,     UNUSED,        VAR) /* 63 RECV                           */
+	OPSPEC(    UNUSED,        ARG,        STD,        VAR) /* 64 RECV_INIT                      */
+	OPSPEC(      SEND,        STD,        ARG,     UNUSED) /* 65 SEND_VAL                       */
+	OPSPEC(      SEND,        VAR,        ARG,     UNUSED) /* 66 SEND_VAR                       */
+	OPSPEC(      SEND,        VAR,        ARG,     UNUSED) /* 67 SEND_REF                       */
+#ifdef ZEND_ENGINE_2
+	OPSPEC(    UNUSED,      CLASS,     UNUSED,        VAR) /* 68 NEW                            */
+#else
+	OPSPEC(    UNUSED,        STD,     UNUSED,        VAR)
+#endif
+#ifdef ZEND_ENGINE_2_3
+	OPSPEC(       STD,        STD,        STD,        STD) /* 69 INIT_NS_FCALL_BY_NAME          */
+#else
+	OPSPEC(    UNUSED,        STD,     OPLINE,     UNUSED) /* 69 JMP_NO_CTOR                    */
+#endif
+	OPSPEC(    UNUSED,        TMP,     UNUSED,     UNUSED) /* 70 FREE                           */
+	OPSPEC(       BIT,        STD,        STD,        TMP) /* 71 INIT_ARRAY                     */
+	OPSPEC(       BIT,        STD,        STD,        TMP) /* 72 ADD_ARRAY_ELEMENT              */
+	OPSPEC(    UNUSED,        STD,    INCLUDE,        VAR) /* 73 INCLUDE_OR_EVAL                */
+#ifdef ZEND_ENGINE_2_1
+  /* php 5.1 and up */
+	OPSPEC(    UNUSED,        STD,      FETCH,     UNUSED) /* 74 UNSET_VAR                      */
+	OPSPEC(       STD,        STD,        STD,     UNUSED) /* 75 UNSET_DIM                      */
+	OPSPEC(       STD,        STD,        STD,     UNUSED) /* 76 UNSET_OBJ                      */
+	OPSPEC(       BIT,        STD,     OPLINE,        VAR) /* 77 FE_RESET                       */
+#else
+  /* <= php 5.0 */
+  /* though there is no ISSET_ISEMPTY in php 5.0 it's better to leave it here i guess */
+	OPSPEC(    UNUSED,        STD,     UNUSED,     UNUSED)
+	OPSPEC(    UNUSED,        VAR,        STD,     UNUSED)
+	OPSPEC(    UNUSED,        VAR,      ISSET,        TMP)
+	OPSPEC(       BIT,        STD,     UNUSED,        VAR)
+#endif
+	OPSPEC(        FE,        STD,     OPLINE,        TMP) /* 78 FE_FETCH                       */
+	OPSPEC(    UNUSED,        STD,     UNUSED,     UNUSED) /* 79 EXIT                           */
+	OPSPEC(    UNUSED,        STD,      FETCH,        VAR) /* 80 FETCH_R                        */
+	OPSPEC(     FETCH,        VAR,        STD,        VAR) /* 81 FETCH_DIM_R                    */
+	OPSPEC(    UNUSED,      VAR_2,        STD,        VAR) /* 82 FETCH_OBJ_R                    */
+	OPSPEC(    UNUSED,        STD,      FETCH,        VAR) /* 83 FETCH_W                        */
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR) /* 84 FETCH_DIM_W                    */
+	OPSPEC(    UNUSED,      VAR_2,        STD,        VAR) /* 85 FETCH_OBJ_W                    */
+	OPSPEC(    UNUSED,        STD,      FETCH,        VAR) /* 86 FETCH_RW                       */
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR) /* 87 FETCH_DIM_RW                   */
+	OPSPEC(    UNUSED,      VAR_2,        STD,        VAR) /* 88 FETCH_OBJ_RW                   */
+	OPSPEC(    UNUSED,        STD,      FETCH,        VAR) /* 89 FETCH_IS                       */
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR) /* 90 FETCH_DIM_IS                   */
+	OPSPEC(    UNUSED,      VAR_2,        STD,        VAR) /* 91 FETCH_OBJ_IS                   */
+	OPSPEC(       ARG,        STD,      FETCH,        VAR) /* 92 FETCH_FUNC_ARG                 */
+	OPSPEC(       ARG,        VAR,        STD,        VAR) /* 93 FETCH_DIM_FUNC_ARG             */
+	OPSPEC(       ARG,      VAR_2,        STD,        VAR) /* 94 FETCH_OBJ_FUNC_ARG             */
+	OPSPEC(    UNUSED,        STD,      FETCH,        VAR) /* 95 FETCH_UNSET                    */
+	OPSPEC(    UNUSED,        VAR,        STD,        VAR) /* 96 FETCH_DIM_UNSET                */
+	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                 */
+#else
+	OPSPEC(    UNUSED,        STD,     UNUSED,        TMP) /* 99 FETCH_CONSTANT                 */
+#endif
+	OPSPEC(   DECLARE,        STD,        STD,     UNUSED) /* 100 DECLARE_FUNCTION_OR_CLASS      */
+	OPSPEC(       STD,        STD,        STD,        STD) /* 101 EXT_STMT                       */
+	OPSPEC(       STD,        STD,        STD,        STD) /* 102 EXT_FCALL_BEGIN                */
+	OPSPEC(       STD,        STD,        STD,        STD) /* 103 EXT_FCALL_END                  */
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 104 EXT_NOP                        */
+	OPSPEC(    UNUSED,        STD,     UNUSED,     UNUSED) /* 105 TICKS                          */
+	OPSPEC(SEND_NOREF,        VAR,        ARG,     UNUSED) /* 106 SEND_VAR_NO_REF                */
+#ifdef ZEND_ENGINE_2
+	OPSPEC(    OPLINE,      CLASS,        STD,     UNUSED) /* 107 CATCH                          */
+	OPSPEC(    UNUSED,        STD,     OPLINE,     UNUSED) /* 108 THROW                          */
+	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               */
+	OPSPEC(    UNUSED,     UCLASS,        STD,     UNUSED) /* 113 INIT_STATIC_METHOD_CALL        */
+	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                   */
+	OPSPEC(    UNUSED,      CLASS,        STD,     UNUSED) /* 118 IMPORT_CONST                   */
+	OPSPEC(       STD,        STD,        STD,        STD) /* 119 OP_119                         */
+	OPSPEC(       STD,        STD,        STD,        STD) /* 120 OP_120                         */
+	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 121 ASSIGN_ADD_OBJ                 */
+	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 122 ASSIGN_SUB_OBJ                 */
+	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 123 ASSIGN_MUL_OBJ                 */
+	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 124 ASSIGN_DIV_OBJ                 */
+	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 125 ASSIGN_MOD_OBJ                 */
+	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 126 ASSIGN_SL_OBJ                  */
+	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 127 ASSIGN_SR_OBJ                  */
+	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 128 ASSIGN_CONCAT_OBJ              */
+	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 129 ASSIGN_BW_OR_OBJ               */
+	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                    */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 134 POST_INC_OBJ                   */
+	OPSPEC(    UNUSED,        STD,        STD,        TMP) /* 135 POST_DEC_OBJ                   */
+	OPSPEC(    UNUSED,        STD,        STD,        VAR) /* 136 ASSIGN_OBJ                     */
+	OPSPEC(    UNUSED,        STD,        STD,        STD) /* 137 OP_DATA                        */
+	OPSPEC(    UNUSED,        STD,      CLASS,        TMP) /* 138 INSTANCEOF                     */
+	OPSPEC(    UNUSED,        STD,        STD,      CLASS) /* 139 DECLARE_CLASS                  */
+	OPSPEC(     CLASS,        STD,        STD,      CLASS) /* 140 DECLARE_INHERITED_CLASS        */
+	OPSPEC(    UNUSED,        STD,        STD,     UNUSED) /* 141 DECLARE_FUNCTION               */
+	OPSPEC(    UNUSED,     UNUSED,     UNUSED,     UNUSED) /* 142 RAISE_ABSTRACT_ERROR           */
+#ifdef ZEND_ENGINE_2_3
+	OPSPEC(   DECLARE,        STD,        STD,     UNUSED) /* 143 DECLARE_CONST                  */
+#else
+	OPSPEC(    UNUSED,        STD,     UNUSED,     UNUSED) /* 143 START_NAMESPACE                */
+#endif
+	OPSPEC(     IFACE,      CLASS,      CLASS,     UNUSED) /* 144 ADD_INTERFACE                  */
+	OPSPEC(    UNUSED,      CLASS,        STD,     UNUSED) /* 145 VERIFY_INSTANCEOF              */
+	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               */
+# 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        */
+# endif
+#endif
+};
Index: /tags/1.3.0-rc1/admin/edit.tpl.php
===================================================================
--- /tags/1.3.0-rc1/admin/edit.tpl.php	(revision 627)
+++ /tags/1.3.0-rc1/admin/edit.tpl.php	(revision 627)
@@ -0,0 +1,13 @@
+<?php include("header.tpl.php"); ?>
+<?php
+$h_name = htmlspecialchars($name);
+$h_value = htmlspecialchars($value);
+?>
+<form method="post" action="">
+	<fieldset>
+		<legend><?php echo sprintf(_T("Editing Variable %s"), $h_name); ?></legend>
+		<textarea name="value" style="width: 100%; height: 200px; overflow-y: auto" <?php echo $editable ? "" : "disabled=disabled"; ?>><?php echo $h_value; ?></textarea><br>
+		<input type="submit">
+	</fieldset>
+</form>
+<?php include("footer.tpl.php"); ?>
Index: /tags/1.3.0-rc1/admin/tablesort.js
===================================================================
--- /tags/1.3.0-rc1/admin/tablesort.js	(revision 604)
+++ /tags/1.3.0-rc1/admin/tablesort.js	(revision 604)
@@ -0,0 +1,58 @@
+var sort_column;
+var prev_span = null;
+function get_inner_text(el) {
+ if((typeof el == 'string')||(typeof el == 'undefined'))
+  return el;
+ if(el.innerText)
+  return el.innerText;
+ else {
+  var str = "";
+  var cs = el.childNodes;
+  var l = cs.length;
+  for (i=0;i<l;i++) {
+   if (cs[i].nodeType==1) str += get_inner_text(cs[i]);
+   else if (cs[i].nodeType==3) str += cs[i].nodeValue;
+  }
+ }
+ return str;
+}
+function sortfn(a,b) {
+ var i = a.cells[sort_column].getAttribute('int');
+ if (i != null) {
+  return parseInt(i)-parseInt(b.cells[sort_column].getAttribute('int'));
+ } else {
+  var at = get_inner_text(a.cells[sort_column]);
+  var bt = get_inner_text(b.cells[sort_column]);
+  aa = at.toLowerCase();
+  bb = bt.toLowerCase();
+  if (aa==bb) return 0;
+  else if (aa<bb) return -1;
+  else return 1;
+ }
+}
+function resort(lnk) {
+ var span = lnk.childNodes[1];
+ if (!span) {
+ 	 var span = document.createElement("span")
+ 	 span.className = "sortarrow";
+ 	 lnk.appendChild(span);
+ }
+ var table = lnk.parentNode.parentNode.parentNode.parentNode;
+ var rows = new Array();
+ for (j=1;j<table.rows.length;j++)
+  rows[j-1] = table.rows[j];
+ sort_column = lnk.parentNode.cellIndex;
+ rows.sort(sortfn);
+ if (prev_span != null) prev_span.innerHTML = '';
+ if (span.getAttribute('sortdir')=='down') {
+  span.innerHTML = '&uarr;';
+  span.setAttribute('sortdir','up');
+  rows.reverse();
+ } else {
+  span.innerHTML = '&darr;';
+  span.setAttribute('sortdir','down');
+ }
+ for (i=0;i<rows.length;i++)
+  table.tBodies[0].appendChild(rows[i]);
+ prev_span = span;
+}
Index: /tags/1.3.0-rc1/admin/edit.php
===================================================================
--- /tags/1.3.0-rc1/admin/edit.php	(revision 627)
+++ /tags/1.3.0-rc1/admin/edit.php	(revision 627)
@@ -0,0 +1,44 @@
+<?php
+
+include("./common.php");
+
+if (!isset($_GET['name'])) {
+	die("missing name");
+}
+
+$name = $_GET['name'];
+// trigger auth
+$vcnt = xcache_count(XC_TYPE_VAR);
+
+if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+	if ($enable_eval) {
+		eval('$value = ' . $_POST['value']);
+	}
+	else {
+		$value = $_POST['value'];
+	}
+	xcache_set($name, $value);
+	header("Location: xcache.php?type=" . XC_TYPE_VAR);
+	exit;
+}
+$value = xcache_get($name);
+if ($enable_eval) {
+	$value = var_export($value, true);
+	$editable = true;
+}
+else {
+	if (is_string($value)) {
+		$editable = true;
+	}
+	else {
+		$editable = false;
+		$value = var_export($value, true);
+	}
+}
+
+$xcache_version = XCACHE_VERSION;
+$xcache_modules = XCACHE_MODULES;
+
+include("edit.tpl.php");
+
+?>
Index: /tags/1.3.0-rc1/admin/header.tpl.php
===================================================================
--- /tags/1.3.0-rc1/admin/header.tpl.php	(revision 623)
+++ /tags/1.3.0-rc1/admin/header.tpl.php	(revision 623)
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<?php
+echo <<<HEAD
+	<meta http-equiv="Content-Type" content="text/html; charset=$charset" />
+	<meta http-equiv="Content-Language" content="$lang" />
+	<script type="text/javascript" src="tablesort.js" charset="$charset"></script>
+HEAD;
+?>
+
+	<link rel="stylesheet" type="text/css" href="xcache.css" />
+	<title><?php echo sprintf(_T("XCache %s Administration"), $xcache_version); ?></title>
+</head>
+
+<body>
+<h1><?php echo sprintf(_T("XCache %s Administration"), $xcache_version); ?></h1>
Index: /tags/1.3.0-rc1/admin/common.php
===================================================================
--- /tags/1.3.0-rc1/admin/common.php	(revision 625)
+++ /tags/1.3.0-rc1/admin/common.php	(revision 625)
@@ -0,0 +1,116 @@
+<?php
+
+function get_language_file_ex($name, $l, $s)
+{
+	static $lmap = array(
+			'zh'    => 'zh-simplified',
+			'zh-hk' => 'zh-traditional',
+			'zh-tw' => 'zh-traditional',
+			);
+	static $smap = array(
+			'gbk'     => 'gb2312',
+			'gb18030' => 'gb2312',
+			);
+
+	if (isset($lmap[$l])) {
+		$l = $lmap[$l];
+	}
+	if (file_exists($file = "$name-$l-$s.lang.php")) {
+		return $file;
+	}
+	if (isset($smap[$s])) {
+		$s = $smap[$s];
+		if (file_exists($file = "$name-$l-$s.lang.php")) {
+			return $file;
+		}
+	}
+	if (file_exists($file = "$name-$l.lang.php")) {
+		return $file;
+	}
+	return null;
+}
+
+function get_language_file($name)
+{
+	global $charset, $lang;
+	$s = strtolower($charset);
+	if (isset($lang)) {
+		$l = strtolower($lang);
+		$file = get_language_file_ex($name, $l, $s);
+		if (!isset($file)) {
+			$l = strtok($l, '-');
+			$file = get_language_file_ex($name, $l, $s);
+		}
+	}
+	else if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+		foreach (explode(',', str_replace(' ', '', $_SERVER['HTTP_ACCEPT_LANGUAGE'])) as $l) {
+			$l = strtok($l, ';');
+			$file = get_language_file_ex($name, $l, $s);
+			if (isset($file)) {
+				$lang = $l;
+				break;
+			}
+			if (strpos($l, '-') !== false) {
+				$ll = strtok($l, '-');
+				$file = get_language_file_ex($name, $ll, $s);
+				if (isset($file)) {
+					$lang = $l;
+					break;
+				}
+			}
+		}
+	}
+	return isset($file) ? $file : "$name-en.lang.php";
+}
+
+function _T($str)
+{
+	if (isset($GLOBALS['strings'][$str])) {
+		return $GLOBALS['strings'][$str];
+	}
+	if (!empty($GLOBALS['show_todo_strings'])) {
+		return '<span style="color:red">' . htmlspecialchars($str) . '</span>';
+	}
+	return $str;
+}
+
+function stripaddslashes_array($value, $mqs = false)
+{
+	if (is_array($value)) {
+		foreach($value as $k => $v) {
+			$value[$k] = stripaddslashes_array($v, $mqs);
+		}
+	}
+	else if(is_string($value)) {
+		$value = $mqs ? str_replace('\'\'', '\'', $value) : stripslashes($value);
+	}
+	return $value;
+}
+
+error_reporting(E_ALL);
+ini_set('display_errors', 'On');
+define('REQUEST_TIME', time());
+
+if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc()) {
+	$mqs = (bool) ini_get('magic_quotes_sybase');
+	$_GET = stripaddslashes_array($_GET, $mqs);
+	$_POST = stripaddslashes_array($_POST, $mqs);
+	$_REQUEST = stripaddslashes_array($_REQUEST, $mqs);
+}
+ini_set('magic_quotes_runtime', '0');
+
+$charset = "UTF-8";
+if (file_exists("./config.php")) {
+	include("./config.php");
+}
+
+include(get_language_file("common"));
+if (!isset($lang)) {
+	$lang = 'en-us';
+}
+if (!isset($usage_graph_width) && !isset($free_graph_width)) {
+	$usage_graph_width = 120;
+}
+$graph_width = isset($free_graph_width) ? $free_graph_width : $usage_graph_width;
+
+?>
Index: /tags/1.3.0-rc1/admin/help.php
===================================================================
--- /tags/1.3.0-rc1/admin/help.php	(revision 604)
+++ /tags/1.3.0-rc1/admin/help.php	(revision 604)
@@ -0,0 +1,33 @@
+<?php
+include("./common.php");
+?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<?php
+echo <<<HEAD
+	<meta http-equiv="Content-Type" content="text/html; charset=$charset" />
+	<meta http-equiv="Content-Language" content="$lang" />
+	<script type="text/javascript" src="tablesort.js" charset="$charset"></script>
+HEAD;
+?>
+
+	<link rel="stylesheet" type="text/css" href="xcache.css" />
+	<title><?php echo _T('XCache Administration Help'); ?></title>
+	<script>
+	function toggle(o)
+	{
+		o.style.display = o.style.display != 'block' ? 'block' : 'none';
+	}
+	</script>
+</head>
+
+<body>
+<h1><?php echo _T('XCache Administration Help'); ?></h1>
+<div id1="help">
+<?php include(get_language_file("help")); ?>
+</div>
+
+<?php echo _T('See also'); ?>: <a href="http://xcache.lighttpd.net/wiki/PhpIni">setting php.ini for XCache</a> in the <a href="http://xcache.lighttpd.net/">XCache wiki</a>
+</body>
+</html>
Index: /tags/1.3.0-rc1/admin/xcache.tpl.php
===================================================================
--- /tags/1.3.0-rc1/admin/xcache.tpl.php	(revision 623)
+++ /tags/1.3.0-rc1/admin/xcache.tpl.php	(revision 623)
@@ -0,0 +1,288 @@
+<?php include("header.tpl.php"); ?>
+<div id="help">
+	<a href="help.php"><?php echo _T("Help") ?> &raquo;</a>
+</div>
+<div class="switcher"><?php echo switcher("type", $types); ?></div>
+<?php
+$a = new Cycle('class="col1"', 'class="col2"');
+$b = new Cycle('class="col1"', 'class="col2"');
+?>
+<table cellspacing="0" cellpadding="4" class="cycles">
+	<caption><?php echo _T('Caches'); ?></caption>
+	<col />
+	<col align="right" />
+	<col align="right" />
+	<col align="right" />
+	<col />
+	<col />
+	<col align="right" />
+	<col align="right" />
+	<col align="right" />
+	<col />
+	<col align="right" />
+	<col align="right" />
+	<col align="right" />
+	<col align="right" />
+	<col align="right" />
+	<col align="right" />
+	<col align="right" />
+	<col />
+	<tr <?php echo $a->next(); ?>>
+		<th>-</th>
+		<th><?php echo _T('Slots'); ?></th>
+		<th><?php echo _T('Size'); ?></th>
+		<th><?php echo _T('Avail'); ?></th>
+		<th><?php echo _T(isset($free_graph_width) ? '% Free' : '% Used'); ?></th>
+		<th><?php echo _T('Clear'); ?></th>
+		<th><?php echo _T('Compiling'); ?></th>
+		<th><?php echo _T('Hits'); ?></th>
+		<th><?php echo _T('Hits/H'); ?></th>
+		<th><?php echo _T('Hits 24H'); ?></th>
+		<th><?php echo _T('Hits/S'); ?></th>
+		<th><?php echo _T('Misses'); ?></th>
+		<th><?php echo _T('Clogs'); ?></th>
+		<th><?php echo _T('OOMs'); ?></th>
+		<th><?php echo _T('Errors'); ?></th>
+		<th><?php echo _T('Protected'); ?></th>
+		<th><?php echo _T('Cached'); ?></th>
+		<th><?php echo _T('Deleted'); ?></th>
+		<th><?php echo _T('GC'); ?></th>
+	</tr>
+	<?php
+	$numkeys = explode(',', 'slots,size,avail,hits,misses,clogs,ooms,errors,cached,deleted');
+	$l_clear = _T('Clear');
+	$l_clear_confirm = _T('Sure to clear?');
+	foreach ($cacheinfos as $i => $ci) {
+		echo "
+		<tr ", $a->next(), ">";
+		$pvalue = (int) ($ci['avail'] / $ci['size'] * 100);
+		$pempty = 100 - $pvalue;
+		if (!isset($free_graph_width)) {
+			// swap
+			$tmp = $pvalue;
+			$pvalue = $pempty;
+			$pempty = $tmp;
+		}
+
+		$w = $graph_width;
+		if (empty($ci['istotal'])) {
+			$graph = freeblock_to_graph($ci['free_blocks'], $ci['size']);
+			$blocksgraph = "<div class=\"blocksgraph\" style=\"width: {$w}px\">{$graph}</div>";
+		}
+		else {
+			$blocksgraph = '';
+		}
+
+		$ci_slots = size($ci['slots']);
+		$ci_size  = size($ci['size']);
+		$ci_avail = size($ci['avail']);
+		$ci = number_formats($ci, $numkeys);
+
+		$hits_avg_h     = number_format(array_avg($ci['hits_by_hour']), 2);
+		$hits_avg_s     = number_format(array_avg($ci['hits_by_second']), 2);
+		$hits_graph_h   = hits_to_graph($ci['hits_by_hour']);
+		$hits_graph_h_w = count($ci['hits_by_hour']) * 2;
+
+		if (!empty($ci['istotal'])) {
+			$ci['compiling']    = '-';
+			$ci['can_readonly'] = '-';
+		}
+		else {
+			$ci['compiling']    = $ci['type'] == $type_php ? ($ci['compiling'] ? 'yes' : 'no') : '-';
+			$ci['can_readonly'] = $ci['can_readonly'] ? 'yes' : 'no';
+		}
+		echo <<<EOS
+		<th>{$ci['cache_name']}</th>
+		<td title="{$ci['slots']}">{$ci_slots}</td>
+		<td title="{$ci['size']}">{$ci_size}</td>
+		<td title="{$ci['avail']}">{$ci_avail}</td>
+		<td title="{$pvalue} %"
+			><div class="percent" style="width: {$w}px"
+				><div style="width: {$pvalue}%" class="pvalue"></div
+				><div style="width: {$pempty}%" class="pempty"></div
+			></div
+		>{$blocksgraph}</td>
+		<td
+			><form method="post" action=""
+				><div
+					><input type="hidden" name="type" value="{$ci['type']}"
+					/><input type="hidden" name="cacheid" value="{$ci['cacheid']}"
+					/><input type="submit" name="clearcache" value="{$l_clear}" class="submit" onclick="return confirm('{$l_clear_confirm}');"
+				/></div
+			></form
+		></td>
+		<td>{$ci['compiling']}</td>
+		<td>{$ci['hits']}</td>
+		<td>{$hits_avg_h}</td>
+		<td><div class="hitsgraph" style="width: {$hits_graph_h_w}px">{$hits_graph_h}</div></td>
+		<td>{$hits_avg_s}</td>
+		<td>{$ci['misses']}</td>
+		<td>{$ci['clogs']}</td>
+		<td>{$ci['ooms']}</td>
+		<td>{$ci['errors']}</td>
+		<td>{$ci['can_readonly']}</td>
+		<td>{$ci['cached']}</td>
+		<td>{$ci['deleted']}</td>
+		<td>{$ci['gc']}</td>
+EOS;
+
+			$b->reset();
+			?>
+	</tr>
+	<?php } ?>
+</table>
+<div class="blockarea legends">
+	<div class="legendtitle"><?php echo _T('Legends:'); ?></div>
+	<div class="legend pvalue">&nbsp;&nbsp;</div>
+	<div class="legendtitle"><?php echo _T(isset($free_graph_width) ? '% Free' : '% Used'); ?></div>
+	<div class="legend" style="background: rgb(0,0,255)">&nbsp;&nbsp;</div>
+	<div class="legendtitle"><?php echo _T(isset($free_graph_width) ? 'Free Blocks' : 'Used Blocks'); ?></div>
+	<div class="legend" style="background: rgb(255,0,0)">&nbsp;&nbsp;</div>
+	<div class="legendtitle"><?php echo _T('Hits'); ?></div>
+</div>
+<?php
+
+if ($cachelist) {
+	$isphp = $cachelist['type'] == $type_php;
+	if (function_exists("ob_filter_path_nicer")) {
+		ob_start("ob_filter_path_nicer");
+	}
+	foreach (array('Cached' => $cachelist['cache_list'], 'Deleted' => $cachelist['deleted_list']) as $listname => $entries) {
+		$a->reset();
+		?>
+
+	<form action="" method="post">
+	<table cellspacing="0" cellpadding="4" class="cycles entries" width="100%">
+		<caption><?php echo _T("{$cachelist['type_name']} $listname"); ?></caption>
+		<col />
+		<col />
+		<col />
+		<col align="right" />
+		<col align="right" />
+		<col align="right" />
+		<col align="right" />
+		<col align="right" />
+		<col align="right" />
+		<?php
+		if ($listname == 'Deleted') {
+			echo '<col align="right" />';
+		}
+		if ($isphp) {
+			echo '<col align="right" />';
+			echo '<col align="right" />';
+			echo '<col align="right" />';
+		}
+
+		echo "
+		<tr ", $a->next(), ">";
+		?>
+
+			<?php if (!$isphp) { ?>
+			<th width="20">R</th>
+			<?php } ?>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('Cache'); ?></a></th>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('entry'); ?></a></th>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('Hits'); ?></a></th>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('Refcount'); ?></a></th>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('Size'); ?></a></th>
+			<?php if ($isphp) { ?>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('SrcSize'); ?></a></th>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('Modify'); ?></a></th>
+			<?php if ($haveinode) { ?>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('device'); ?></a></th>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('inode'); ?></a></th>
+			<?php } ?>
+			<?php } ?>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('hash'); ?></a></th>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('Access'); ?></a></th>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('Create'); ?></a></th>
+			<?php if ($listname == 'Deleted') { ?>
+			<th><a href="javascript:" onclick="resort(this); return false"><?php echo _T('Delete'); ?></a></th>
+			<?php } ?>
+		</tr>
+		<?php
+		foreach ($entries as $i => $entry) {
+			echo "
+			<tr ", $a->next(), ">";
+			$name     = htmlspecialchars($entry['name']);
+			$hits     = number_format($entry['hits']);
+			$refcount = number_format($entry['refcount']);
+			$size     = size($entry['size']);
+			if ($isphp) {
+				$sourcesize = size($entry['sourcesize']);
+			}
+
+			if ($isphp) {
+				$mtime = age($entry['mtime']);
+			}
+			$ctime = age($entry['ctime']);
+			$atime = age($entry['atime']);
+			if ($listname == 'Deleted') {
+				$dtime = age($entry['dtime']);
+			}
+
+			if (!$isphp) {
+				echo <<<ENTRY
+					<td><input type="checkbox" name="remove[]" value="{$name}"/></td>
+ENTRY;
+				$uname = urlencode($entry['name']);
+				$namelink = "<a href=\"edit.php?name=$uname\">$name</a>";
+			}
+			else {
+				$namelink = $name;
+			}
+
+			echo <<<ENTRY
+			<td>{$entry['cache_name']} {$i}</td>
+			<td>{$namelink}</td>
+			<td int="{$entry['hits']}">{$entry['hits']}</td>
+			<td int="{$entry['refcount']}">{$entry['refcount']}</td>
+			<td int="{$entry['size']}">{$size}</td>
+ENTRY;
+			if ($isphp) {
+				echo <<<ENTRY
+				<td int="{$entry['sourcesize']}">{$sourcesize}</td>
+				<td int="{$entry['mtime']}">{$mtime}</td>
+ENTRY;
+				if (isset($entry['inode'])) {
+					echo <<<ENTRY
+					<td int="{$entry['device']}">{$entry['device']}</td>
+					<td int="{$entry['inode']}">{$entry['inode']}</td>
+ENTRY;
+				}
+			}
+			echo <<<ENTRY
+			<td int="{$entry['hvalue']}">{$entry['hvalue']}</td>
+			<td int="{$entry['atime']}">{$atime}</td>
+			<td int="{$entry['ctime']}">{$ctime}</td>
+ENTRY;
+			if ($listname == 'Deleted') {
+			echo <<<ENTRY
+				<td int="{$entry['dtime']}">{$dtime}</td>
+ENTRY;
+			}
+
+			echo "
+		</tr>
+			";
+		}
+		?>
+
+	</table>
+	<input type="submit" value="<?php echo _T("Remove Selected"); ?>">
+	</form>
+<?php
+	}
+	if (function_exists("ob_filter_path_nicer")) {
+		ob_end_flush();
+	}
+}
+if ($moduleinfo) {
+	$t_moduleinfo = _T("Module Info");
+	echo <<<HTML
+<h2>$t_moduleinfo</h2>
+<div class="moduleinfo">$moduleinfo</div>
+HTML;
+}
+?>
+<?php include("footer.tpl.php"); ?>
Index: /tags/1.3.0-rc1/admin/mkpassword.php
===================================================================
--- /tags/1.3.0-rc1/admin/mkpassword.php	(revision 625)
+++ /tags/1.3.0-rc1/admin/mkpassword.php	(revision 625)
@@ -0,0 +1,24 @@
+<html>
+	<head>
+		<title>Simple MD5 password generator</title>
+	</head>
+	<body>
+		<h1>Simple MD5 password generator</h1>
+		<form method="post">
+			<fieldset>
+				md5: <input type="password" name="password"> <input type="submit"><br>
+				<div>
+				<?php
+				if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+					$md5 = md5(@ $_POST['password']);
+					$offs = mt_rand(0 + 1, 31 - 1);
+					$md5_1 = substr($md5, 0, $offs);
+					$md5_2 = substr($md5, $offs);
+					echo "Result: <span>$md5_1</span><span>$md5_2</span>";
+				}
+				?>
+				</div>
+			</fieldset>
+		</form>
+	</body>
+</html>
Index: /tags/1.3.0-rc1/admin/xcache.php
===================================================================
--- /tags/1.3.0-rc1/admin/xcache.php	(revision 625)
+++ /tags/1.3.0-rc1/admin/xcache.php	(revision 625)
@@ -0,0 +1,373 @@
+<?php
+
+include("./common.php");
+
+class Cycle
+{
+	var $values;
+	var $i;
+	var $count;
+
+	function Cycle($v)
+	{
+		$this->values = func_get_args();
+		$this->i = -1;
+		$this->count = count($this->values);
+	}
+
+	function next()
+	{
+		$this->i = ($this->i + 1) % $this->count;
+		return $this->values[$this->i];
+	}
+
+	function cur()
+	{
+		return $this->values[$this->i];
+	}
+
+	function reset()
+	{
+		$this->i = -1;
+	}
+}
+
+function number_formats($a, $keys)
+{
+	foreach ($keys as $k) {
+		$a[$k] = number_format($a[$k]);
+	}
+	return $a;
+}
+
+function size($size)
+{
+	$size = (int) $size;
+	if ($size < 1024)
+		return number_format($size, 2) . ' b';
+
+	if ($size < 1048576)
+		return number_format($size / 1024, 2) . ' K';
+
+	return number_format($size / 1048576, 2) . ' M';
+}
+
+function age($time)
+{
+	if (!$time) return '';
+	$delta = REQUEST_TIME - $time;
+
+	if ($delta < 0) {
+		$delta = -$delta;
+	}
+	
+  	static $seconds = array(1, 60, 3600, 86400, 604800, 2678400, 31536000);
+	static $name = array('s', 'm', 'h', 'd', 'w', 'M', 'Y');
+
+	for ($i = 6; $i >= 0; $i --) {
+		if ($delta >= $seconds[$i]) {
+			$ret = (int) ($delta / $seconds[$i]);
+			return $ret . ' ' . $name[$i];
+		}
+	}
+
+	return '0 s';
+}
+
+function freeblock_to_graph($freeblocks, $size)
+{
+	global $graph_width, $usage_graph_width, $free_graph_width;
+
+	// cached in static variable
+	static $graph_initial;
+	if (!isset($graph_initial)) {
+		$graph_initial = array_fill(0, $graph_width, 0);
+	}
+	$graph = $graph_initial;
+	foreach ($freeblocks as $b) {
+		$begin = $b['offset'] / $size * $graph_width;
+		$end = ($b['offset'] + $b['size']) / $size * $graph_width;
+
+		if ((int) $begin == (int) $end) {
+			$v = $end - $begin;
+			$graph[(int) $v] += $v - (int) $v;
+		}
+		else {
+			$graph[(int) $begin] += 1 - ($begin - (int) $begin);
+			$graph[(int) $end] += $end - (int) $end;
+			for ($i = (int) $begin + 1, $e = (int) $end; $i < $e; $i ++) {
+				$graph[$i] += 1;
+			}
+		}
+	}
+	$html = array();
+	$c = 255;
+	foreach ($graph as $k => $v) {
+		if (!isset($free_graph_width)) {
+			$v = 1 - $v;
+		}
+		$v = (int) ($v * $c);
+		$r = $g = $c - $v;
+		$b = $c;
+		$html[] = '<div style="background: rgb(' . "$r,$g,$b" . ')"></div>';
+	}
+	return implode('', $html);
+}
+
+function calc_total(&$total, $data)
+{
+	foreach ($data as $k => $v) {
+		switch ($k) {
+		case 'type':
+		case 'cache_name':
+		case 'cacheid':
+		case 'free_blocks':
+			continue 2;
+		}
+		if (!isset($total[$k])) {
+			$total[$k] = $v;
+		}
+		else {
+			switch ($k) {
+			case 'hits_by_hour':
+			case 'hits_by_second':
+				foreach ($data[$k] as $kk => $vv) {
+					$total[$k][$kk] += $vv;
+				}
+				break;
+
+			default:
+				$total[$k] += $v;
+			}
+		}
+	}
+}
+
+function array_avg($a)
+{
+	if (count($a) == 0) {
+		return '';
+	}
+	return array_sum($a) / count($a);
+}
+
+function bar_hits_percent($v, $percent, $active)
+{
+	$r = 220 + (int) ($percent * 25);
+	$g = $b = 220 - (int) ($percent * 220);
+	$percent = (int) ($percent * 100);
+	$a = $active ? ' active' : '';
+	return '<div title="' . $v . '">'
+		. '<div class="barf' . $a . '" style="height: ' . (100 - $percent) . '%"></div>'
+		. '<div class="barv' . $a . '" style="background: rgb(' . "$r,$g,$b" . '); height: ' . $percent . '%"></div>'
+		. '</div>';
+}
+
+function hits_to_graph($hits)
+{
+	$max = 0;
+	foreach ($hits as $v) {
+		if ($max < $v) {
+			$max = $v;
+		}
+	}
+	if (!$max) {
+		return '';
+	}
+	$t = (time() / (60 * 60)) % 24;
+	$html = array();
+	foreach ($hits as $i => $v) {
+		$html[] = bar_hits_percent($v, $v / $max, $i == $t);
+	}
+	return implode('', $html);
+}
+
+function switcher($name, $options)
+{
+	$n = isset($_GET[$name]) ? $_GET[$name] : null;
+	$html = array();
+	foreach ($options as $k => $v) {
+		$html[] = sprintf('<a href="?%s=%s"%s>%s</a>', $name, $k, $k == $n ? ' class="active"' : '', $v);
+	}
+	return implode(' ', $html);
+}
+
+if (!extension_loaded('XCache')) {
+	echo '<h1>XCache is not loaded</h1>';
+	ob_start();
+	phpinfo();
+	$info = ob_get_clean();
+	if (preg_match('!<td class="v">(.*\\.ini)!', $info, $m)) {
+		echo "Please check $m[1]";
+	}
+	else if (preg_match('!Configuration File \\(php.ini\\) Path *</td><td class="v">([^<]+)!', $info, $m)) {
+		echo "Please put a php.ini in $m[1] and load XCache extension";
+	}
+	else {
+		echo "You don't even have a php.ini yet?";
+	}
+	exit;
+}
+$pcnt = xcache_count(XC_TYPE_PHP);
+$vcnt = xcache_count(XC_TYPE_VAR);
+
+if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+	$remove = @ $_POST['remove'];
+	if ($remove && is_array($remove)) {
+		foreach ($remove as $name) {
+			xcache_unset($name);
+		}
+	}
+}
+
+$moduleinfo = null;
+$type_none = -1;
+if (!isset($_GET['type'])) {
+	$_GET['type'] = $type_none;
+}
+$_GET['type'] = $type = (int) $_GET['type'];
+
+// {{{ process clear
+function processClear()
+{
+	$type = isset($_POST['type']) ? $_POST['type'] : null;
+	if ($type != XC_TYPE_PHP && $type != XC_TYPE_VAR) {
+		$type = null;
+	}
+	if (isset($type)) {
+		$cacheid = (int) (isset($_POST['cacheid']) ? $_POST['cacheid'] : 0);
+		if (isset($_POST['clearcache'])) {
+			$count = xcache_count($type);
+			if ($cacheid == $count) {
+				for ($cacheid = 0; $cacheid < $count; $cacheid ++) {
+					xcache_clear_cache($type, $cacheid);
+				}
+			}
+			else {
+				xcache_clear_cache($type, $cacheid);
+			}
+		}
+	}
+}
+processClear();
+// }}}
+// {{{ load info/list
+$cacheinfos = array();
+$total = array();
+for ($i = 0; $i < $pcnt; $i ++) {
+	$data = xcache_info(XC_TYPE_PHP, $i);
+	if ($type === XC_TYPE_PHP) {
+		$data += xcache_list(XC_TYPE_PHP, $i);
+	}
+	$data['type'] = XC_TYPE_PHP;
+	$data['cache_name'] = "php#$i";
+	$data['cacheid'] = $i;
+	$cacheinfos[] = $data;
+	if ($pcnt >= 2) {
+		calc_total($total, $data);
+	}
+}
+
+if ($pcnt >= 2) {
+	$total['type'] = XC_TYPE_PHP;
+	$total['cache_name'] = _T('Total');
+	$total['cacheid'] = $pcnt;
+	$total['gc'] = null;
+	$total['istotal'] = true;
+	$cacheinfos[] = $total;
+}
+
+$total = array();
+for ($i = 0; $i < $vcnt; $i ++) {
+	$data = xcache_info(XC_TYPE_VAR, $i);
+	if ($type === XC_TYPE_VAR) {
+		$data += xcache_list(XC_TYPE_VAR, $i);
+	}
+	$data['type'] = XC_TYPE_VAR;
+	$data['cache_name'] = "var#$i";
+	$data['cacheid'] = $i;
+	$cacheinfos[] = $data;
+	if ($pcnt >= 2) {
+		calc_total($total, $data);
+	}
+}
+
+if ($vcnt >= 2) {
+	$total['type'] = XC_TYPE_VAR;
+	$total['cache_name'] = _T('Total');
+	$total['cacheid'] = $vcnt;
+	$total['gc'] = null;
+	$total['istotal'] = true;
+	$cacheinfos[] = $total;
+}
+// }}}
+// {{{ merge the list
+switch ($type) {
+case XC_TYPE_PHP:
+case XC_TYPE_VAR:
+	$cachelist = array('type' => $type, 'cache_list' => array(), 'deleted_list' => array());
+	if ($type == XC_TYPE_VAR) {
+		$cachelist['type_name'] = 'var';
+	}
+	else {
+		$cachelist['type_name'] = 'php';
+	}
+	foreach ($cacheinfos as $i => $c) {
+		if (!empty($c['istotal'])) {
+			continue;
+		}
+		if ($c['type'] == $type && isset($c['cache_list'])) {
+			foreach ($c['cache_list'] as $e) {
+				$e['cache_name'] = $c['cache_name'];
+				$cachelist['cache_list'][] = $e;
+			}
+			foreach ($c['deleted_list'] as $e) {
+				$e['cache_name'] = $c['cache_name'];
+				$cachelist['deleted_list'][] = $e;
+			}
+		}
+	}
+	if ($type == XC_TYPE_PHP) {
+		$inodes = array();
+		$haveinode = false;
+		foreach ($cachelist['cache_list'] as $e) {
+			if (isset($e['inode'])) {
+				$haveinode = true;
+			}
+		}
+		if (!$haveinode) {
+			foreach ($cachelist['deleted_list'] as $e) {
+				if (isset($e['inode'])) {
+					$haveinode = true;
+				}
+			}
+		}
+	}
+	unset($data);
+	break;
+
+default:
+	$_GET['type'] = $type_none;
+	$cachelist = array();
+	ob_start();
+	phpinfo(INFO_MODULES);
+	$moduleinfo = ob_get_clean();
+	if (preg_match('!XCache</a></h2>(.*?)<h2>!is', $moduleinfo, $m)) {
+		$moduleinfo = $m[1];
+	}
+	else {
+		$moduleinfo = null;
+	}
+	break;
+}
+// }}}
+
+$type_php = XC_TYPE_PHP;
+$type_var = XC_TYPE_VAR;
+$types = array($type_none => _T('Statistics'), $type_php => _T('List PHP'), $type_var => _T('List Var Data'));
+$xcache_version = XCACHE_VERSION;
+$xcache_modules = XCACHE_MODULES;
+
+include("xcache.tpl.php");
+
+?>
Index: /tags/1.3.0-rc1/admin/xcache.css
===================================================================
--- /tags/1.3.0-rc1/admin/xcache.css	(revision 623)
+++ /tags/1.3.0-rc1/admin/xcache.css	(revision 623)
@@ -0,0 +1,50 @@
+input, table { font-family: sans-serif; }
+input { font-size: 12px; }
+table { border-collapse: collapse; font-size: 11px; margin: 0; margin-bottom: 10px; }
+table caption, h2 { font-size: 16px; font-weight: bold; text-align: left; padding-top: 20px; margin-bottom: 2px; }
+table { white-space: pre; }
+table.cycles { border: 1px solid black; margin-top: 5px; margin-bottom: 5px; }
+table.cycles .col1 { background-color: #f5f5f5; }
+table.cycles .col2 { background-color: #e0e0e0; }
+table.cycles th, table.cycles td { border: 1px solid black; font-family: monospace; }
+table.cycles th { background-color: #9999cc; color: black; font-weight: bold; height: 20px; line-height: 20px; font-family: serif; }
+th a { color: black; font-weight: bold; display: block; width: 100%; height: 100%; }
+th { font-size: 12px; }
+.moduleinfo table { border: 1px solid black; }
+.moduleinfo table th, .moduleinfo table td { border: 1px solid black; }
+.moduleinfo table th { font-weight: bold; }
+.moduleinfo .e {background-color: #ccccff; font-weight: bold; color: #000000;}
+.moduleinfo .h {background-color: #9999cc; font-weight: bold; color: #000000;}
+.moduleinfo .v {background-color: #cccccc; color: #000000;}
+.button { }
+span.sortarrow { color: white; text-decoration: none; }
+form {margin: 0; padding: 0}
+
+.percent { height: 3px; margin-bottom: 1px; border: 1px solid gray; }
+.percent div { float: left; height: 100%; }
+.pvalue { background: limegreen; }
+
+.blocksgraph { height: 16px; }
+.blocksgraph div { float: left; height: 3px; width: 4px; border: solid gray; border-width: 0 0px 1px 0; }
+.blocksgraph { border: 1px solid gray; border-bottom: 0px; }
+
+.hitsgraph { height: 20px; margin: auto; }
+.hitsgraph div { float: left; width: 2px; height: 100%; }
+.hitsgraph div:hover { background: gray; }
+.hitsgraph div div { float: none; width: 100%; }
+.hitsgraph div div.barf { border: 0px solid gray; border-width: 1px 0 0 0; }
+.hitsgraph div div.barv { border: 0px solid gray; border-width: 0 0 1px 0; }
+.hitsgraph div div.barf.active { border-color: yellow; }
+.hitsgraph div div.barv.active { border-color: yellow; }
+
+.switcher, h1 { text-align: center; display: block; }
+.switcher * { color: blue; }
+.switcher a.active { font-weight: bold; font-size: 130%; color: black; }
+#help { display: block; float: right; }
+.footnote { text-align: right; font-size: 12px; }
+dl { overflow: hidden; }
+dt { font-weight: bold; clear: both; float: left; width: 100px; text-align: right; margin: 0; }
+dd { margin: 0; }
+.blockarea { overflow: hidden; _width: 1px; }
+div.legend { float: left; border: 1px solid gray; font: 12px/12px monospace; }
+div.legendtitle { float: left; padding: 2px; padding-right: 10px; font: 12px/12px monospace; }
Index: /tags/1.3.0-rc1/admin/footer.tpl.php
===================================================================
--- /tags/1.3.0-rc1/admin/footer.tpl.php	(revision 604)
+++ /tags/1.3.0-rc1/admin/footer.tpl.php	(revision 604)
@@ -0,0 +1,9 @@
+<div class="footnote">
+<?php echo <<<EOS
+Powered By: XCache {$xcache_version}, {$xcache_modules}
+EOS;
+?>
+</div>
+
+</body>
+</html>
Index: /tags/1.3.0-rc1/admin/config.php.example
===================================================================
--- /tags/1.3.0-rc1/admin/config.php.example	(revision 627)
+++ /tags/1.3.0-rc1/admin/config.php.example	(revision 627)
@@ -0,0 +1,68 @@
+<?php
+
+// this is an example only
+// write your own config and name it as config.php
+
+// detected by browser
+// $lang = 'en-us';
+
+$charset = "UTF-8";
+
+// developers only
+$show_todo_strings = false;
+
+// width of graph for free or usage blocks
+$usage_graph_width = 120;
+// do not define both with
+// $free_graph_width = 120;
+
+// only enable if you have password protection for admin page
+// enabling this option will cause user to eval() whatever code they want
+$enable_eval = false;
+
+// this function is detected by xcache.tpl.php, and enabled if function_exists
+// this ob filter is applied for the cache list, not the whole page
+function ob_filter_path_nicer($o)
+{
+	$sep = DIRECTORY_SEPARATOR;
+	$o = str_replace($_SERVER['DOCUMENT_ROOT'],  "{DOCROOT}" . (substr($d, -1) == $sep ? $sep : ""), $o);
+	$xcachedir = realpath(dirname(__FILE__) . "$sep..$sep");
+	$o = str_replace($xcachedir . $sep, "{XCache}$sep", $o);
+	if ($sep == '/') {
+		$o = str_replace("/home/", "{H}/", $o);
+	}
+	return $o;
+}
+
+// you can simply let xcache to do the http auth
+// but if you have your home made login/permission system, you can implement the following
+// {{{ home made login example
+// this is an example only, it's won't work for you without your implemention.
+function check_admin_and_by_pass_xcache_http_auth()
+{
+	require("/path/to/user-login-and-permission-lib.php");
+	session_start();
+
+	if (!user_logined()) {
+		if (!ask_the_user_to_login()) {
+			exit;
+		}
+	}
+
+	user_load_permissions();
+	if (!user_is_admin()) {
+		die("Permission denied");
+	}
+
+	// user is trusted after permission checks above.
+	// tell XCache about it (the only way to by pass XCache http auth)
+	$_SERVER["PHP_AUTH_USER"] = "moo";
+	$_SERVER["PHP_AUTH_PW"] = "your-xcache-password";
+	return true;
+}
+
+// uncomment:
+// check_admin_and_by_pass_xcache_http_auth();
+// }}}
+
+?>
Index: /tags/1.3.0-rc1/admin/common-zh-traditional-utf-8.lang.php
===================================================================
--- /tags/1.3.0-rc1/admin/common-zh-traditional-utf-8.lang.php	(revision 623)
+++ /tags/1.3.0-rc1/admin/common-zh-traditional-utf-8.lang.php	(revision 623)
@@ -0,0 +1,122 @@
+<?php
+
+$strings = array(
+		'Cache Legends'
+		=> 'Cache 說明',
+		'List Legends'
+		=> 'List 說明',
+		'XCache Administration Help'
+		=> 'XCache 管理頁面說明訊息',
+		'Help'
+		=> '說明',
+		'Slots'
+		=> '槽',
+		'Size'
+		=> '大小',
+		'Avail'
+		=> '剩餘',
+		'Used'
+		=> '已用',
+		'Clear'
+		=> '清除',
+		'Sure to clear?'
+		=> '確認要清除嗎?',
+		'Compiling'
+		=> '編譯中',
+		'% Free'
+		=> '% 剩余',
+		'% Used'
+		=> '% 已用',
+		'Hits'
+		=> '命中',
+		'Hits 24H'
+		=> '24H 分布',
+		'Hits/H'
+		=> '命中/H',
+		'Hits/S'
+		=> '命中/S',
+		'Misses'
+		=> '錯過',
+		'Clogs'
+		=> '阻塞',
+		'OOMs'
+		=> '記憶體不足',
+		'Errors'
+		=> '错误',
+		'Protected'
+		=> '保護',
+		'Cached'
+		=> '快取',
+		'Deleted'
+		=> '待刪',
+		'Delete'
+		=> '刪除',
+		'Free Blocks'
+		=> '空閒塊',
+
+		'entry'
+		=> '項目',
+		'Refcount'
+		=> '引用數',
+		'SrcSize'
+		=> '原始檔案大小',
+		'Modify'
+		=> '修改',
+		'device'
+		=> '設備',
+		'inode'
+		=> 'Inode',
+		'hash'
+		=> 'Hash',
+		'Access'
+		=> '存取',
+		'Create'
+		=> '建立',
+		'See also'
+		=> '建議參考',
+		'GC'
+		=> 'GC',
+		'Legends:'
+		=> '图例:',
+		'Used Blocks'
+		=> '已用块',
+		'Free Blocks'
+		=> '未用块',
+		'Total'
+		=> '总共',
+		'Cache'
+		=> '快取',
+		'Caches'
+		=> '快取',
+		'Cached'
+		=> '快取',
+		'php Cached'
+		=> '快取的 php 指令',
+		'php Deleted'
+		=> '待刪 php 指令',
+		'var Cached'
+		=> '快取的變數',
+		'var Deleted'
+		=> '待刪變數',
+		'Statistics'
+		=> '摘要統計',
+		'List PHP'
+		=> '列出PHP',
+		'List Var Data'
+		=> '列變數資料',
+		'XCache %s Administration'
+		=> 'XCache %s 管理頁面',
+		'size'
+		=> '大小',
+		'offset'
+		=> '位置',
+		'Module Info'
+		=> '組元訊息',
+		'Remove Selected'
+		=> '移除所选',
+		'Editing Variable %s'
+		=> '正在编辑变量 %s',
+		''
+		=> '',
+		);
+
Index: /tags/1.3.0-rc1/admin/help-zh-traditional-utf-8.lang.php
===================================================================
--- /tags/1.3.0-rc1/admin/help-zh-traditional-utf-8.lang.php	(revision 623)
+++ /tags/1.3.0-rc1/admin/help-zh-traditional-utf-8.lang.php	(revision 623)
@@ -0,0 +1,33 @@
+<h2><?php echo _T('Cache Legends'); ?></h2>
+<dl>
+<dt><?php echo _T('Slots'); ?>: </dt><dd>Hash 槽個數，對應 php.ini 裡的設置</dd>
+<dt><?php echo _T('Size'); ?>: </dt><dd>共享記憶體區大小，單位：位元</dd>
+<dt><?php echo _T('Avail'); ?>: </dt><dd>可用記憶體，對應共享記憶體區的剩餘記憶體位元數</dd>
+<dt><?php echo _T('% Used'); ?>: </dt><dd>百分比，條狀顯示可用記憶體的比例</dd>
+<dt><?php echo _T('Clear'); ?>: </dt><dd>清除按鈕，點擊按鈕清除對應共享記憶體區的資料</dd>
+<dt><?php echo _T('Compiling'); ?>: </dt><dd>編譯標記，當共享記憶體區正在編譯 php 指令時標記為 "yes"</dd>
+<dt><?php echo _T('Hits'); ?>: </dt><dd>共享記憶體命中次數，命中=從該共享記憶體載入php或者變數</dd>
+<dt><?php echo _T('Misses'); ?>: </dt><dd>共享記憶體錯過次數，錯過=請求的php或者變數並不在該共享記憶體內</dd>
+<dt><?php echo _T('Clogs'); ?>: </dt><dd>編譯阻塞跳過，阻塞=當需該共享記憶體區負責編譯時，其他程序/現成無法存取此共享記憶體. 跳過=XCache 自動判斷阻塞的共享記憶體區自動跳過阻塞等待，直接使用非共享記憶體方式繼續處理請求</dd>
+<dt><?php echo _T('OOMs'); ?>: </dt><dd>記憶體不足次數，顯示需要儲存新資料但是共享記憶體區記憶體不足的次數. 如果出現太頻繁請考慮加大配置中的 xcache.size 或者 xcache.var_size</dd>
+<dt><?php echo _T('Errors'); ?>: </dt><dd>编译错误, 显示您的脚本被编译时出错的次数. 如果您发现这个数字不断增长, 您应该检查什么脚本产生错误. 参考 <a href="http://www.php.net/manual/en/ref.errorfunc.php#ini.error-log">ini.error-log</a> and <a href="http://cn2.php.net/manual/en/ref.errorfunc.php#ini.display-errors">ini.display-errors</a></dd>
+<dt><?php echo _T('Protected'); ?>: </dt><dd>顯示該 Cache 是否支援並啟用 <a href="http://xcache.lighttpd.net/xcache/wiki/ReadonlyProtection">readonly_protection</a></dd>
+<dt><?php echo _T('Cached'); ?>: </dt><dd>共享記憶體於該共享記憶體區的項目個數</dd>
+<dt><?php echo _T('Deleted'); ?>: </dt><dd>共享記憶體區內將要刪除的項目 (已經刪除但是還被某些程序佔用)</dd>
+<dt><?php echo _T('GC'); ?>: </dt><dd>垃圾回收的倒數計時</dd>
+<dt><?php echo _T('Free Blocks'); ?>: </dt><dd>共享記憶體區內的空閒記憶體區塊</dd>
+</dl>
+
+<h2><?php echo _T('List Legends'); ?></h2>
+<dl>
+<dt><?php echo _T('entry'); ?>: </dt><dd>項目名稱或者檔案名稱</dd>
+<dt><?php echo _T('Hits'); ?>: </dt><dd>該項目被命中的次數 (從共享記憶體區載入)</dd>
+<dt><?php echo _T('Refcount'); ?>: </dt><dd>項目依然被其他程序佔用的引用次數</dd>
+<dt><?php echo _T('Size'); ?>: </dt><dd>項目在共享記憶體裡佔用位元數</dd>
+<dt><?php echo _T('SrcSize'); ?>: </dt><dd>原始檔案大小</dd>
+<dt><?php echo _T('Modify'); ?>: </dt><dd>原始檔案最後修改時間</dd>
+<dt><?php echo _T('device'); ?>: </dt><dd>原始檔案所在設備ID</dd>
+<dt><?php echo _T('inode'); ?>: </dt><dd>原始檔案的inode</dd>
+<dt><?php echo _T('Access'); ?>: </dt><dd>最後存取該項目的時間</dd>
+<dt><?php echo _T('Create'); ?>: </dt><dd>該項目被建立於共享內的時間</dd>
+</dl>
Index: /tags/1.3.0-rc1/admin/index.php
===================================================================
--- /tags/1.3.0-rc1/admin/index.php	(revision 604)
+++ /tags/1.3.0-rc1/admin/index.php	(revision 604)
@@ -0,0 +1,3 @@
+<?php
+
+include("xcache.php");
Index: /tags/1.3.0-rc1/admin/help-en.lang.php
===================================================================
--- /tags/1.3.0-rc1/admin/help-en.lang.php	(revision 623)
+++ /tags/1.3.0-rc1/admin/help-en.lang.php	(revision 623)
@@ -0,0 +1,36 @@
+<h2><?php echo _T('Cache Legends'); ?></h2>
+<dl>
+<dt><?php echo _T('Slots'); ?>: </dt><dd>Number of hash slots. the setting from your php.ini</dd>
+<dt><?php echo _T('Size'); ?>: </dt><dd>Cache Size, Size of the cache (or cache chunk), in bytes</dd>
+<dt><?php echo _T('Avail'); ?>: </dt><dd>Available Memory, free memory in bytes of this cache</dd>
+<dt><?php echo _T('% Used'); ?>: </dt><dd>Percent, A bar shows how much memory available in percent, and memory blocks status</dd>
+<dt><?php echo _T('Clear'); ?>: </dt><dd>Clear Button, Press the button to clean this cache</dd>
+<dt><?php echo _T('Compiling'); ?>: </dt><dd>Compiling flag, "yes" if the cache is busy compiling php script</dd>
+<dt><?php echo _T('Hits'); ?>: </dt><dd>Cache Hits, hit=a var/php is loaded from this cache</dd>
+<dt><?php echo _T('Hits/H'); ?>: </dt><dd>Average Hits per Hour. Only last 24 hours is logged</dd>
+<dt><?php echo _T('Hits 24H'); ?>: </dt><dd>Hits 24 Hours. Hits graph of last 24 hours</dd>
+<dt><?php echo _T('Hits/S'); ?>: </dt><dd>Average Hits per Second. Only last 5 seconds is logged</dd>
+<dt><?php echo _T('Misses'); ?>: </dt><dd>Cache Misses, miss=a var/php is requested but not in the cache</dd>
+<dt><?php echo _T('Clogs'); ?>: </dt><dd>Compiling Clogs, clog=compiling is needed but avoided to wait(be blocked) when the cache is busy compiling already</dd>
+<dt><?php echo _T('OOMs'); ?>: </dt><dd>Out Of Memory, how many times a new item should be stored but there isn't enough memory in the cache, think of increasing the xcache.size or xcache.var_size</dd>
+<dt><?php echo _T('Errors'); ?>: </dt><dd>Compiler errors, how many times your script is compiled but failed. You should really check what is happening if you see this value increase. See <a href="http://www.php.net/manual/en/ref.errorfunc.php#ini.error-log">ini.error-log</a> and <a href="http://cn2.php.net/manual/en/ref.errorfunc.php#ini.display-errors">ini.display-errors</a></dd>
+<dt><?php echo _T('Protected'); ?>: </dt><dd>Whether <a href="http://xcache.lighttpd.net/wiki/ReadonlyProtection">readonly_protection</a> is available and enable on this cache</dd>
+<dt><?php echo _T('Cached'); ?>: </dt><dd>Number of entries stored in this cache</dd>
+<dt><?php echo _T('Deleted'); ?>: </dt><dd>Number of entries is pending in delete list (expired but referenced)</dd>
+<dt><?php echo _T('GC'); ?>: </dt><dd>Seconds count down of Garbage Collection</dd>
+<dt><?php echo _T('Free Blocks'); ?>: </dt><dd>Free blocks list in the specified cache</dd>
+</dl>
+
+<h2><?php echo _T('List Legends'); ?></h2>
+<dl>
+<dt><?php echo _T('entry'); ?>: </dt><dd>The entry name or filename</dd>
+<dt><?php echo _T('Hits'); ?>: </dt><dd>Times this entry is hit (loaded from this cache)</dd>
+<dt><?php echo _T('Refcount'); ?>: </dt><dd>Reference count this entry is holded by a php request</dd>
+<dt><?php echo _T('Size'); ?>: </dt><dd>Size in bytes of this entry in the cache</dd>
+<dt><?php echo _T('SrcSize'); ?>: </dt><dd>Size of the source file</dd>
+<dt><?php echo _T('Modify'); ?>: </dt><dd>Last modified time of the source file</dd>
+<dt><?php echo _T('device'); ?>: </dt><dd>device number of the source file</dd>
+<dt><?php echo _T('inode'); ?>: </dt><dd>inode number of the source file</dd>
+<dt><?php echo _T('Access'); ?>: </dt><dd>Last access time of the cached entry</dd>
+<dt><?php echo _T('Create'); ?>: </dt><dd>The time when this entry is stored</dd>
+</dl>
Index: /tags/1.3.0-rc1/admin/common-en.lang.php
===================================================================
--- /tags/1.3.0-rc1/admin/common-en.lang.php	(revision 604)
+++ /tags/1.3.0-rc1/admin/common-en.lang.php	(revision 604)
@@ -0,0 +1,5 @@
+<?php
+
+$GLOBALS['show_todo_strings'] = false;
+
+?>
Index: /tags/1.3.0-rc1/admin/common-zh-simplified-utf-8.lang.php
===================================================================
--- /tags/1.3.0-rc1/admin/common-zh-simplified-utf-8.lang.php	(revision 623)
+++ /tags/1.3.0-rc1/admin/common-zh-simplified-utf-8.lang.php	(revision 623)
@@ -0,0 +1,122 @@
+<?php
+
+$strings = array(
+		'Cache Legends'
+		=> 'Cache 帮助',
+		'List Legends'
+		=> 'List 帮助',
+		'XCache Administration Help'
+		=> 'XCache 管理页面帮助信息',
+		'Help'
+		=> '帮助',
+		'Slots'
+		=> '槽',
+		'Size'
+		=> '大小',
+		'Avail'
+		=> '剩余',
+		'Used'
+		=> '已用',
+		'Clear'
+		=> '清除',
+		'Sure to clear?'
+		=> '确认要清除吗?',
+		'Compiling'
+		=> '编译中',
+		'% Free'
+		=> '% 剩余',
+		'% Used'
+		=> '% 已用',
+		'Hits'
+		=> '命中',
+		'Hits 24H'
+		=> '24H 分布',
+		'Hits/H'
+		=> '命中/H',
+		'Hits/S'
+		=> '命中/S',
+		'Misses'
+		=> '错过',
+		'Clogs'
+		=> '阻塞',
+		'OOMs'
+		=> '内存不足',
+		'Errors'
+		=> '错误',
+		'Protected'
+		=> '保护',
+		'Cached'
+		=> '缓存',
+		'Deleted'
+		=> '待删',
+		'Delete'
+		=> '删除',
+		'Free Blocks'
+		=> '空闲块',
+
+		'entry'
+		=> '项目',
+		'Refcount'
+		=> '引用数',
+		'SrcSize'
+		=> '源大小',
+		'Modify'
+		=> '修改',
+		'device'
+		=> '设备',
+		'inode'
+		=> 'Inode',
+		'hash'
+		=> 'Hash',
+		'Access'
+		=> '访问',
+		'Create'
+		=> '创建',
+		'See also'
+		=> '建议参考',
+		'GC'
+		=> 'GC',
+		'Legends:'
+		=> '图例:',
+		'Used Blocks'
+		=> '已用块',
+		'Free Blocks'
+		=> '未用块',
+		'Total'
+		=> '总共',
+		'Cache'
+		=> '缓冲区',
+		'Caches'
+		=> '缓冲区',
+		'Cached'
+		=> '缓冲',
+		'php Cached'
+		=> '缓冲的 php 脚本',
+		'php Deleted'
+		=> '待删 php 脚本',
+		'var Cached'
+		=> '缓冲的变量',
+		'var Deleted'
+		=> '待删变量',
+		'Statistics'
+		=> '摘要统计',
+		'List PHP'
+		=> '列出PHP',
+		'List Var Data'
+		=> '列变量数据',
+		'XCache %s Administration'
+		=> 'XCache %s 管理页面',
+		'size'
+		=> '大小',
+		'offset'
+		=> '位置',
+		'Module Info'
+		=> '模块信息',
+		'Remove Selected'
+		=> '删除所选',
+		'Editing Variable %s'
+		=> '正在编辑变量 %s',
+		''
+		=> '',
+		);
+
Index: /tags/1.3.0-rc1/admin/help-zh-simplified-utf-8.lang.php
===================================================================
--- /tags/1.3.0-rc1/admin/help-zh-simplified-utf-8.lang.php	(revision 623)
+++ /tags/1.3.0-rc1/admin/help-zh-simplified-utf-8.lang.php	(revision 623)
@@ -0,0 +1,36 @@
+<h2><?php echo _T('Cache Legends'); ?></h2>
+<dl>
+<dt><?php echo _T('Slots'); ?>: </dt><dd>Hash 槽个数, 对应 php.ini 里的设置</dd>
+<dt><?php echo _T('Size'); ?>: </dt><dd>共享内存区大小, 单位: 字节</dd>
+<dt><?php echo _T('Avail'); ?>: </dt><dd>可用内存, 对应共享内存区的剩余内存字节数</dd>
+<dt><?php echo _T('% Used'); ?>: </dt><dd>百分比, 条状显示可用内存的比例, 以及显示分配块状态</dd>
+<dt><?php echo _T('Clear'); ?>: </dt><dd>清除按钮, 点击按钮清除对应共享内存区的数据</dd>
+<dt><?php echo _T('Compiling'); ?>: </dt><dd>编译标记, 当共享内存区正在编译 php 脚本时标记为 "yes"</dd>
+<dt><?php echo _T('Hits'); ?>: </dt><dd>共享内存命中次数, 命中=从该共享内存载入php或者变量</dd>
+<dt><?php echo _T('Hits/H'); ?>: </dt><dd>每小时命中次数. 只统计最后 24 小时</dd>
+<dt><?php echo _T('Hits 24H'); ?>: </dt><dd>24 小时命中分布图. 图表现是最后 24 小时的命中次数</dd>
+<dt><?php echo _T('Hits/S'); ?>: </dt><dd>每秒命中次数. 只统计最后 5 秒</dd>
+<dt><?php echo _T('Misses'); ?>: </dt><dd>共享内存错过次数, 错过=请求的php或者变量并不在该共享内存内</dd>
+<dt><?php echo _T('Clogs'); ?>: </dt><dd>编译阻塞跳过, 阻塞=当需该共享内存区负责编译时, 其他进程/现成无法访问此共享内存. 跳过=XCache 自动判断阻塞的共享内存区自动跳过阻塞等待, 直接使用非共享内存方式继续处理请求</dd>
+<dt><?php echo _T('OOMs'); ?>: </dt><dd>内存不足次数, 显示需要存储新数据但是共享内存区内存不足的次数. 如果出现太频繁请考虑加大配置中的 xcache.size 或者 xcache.var_size</dd>
+<dt><?php echo _T('Errors'); ?>: </dt><dd>编译错误, 显示您的脚本被编译时出错的次数. 如果您发现这个数字不断增长, 您应该检查什么脚本产生错误. 参考 <a href="http://www.php.net/manual/en/ref.errorfunc.php#ini.error-log">ini.error-log</a> and <a href="http://cn2.php.net/manual/en/ref.errorfunc.php#ini.display-errors">ini.display-errors</a></dd>
+<dt><?php echo _T('Protected'); ?>: </dt><dd>显示该 Cache 是否支持并启用 <a href="http://xcache.lighttpd.net/xcache/wiki/ReadonlyProtection">readonly_protection</a></dd>
+<dt><?php echo _T('Cached'); ?>: </dt><dd>共享内存于该共享内存区的项目条数</dd>
+<dt><?php echo _T('Deleted'); ?>: </dt><dd>共享内存区内将要删除的项目 (已经删除但是还被某些进程占用)</dd>
+<dt><?php echo _T('GC'); ?>: </dt><dd>垃圾回收的倒计时</dd>
+<dt><?php echo _T('Free Blocks'); ?>: </dt><dd>共享内存区内的空闲内存块</dd>
+</dl>
+
+<h2><?php echo _T('List Legends'); ?></h2>
+<dl>
+<dt><?php echo _T('entry'); ?>: </dt><dd>项目名或者文件名</dd>
+<dt><?php echo _T('Hits'); ?>: </dt><dd>该项目被命中的次数 (从共享内存区载入)</dd>
+<dt><?php echo _T('Refcount'); ?>: </dt><dd>项目依然被其他进程占据的引用次数</dd>
+<dt><?php echo _T('Size'); ?>: </dt><dd>项目在共享内存里占用字节数</dd>
+<dt><?php echo _T('SrcSize'); ?>: </dt><dd>源文件大小</dd>
+<dt><?php echo _T('Modify'); ?>: </dt><dd>源文件最后修改时间</dd>
+<dt><?php echo _T('device'); ?>: </dt><dd>源文件所在设备ID</dd>
+<dt><?php echo _T('inode'); ?>: </dt><dd>源文件的inode</dd>
+<dt><?php echo _T('Access'); ?>: </dt><dd>最后访问该项目的时间</dd>
+<dt><?php echo _T('Create'); ?>: </dt><dd>该项目被创建于共享内的时间</dd>
+</dl>
Index: /tags/1.3.0-rc1/prepare.devel
===================================================================
--- /tags/1.3.0-rc1/prepare.devel	(revision 626)
+++ /tags/1.3.0-rc1/prepare.devel	(revision 626)
@@ -0,0 +1,100 @@
+#! /bin/bash
+SELF="$0"
+
+if test -e prepare.devel.inc ; then
+	. prepare.devel.inc
+else
+	echo prepare.devel.inc is required, see prepare.devel.inc.example >&2
+	exit
+fi
+
+CTAGS=`which ctags 2>/dev/null || which exuberant-ctags 2>/dev/null `
+AWK=`which gawk 2>/dev/null || which awk 2>/dev/null `
+
+make_all() {
+	make_opcode_spec_def.h
+	make_const_string
+	test -e tags && echo tags exists, skipping. use \""$0" tags\" to rebuild || make_tags
+}
+
+make_clean() {
+ 	make_clean_const_string
+	echo "*" rm -f tags opcode_spec_def.h
+	rm -f tags opcode_spec_def.h
+}
+
+make_const_string() {
+	make_const_string_opcodes_php4.x.h
+	make_const_string_opcodes_php5.0.h
+	make_const_string_opcodes_php5.1.h
+	make_const_string_opcodes_php6.x.h
+}
+
+make_clean_const_string() {
+	echo "*" rm -f const_string_opcodes_php*.h{,.tmp}
+	rm -f const_string_opcodes_php*.h
+}
+
+make_const_string_opcodes_php4.x.h() {
+	precheck const_string_opcodes_php4.x.h "${PHP4_x_DIR}/Zend/zend_compile.h" && "$AWK" -f ./mkopcode.awk < "$I" > "$O.tmp" && mv "$O.tmp" "$O"
+}
+
+make_const_string_opcodes_php5.0.h() {
+	precheck const_string_opcodes_php5.0.h "${PHP5_0_DIR}/Zend/zend_compile.h" && "$AWK" -f ./mkopcode.awk < "$I" > "$O.tmp" && mv "$O.tmp" "$O"
+}
+
+make_const_string_opcodes_php5.1.h() {
+	precheck const_string_opcodes_php5.1.h "${PHP5_1_DIR}/Zend/zend_vm_def.h"  && "$AWK" -f ./mkopcode.awk < "$I" > "$O.tmp" && mv "$O.tmp" "$O"
+}
+
+make_const_string_opcodes_php6.x.h() {
+	precheck const_string_opcodes_php6.x.h "${PHP6_x_DIR}/Zend/zend_vm_def.h"  && "$AWK" -f ./mkopcode.awk < "$I" > "$O.tmp" && mv "$O.tmp" "$O"
+}
+
+make_opcode_spec_def.h() {
+	precheck "opcode_spec_def.h" "${EA_DIR}/opcodes.c" && "$AWK" -f ./mkopcode_spec.awk < "$I" > "$O"
+}
+
+make_tags() {
+	if test -z "$CTAGS" ; then
+		echo tool ctags not found, skip building tags >&2
+		return
+	fi
+
+	if test -d "${PHP_DEVEL_DIR}" ; then
+		echo "* Making tags with ${PHP_DEVEL_DIR}"
+		"$CTAGS" -R . "${PHP_DEVEL_DIR}/main" "${PHP_DEVEL_DIR}/Zend" "${PHP_DEVEL_DIR}/TSRM" "${PHP_DEVEL_DIR}/ext/standard"
+	else
+		echo "* Making tags without php source files"
+		"$CTAGS" -R .
+	fi
+}
+
+error() {
+	echo "$@" >&2
+}
+
+precheck() {
+	if test -e "$2" ; then :; else
+		error X skipping "$1" because "$2" not found
+		return 1
+	fi
+	if test "$1" -ot "$2" ; then :; else
+		echo O "$1" is up to date.
+		return 1
+	fi
+	O="$1"
+	I="$2"
+	echo "* Making $1 from $2"
+	return 0
+}
+
+if test -z "$1" ; then
+	make_all
+else
+	while ! test -z "$1" ; do
+		eval "make_$1"
+		shift
+	done
+fi
+
Index: /tags/1.3.0-rc1/README
===================================================================
--- /tags/1.3.0-rc1/README	(revision 459)
+++ /tags/1.3.0-rc1/README	(revision 459)
@@ -0,0 +1,1 @@
+Please check http://xcache.lighttpd.net/ and http://forum.lighttpd.net/forum/4/ for help
Index: /tags/1.3.0-rc1/.vimrc
===================================================================
--- /tags/1.3.0-rc1/.vimrc	(revision 604)
+++ /tags/1.3.0-rc1/.vimrc	(revision 604)
@@ -0,0 +1,3 @@
+set noexpandtab
+au FileType m4 setlocal ts=2 sw=2 fdm=marker noexpandtab
+au FileType c setlocal ts=4 sw=4 fdm=marker noexpandtab
Index: /tags/1.3.0-rc1/const_string_opcodes_php5.0.h
===================================================================
--- /tags/1.3.0-rc1/const_string_opcodes_php5.0.h	(revision 394)
+++ /tags/1.3.0-rc1/const_string_opcodes_php5.0.h	(revision 394)
@@ -0,0 +1,153 @@
+/* size = 149 */
+static const char *const xc_opcode_names[] = {
+/* 0 */	"NOP",
+/* 1 */	"ADD",
+/* 2 */	"SUB",
+/* 3 */	"MUL",
+/* 4 */	"DIV",
+/* 5 */	"MOD",
+/* 6 */	"SL",
+/* 7 */	"SR",
+/* 8 */	"CONCAT",
+/* 9 */	"BW_OR",
+/* 10 */	"BW_AND",
+/* 11 */	"BW_XOR",
+/* 12 */	"BW_NOT",
+/* 13 */	"BOOL_NOT",
+/* 14 */	"BOOL_XOR",
+/* 15 */	"IS_IDENTICAL",
+/* 16 */	"IS_NOT_IDENTICAL",
+/* 17 */	"IS_EQUAL",
+/* 18 */	"IS_NOT_EQUAL",
+/* 19 */	"IS_SMALLER",
+/* 20 */	"IS_SMALLER_OR_EQUAL",
+/* 21 */	"CAST",
+/* 22 */	"QM_ASSIGN",
+/* 23 */	"ASSIGN_ADD",
+/* 24 */	"ASSIGN_SUB",
+/* 25 */	"ASSIGN_MUL",
+/* 26 */	"ASSIGN_DIV",
+/* 27 */	"ASSIGN_MOD",
+/* 28 */	"ASSIGN_SL",
+/* 29 */	"ASSIGN_SR",
+/* 30 */	"ASSIGN_CONCAT",
+/* 31 */	"ASSIGN_BW_OR",
+/* 32 */	"ASSIGN_BW_AND",
+/* 33 */	"ASSIGN_BW_XOR",
+/* 34 */	"PRE_INC",
+/* 35 */	"PRE_DEC",
+/* 36 */	"POST_INC",
+/* 37 */	"POST_DEC",
+/* 38 */	"ASSIGN",
+/* 39 */	"ASSIGN_REF",
+/* 40 */	"ECHO",
+/* 41 */	"PRINT",
+/* 42 */	"JMP",
+/* 43 */	"JMPZ",
+/* 44 */	"JMPNZ",
+/* 45 */	"JMPZNZ",
+/* 46 */	"JMPZ_EX",
+/* 47 */	"JMPNZ_EX",
+/* 48 */	"CASE",
+/* 49 */	"SWITCH_FREE",
+/* 50 */	"BRK",
+/* 51 */	"CONT",
+/* 52 */	"BOOL",
+/* 53 */	"INIT_STRING",
+/* 54 */	"ADD_CHAR",
+/* 55 */	"ADD_STRING",
+/* 56 */	"ADD_VAR",
+/* 57 */	"BEGIN_SILENCE",
+/* 58 */	"END_SILENCE",
+/* 59 */	"INIT_FCALL_BY_NAME",
+/* 60 */	"DO_FCALL",
+/* 61 */	"DO_FCALL_BY_NAME",
+/* 62 */	"RETURN",
+/* 63 */	"RECV",
+/* 64 */	"RECV_INIT",
+/* 65 */	"SEND_VAL",
+/* 66 */	"SEND_VAR",
+/* 67 */	"SEND_REF",
+/* 68 */	"NEW",
+/* 69 */	"JMP_NO_CTOR",
+/* 70 */	"FREE",
+/* 71 */	"INIT_ARRAY",
+/* 72 */	"ADD_ARRAY_ELEMENT",
+/* 73 */	"INCLUDE_OR_EVAL",
+/* 74 */	"UNSET_VAR",
+/* 75 */	"UNSET_DIM_OBJ",
+/* 76 */	"UNDEF",
+/* 77 */	"FE_RESET",
+/* 78 */	"FE_FETCH",
+/* 79 */	"EXIT",
+/* 80 */	"FETCH_R",
+/* 81 */	"FETCH_DIM_R",
+/* 82 */	"FETCH_OBJ_R",
+/* 83 */	"FETCH_W",
+/* 84 */	"FETCH_DIM_W",
+/* 85 */	"FETCH_OBJ_W",
+/* 86 */	"FETCH_RW",
+/* 87 */	"FETCH_DIM_RW",
+/* 88 */	"FETCH_OBJ_RW",
+/* 89 */	"FETCH_IS",
+/* 90 */	"FETCH_DIM_IS",
+/* 91 */	"FETCH_OBJ_IS",
+/* 92 */	"FETCH_FUNC_ARG",
+/* 93 */	"FETCH_DIM_FUNC_ARG",
+/* 94 */	"FETCH_OBJ_FUNC_ARG",
+/* 95 */	"FETCH_UNSET",
+/* 96 */	"FETCH_DIM_UNSET",
+/* 97 */	"FETCH_OBJ_UNSET",
+/* 98 */	"FETCH_DIM_TMP_VAR",
+/* 99 */	"FETCH_CONSTANT",
+/* 100 */	"UNDEF",
+/* 101 */	"EXT_STMT",
+/* 102 */	"EXT_FCALL_BEGIN",
+/* 103 */	"EXT_FCALL_END",
+/* 104 */	"EXT_NOP",
+/* 105 */	"TICKS",
+/* 106 */	"SEND_VAR_NO_REF",
+/* 107 */	"CATCH",
+/* 108 */	"THROW",
+/* 109 */	"FETCH_CLASS",
+/* 110 */	"CLONE",
+/* 111 */	"INIT_CTOR_CALL",
+/* 112 */	"INIT_METHOD_CALL",
+/* 113 */	"INIT_STATIC_METHOD_CALL",
+/* 114 */	"ISSET_ISEMPTY_VAR",
+/* 115 */	"ISSET_ISEMPTY_DIM_OBJ",
+/* 116 */	"UNDEF",
+/* 117 */	"UNDEF",
+/* 118 */	"UNDEF",
+/* 119 */	"UNDEF",
+/* 120 */	"UNDEF",
+/* 121 */	"UNDEF",
+/* 122 */	"UNDEF",
+/* 123 */	"UNDEF",
+/* 124 */	"UNDEF",
+/* 125 */	"UNDEF",
+/* 126 */	"UNDEF",
+/* 127 */	"UNDEF",
+/* 128 */	"UNDEF",
+/* 129 */	"UNDEF",
+/* 130 */	"UNDEF",
+/* 131 */	"UNDEF",
+/* 132 */	"PRE_INC_OBJ",
+/* 133 */	"PRE_DEC_OBJ",
+/* 134 */	"POST_INC_OBJ",
+/* 135 */	"POST_DEC_OBJ",
+/* 136 */	"ASSIGN_OBJ",
+/* 137 */	"OP_DATA",
+/* 138 */	"INSTANCEOF",
+/* 139 */	"DECLARE_CLASS",
+/* 140 */	"DECLARE_INHERITED_CLASS",
+/* 141 */	"DECLARE_FUNCTION",
+/* 142 */	"RAISE_ABSTRACT_ERROR",
+/* 143 */	"UNDEF",
+/* 144 */	"ADD_INTERFACE",
+/* 145 */	"UNDEF",
+/* 146 */	"VERIFY_ABSTRACT_CLASS",
+/* 147 */	"ASSIGN_DIM",
+/* 148 */	"ISSET_ISEMPTY_PROP_OBJ",
+/* 149 */	"HANDLE_EXCEPTION"
+};
Index: /tags/1.3.0-rc1/mkstructinfo.awk
===================================================================
--- /tags/1.3.0-rc1/mkstructinfo.awk	(revision 394)
+++ /tags/1.3.0-rc1/mkstructinfo.awk	(revision 394)
@@ -0,0 +1,164 @@
+#! /usr/bin/awk -f
+# vim:ts=4:sw=4
+BEGIN {
+	brace = 0;
+	incomment = 0;
+	buffer_len = 0;
+}
+
+# multiline comment handling
+{
+	# removes one line comment
+	gsub(/\/\*(.+?)\*\//, " ");
+}
+/\*\// {
+	if (incomment) {
+		sub(/.*\*\//, "");
+		incomment = 0;
+	}
+}
+incomment {
+	next;
+}
+/\/\*/ {
+	sub(/\/\*.*/, "");
+	incomment = 1;
+	# fall through
+}
+
+# skip file/line mark here to be faster
+/^#/ {
+	next;
+}
+
+/^}.*;/ {
+	if (instruct) {
+		sub(";", "");
+		if (instruct == 1 && $2) {
+			instruct = $2;
+		}
+		if (instruct in typedefs) {
+			instruct = typedefs[instruct];
+		}
+		sizeinfo = "";
+		elms = "";
+		for (i = 0; i in buffer; i ++) {
+			if (i) {
+				sizeinfo = sizeinfo " + ";
+			}
+			sizeinfo = sizeinfo "sizeof(((" instruct "*)NULL)->" buffer[i] ")";
+
+			if (i == 0) {
+				elms = buffer[i];
+			}
+			else {
+				elms = elms "," buffer[i];
+			}
+		}
+		printf "define(`ELEMENTSOF_%s', `%s')\n", instruct, elms;
+		printf "define(`COUNTOF_%s', `%s')\n", instruct, i;
+		printf "define(`SIZEOF_%s', `(  %s  )')\n", instruct, sizeinfo;
+		print "\n";
+		for (i in buffer) {
+			delete buffer[i];
+		}
+		buffer_len = 0;
+		instruct = 0;
+	}
+	next;
+}
+
+/.\{/ {
+	brace = brace + 1;
+}
+/.}/ {
+	brace = brace - 1;
+}
+
+{
+	if (brace == 1 && instruct) {
+		gsub(/(^[\t ]+|[\t ]+$)/, ""); # trim whitespaces
+		sub(/.*[{}]/, "");
+		gsub(/\[[^\]]+\]/, ""); # ignore [...]
+		gsub(/:[0-9]+/, ""); # ignore struct bit
+		if (match($0, /^[^(]*\([ ]*\*([^)]+)\)/)) {
+			sub(/ +/, "")
+			sub(/^[^(]*\(\*/, "");
+			sub(/\).*/, "");
+			# function pointer
+			buffer[buffer_len] = $0;
+			buffer_len ++;
+		}
+		else {
+			# process normal variables
+
+			# ignore any ()s
+			while (gsub(/(\([^)]*\))/, "")) {
+			}
+			if (match($0, /[()]/)) {
+				next;
+			}
+			# unsigned int *a,  b; int c;
+			gsub(/[*]/, " ");
+			# unsigned int a,  b; int c;
+			gsub(/ +/, " ");
+			# unsigned int a, b; int c;
+			gsub(/ *[,;]/, ";");
+			# unsigned int a; b; int c;
+			if (!match($0, /;/)) {
+				next;
+			}
+			# print "=DEBUG=" $0 "==";
+			split($0, chunks, ";");
+			# [unsigned int a, b, c]
+
+			for (i = 1; i in chunks; i ++) {
+				if (chunks[i] == "") {
+					delete chunks[i];
+					continue;
+				}
+				split(chunks[i], pieces, " ");
+				# [unsigned, int, a]
+				# [b]
+				# [c]
+
+				last_piece = "";
+				for (j = 1; j in pieces; j ++) {
+					last_piece = pieces[j];
+					delete pieces[j];
+				}
+				if (last_piece == "") {
+					# print "=ERROR=" chunks[i] "==";
+					delete chunks[i];
+					continue;
+				}
+				# a
+				# b
+				# c
+
+				buffer[buffer_len] = last_piece;
+				buffer_len ++;
+				delete chunks[i]
+			}
+			last_piece = "";
+		}
+		next;
+	}
+}
+
+/^typedef struct [^{]*;/ {
+	sub(";", "");
+	typedefs[$3] = $4;
+	next;
+}
+/^typedef struct .*\{[^}]*$/ {
+	brace = 1;
+	instruct = 1;
+	next;
+}
+
+/^struct .*\{/ {
+	instruct = $2;
+	brace = 1;
+	next;
+}
Index: /tags/1.3.0-rc1/mmap.c
===================================================================
--- /tags/1.3.0-rc1/mmap.c	(revision 625)
+++ /tags/1.3.0-rc1/mmap.c	(revision 625)
@@ -0,0 +1,310 @@
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* mmap */
+#ifdef ZEND_WIN32
+#	define ftruncate chsize
+#	define getuid() 0
+#	include <process.h>
+#	define XCacheCreateFileMapping(size, perm, name) \
+		CreateFileMapping(INVALID_HANDLE_VALUE, NULL, perm, (sizeof(xc_shmsize_t) > 4) ? size >> 32 : 0, size & 0xffffffff, name)
+#	define XCACHE_MAP_FAILED NULL
+#	define munmap(p, s) UnmapViewOfFile(p)
+#else
+#	include <unistd.h>
+/* make sure to mark(change) it to NULL to keep consistent */
+#	define XCACHE_MAP_FAILED MAP_FAILED
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifndef ZEND_WIN32
+#include <sys/mman.h>
+#endif
+
+#include "php.h"
+#define XC_SHM_IMPL _xc_mmap_shm_t
+#include "xc_shm.h"
+#include "utils.h"
+
+#ifndef max
+#define max(a, b) ((a) < (b) ? (b) : (a))
+#endif
+
+/* {{{ xc_shm_t */
+struct _xc_mmap_shm_t {
+	xc_shm_handlers_t *handlers;
+	void *ptr;
+	void *ptr_ro;
+	long  diff;
+	xc_shmsize_t size;
+	char *name;
+	int newfile;
+	xc_shmsize_t memoffset;
+#ifdef ZEND_WIN32
+	HANDLE hmap;
+	HANDLE hmap_ro;
+#endif
+};
+
+/* }}} */
+#define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0)
+#define PTR_ADD(ptr, v) (((char *) (ptr)) + (v))
+#define PTR_SUB(ptr, v) (((char *) (ptr)) - (v))
+
+static XC_SHM_CAN_READONLY(xc_mmap_can_readonly) /* {{{ */
+{
+	return shm->ptr_ro != NULL;
+}
+/* }}} */
+static XC_SHM_IS_READWRITE(xc_mmap_is_readwrite) /* {{{ */
+{
+	return p >= shm->ptr && (char *)p < (char *)shm->ptr + shm->size;
+}
+/* }}} */
+static XC_SHM_IS_READONLY(xc_mmap_is_readonly) /* {{{ */
+{
+	return xc_mmap_can_readonly(shm) && p >= shm->ptr_ro && (char *)p < (char *)shm->ptr_ro + shm->size;
+}
+/* }}} */
+static XC_SHM_TO_READWRITE(xc_mmap_to_readwrite) /* {{{ */
+{
+	if (shm->diff) {
+		assert(xc_mmap_is_readonly(shm, p));
+		p = PTR_SUB(p, shm->diff);
+	}
+	assert(xc_mmap_is_readwrite(shm, p));
+	return p;
+}
+/* }}} */
+static XC_SHM_TO_READONLY(xc_mmap_to_readonly) /* {{{ */
+{
+	assert(xc_mmap_is_readwrite(shm, p));
+	if (shm->diff) {
+		p = PTR_ADD(p, shm->diff);
+		assert(xc_mmap_is_readonly(shm, p));
+	}
+	return p;
+}
+/* }}} */
+
+static XC_SHM_DESTROY(xc_mmap_destroy) /* {{{ */
+{
+	if (shm->ptr_ro) {
+		munmap(shm->ptr_ro, shm->size);
+		/*
+		shm->ptr_ro = NULL;
+		*/
+	}
+	if (shm->ptr) {
+		/* shm->size depends on shm->ptr */
+		munmap(shm->ptr, shm->size);
+		/*
+		shm->ptr = NULL;
+		*/
+	}
+#ifdef ZEND_WIN32
+	if (shm->hmap) {
+		CloseHandle(shm->hmap);
+	}
+	if (shm->hmap_ro) {
+		CloseHandle(shm->hmap_ro);
+	}
+#endif
+
+	if (shm->name) {
+#ifdef __CYGWIN__
+		if (shm->newfile) {
+			unlink(shm->name);
+		}
+#endif
+		free(shm->name);
+	}
+	/*
+	shm->size = NULL;
+	shm->diff = 0;
+	*/
+
+	free(shm);
+	return;
+}
+/* }}} */
+static XC_SHM_INIT(xc_mmap_init) /* {{{ */
+{
+#ifdef ZEND_WIN32
+#	define TMP_PATH "XCache"
+#else
+#	define TMP_PATH "/tmp/XCache"
+#endif
+	xc_shm_t *shm = NULL;
+	int fd = -1;
+	int ro_ok;
+	volatile void *romem;
+	char tmpname[sizeof(TMP_PATH) - 1 + 100];
+	const char *errstr = NULL;
+	const char *path = (const char *) arg1;
+
+	CHECK(shm = calloc(1, sizeof(xc_shm_t)), "shm OOM");
+	shm->size = size;
+
+	if (path == NULL || !path[0]) {
+		static int inc = 0;
+		snprintf(tmpname, sizeof(tmpname) - 1, "%s.%d.%d.%d.%d", TMP_PATH, (int) getuid(), (int) getpid(), inc ++, rand());
+		path = tmpname;
+	}
+#ifdef ZEND_WIN32
+	else {
+		static int inc2 = 0;
+		snprintf(tmpname, sizeof(tmpname) - 1, "%s.%d.%d.%d.%d", path, (int) getuid(), (int) getpid(), inc2 ++, rand());
+		path = tmpname;
+	}
+#endif
+
+	shm->name = strdup(path);
+
+#ifndef ZEND_WIN32
+#	define XCACHE_MMAP_PERMISSION (S_IRUSR | S_IWUSR)
+	fd = open(shm->name, O_RDWR, XCACHE_MMAP_PERMISSION);
+	if (fd == -1) {
+		/* do not create file in /dev */
+		if (strncmp(shm->name, "/dev", 4) == 0) {
+			perror(shm->name);
+			errstr = "Cannot open file set by xcache.mmap_path, check the xcache.size/var_size against system limitation";
+			goto err;
+		}
+		fd = open(shm->name, O_CREAT | O_RDWR, XCACHE_MMAP_PERMISSION);
+		shm->newfile = 1;
+		if (fd == -1) {
+			perror(shm->name);
+			errstr = "Cannot open or create file set by xcache.mmap_path, check the path permission or check xcache.size/var_size against system limitation";
+			goto err;
+		}
+	}
+	ftruncate(fd, size);
+#endif
+
+#ifdef ZEND_WIN32
+	shm->hmap = XCacheCreateFileMapping(size, PAGE_READWRITE, shm->name);
+	shm->ptr = (LPSTR) MapViewOfFile(shm->hmap, FILE_MAP_WRITE, 0, 0, 0);
+#else
+	shm->ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+#endif
+
+	if (shm->ptr == XCACHE_MAP_FAILED) {
+		perror(shm->name);
+		errstr = "Failed creating file mapping";
+		shm->ptr = NULL;
+		goto err;
+	}
+
+	/* {{{ readonly protection, mmap it readonly and check if ptr_ro works */
+	if (readonly_protection) {
+		ro_ok = 0;
+
+#ifdef ZEND_WIN32
+		shm->hmap_ro = XCacheCreateFileMapping(size, PAGE_READONLY, shm->name);
+		shm->ptr_ro = (LPSTR) MapViewOfFile(shm->hmap_ro, FILE_MAP_READ, 0, 0, 0);
+#else
+		shm->ptr_ro = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+#endif
+		if (shm->ptr_ro == XCACHE_MAP_FAILED) {
+			shm->ptr_ro = NULL;
+		}
+		romem = shm->ptr_ro;
+
+		do {
+			if (romem == NULL || romem == shm->ptr) {
+				break;
+			}
+			*(char *)shm->ptr = 1;
+			if (*(char *)romem != 1) {
+				break;
+			}
+			*(char *)shm->ptr = 2;
+			if (*(char *)romem != 2) {
+				break;
+			}
+			ro_ok = 1;
+		} while (0);
+
+		if (ro_ok) {
+			shm->diff = PTR_SUB(shm->ptr_ro, (char *) shm->ptr);
+			/* no overlap */
+			assert(abs(shm->diff) >= size);
+		}
+		else {
+			if (shm->ptr_ro) {
+				munmap(shm->ptr_ro, size);
+			}
+#ifdef ZEND_WIN32
+			if (shm->hmap_ro) {
+				CloseHandle(shm->hmap_ro);
+			}
+#endif
+			shm->ptr_ro = NULL;
+			shm->diff = 0;
+		}
+	}
+
+	/* }}} */
+
+	close(fd);
+#ifndef __CYGWIN__
+	if (shm->newfile) {
+		unlink(shm->name);
+	}
+#endif
+
+	return shm;
+
+err:
+	if (fd != -1) {
+		close(fd);
+	}
+	if (shm) {
+		xc_mmap_destroy(shm);
+	}
+	if (errstr) {
+		fprintf(stderr, "%s\n", errstr);
+		zend_error(E_ERROR, "%s", errstr);
+	}
+	return NULL;
+}
+/* }}} */
+
+static XC_SHM_MEMINIT(xc_mmap_meminit) /* {{{ */
+{
+	xc_mem_t *mem;
+	if (shm->memoffset + size > shm->size) {
+		zend_error(E_ERROR, "XCache: internal error at %s#%d", __FILE__, __LINE__);
+		return NULL;
+	}
+	mem = (xc_mem_t *) PTR_ADD(shm->ptr, shm->memoffset);
+	shm->memoffset += size;
+	mem->handlers = shm->handlers->memhandlers;
+	mem->handlers->init(shm, mem, size);
+	return mem;
+}
+/* }}} */
+static XC_SHM_MEMDESTROY(xc_mmap_memdestroy) /* {{{ */
+{
+}
+/* }}} */
+
+static xc_shm_handlers_t xc_shm_mmap_handlers = XC_SHM_HANDLERS(mmap);
+void xc_shm_mmap_register() /* {{{ */
+{
+	CHECK(xc_shm_mmap_handlers.memhandlers = xc_mem_scheme_find("mem"), "cannot find mem handlers");
+	if (xc_shm_scheme_register("mmap", &xc_shm_mmap_handlers) == 0) {
+		zend_error(E_ERROR, "XCache: failed to register mmap shm_scheme");
+	}
+err:
+	return;
+}
+/* }}} */
Index: /tags/1.3.0-rc1/processor/string.m4
===================================================================
--- /tags/1.3.0-rc1/processor/string.m4	(revision 646)
+++ /tags/1.3.0-rc1/processor/string.m4	(revision 646)
@@ -0,0 +1,121 @@
+
+dnl {{{ PROC_STRING_N_EX(1:dst, 2:src, 3:size, 4:name, 5:type=char)
+define(`PROC_STRING_N_EX', `
+	pushdef(`STRTYPE', `ifelse(`$5',,`char',`$5')')
+	pushdef(`PTRTYPE', ifelse(
+			STRTYPE, `char',      `char',
+			STRTYPE, `zstr_char', `char',
+			`',      `',          `UChar'))
+	pushdef(`ISTYPE', ifelse(STRTYPE,`zstr_uchar',IS_UNICODE,IS_STRING))
+	pushdef(`UNI_STRLEN', ifelse(
+			STRTYPE, `zstr_uchar', `xc_zstrlen_uchar',
+			STRTYPE, `zstr_char',  `xc_zstrlen_char',
+			`',      `',           `strlen'))
+	pushdef(`SRCSTR', ifelse(STRTYPE,`char',`ZSTR($2)',`$2'))
+	pushdef(`SRCPTR', ifelse(
+			STRTYPE, `zstr_uchar', `ZSTR_U($2)',
+			STRTYPE, `zstr_char',  `ZSTR_S($2)',
+			`',      `',           `$2'))
+	pushdef(`DSTPTR', ifelse(
+			STRTYPE, `zstr_uchar', `ZSTR_U($1)',
+			STRTYPE, `zstr_char',  `ZSTR_S($1)',
+			`',      `',           `$1'))
+	pushdef(`U', ifelse(
+			PTRTYPE, `char',  `',
+			PTRTYPE, `UChar', `u'))
+	if (SRCPTR == NULL) {
+		IFNOTMEMCPY(`IFCOPY(`
+			DSTPTR = NULL;
+		')')
+		IFDASM(`
+			add_assoc_null_ex(dst, ZEND_STRS("$4"));
+		')
+	}
+	else {
+		IFDPRINT(`INDENT()
+			ifelse(STRTYPE, `zstr_uchar', `
+#ifdef IS_UNICODE
+			do {
+				zval zv;
+				zval reszv;
+				int usecopy;
+
+				INIT_ZVAL(zv);
+				ZVAL_UNICODEL(&zv, ZSTR_U($2), $3 - 1, 1);
+				zend_make_printable_zval(&zv, &reszv, &usecopy);
+				fprintf(stderr, "string:%s:\t\"", "$1");
+				xc_dprint_str_len(Z_STRVAL(reszv), Z_STRLEN(reszv));
+				fprintf(stderr, "\" len=%d\n", $3 - 1);
+				if (usecopy) {
+					zval_dtor(&reszv);
+				}
+				zval_dtor(&zv);
+			} while (0);
+#endif
+			', `
+			fprintf(stderr, "string:%s:\t\"", "$1");
+			xc_dprint_str_len(SRCPTR, $3 - 1);
+			fprintf(stderr, "\" len=%d\n", $3 - 1);
+			')
+		')
+		IFCALC(`xc_calc_string_n(processor, ISTYPE, ZSTR(SRCSTR), $3 IFASSERT(`, __LINE__'));')
+		IFSTORE(`DSTPTR = ifelse(PTRTYPE,`char',`ZSTR_S',`ZSTR_U')(xc_store_string_n(processor, ISTYPE, ZSTR(SRCSTR), $3 IFASSERT(`, __LINE__')));')
+		IFRESTORE(`
+			DSTPTR = e`'U`'strndup(SRCPTR, ($3) - 1);
+		')
+		FIXPOINTER_EX(`PTRTYPE', DSTPTR)
+		IFDASM(`
+			ifelse(STRTYPE,zstr_uchar, `
+				add_assoc_unicodel_ex(dst, ZEND_STRS("$4"), ZSTR_U($2), $3-1, 1);
+				', ` dnl else
+				ifelse(STRTYPE,zstr_char, `
+					add_assoc_stringl_ex(dst, ZEND_STRS("$4"), ZSTR_S($2), $3-1, 1);
+					', `
+					add_assoc_stringl_ex(dst, ZEND_STRS("$4"), $2, $3-1, 1);
+				')
+			')
+		')
+	}
+	popdef(`U')
+	popdef(`DSTPTR')
+	popdef(`SRCPTR')
+	popdef(`SRCSTR')
+	popdef(`UNI_STRLEN')
+	popdef(`STRTYPE')
+	popdef(`ISTYPE')
+')
+dnl }}}
+dnl PROC_STRING_N(1:name, 2:size, 3:type)
+define(`PROC_STRING_N', `DBG(`$0($*)') DONE(`$1')`'PROC_STRING_N_EX(`dst->$1', `src->$1', `src->$2', `$1', `char')')
+
+define(`PROC_STRING_L', `DBG(`$0($*)') PROC_STRING_N(`$1', `$2 + 1')')
+define(`PROC_STRING',   `DBG(`$0($*)') DONE(`$1')`'PROC_STRING_N_EX(`dst->$1', `src->$1', `strlen(src->$1) + 1', `$1', `char')')
+
+dnl {{{ PROC_ZSTRING_N(1:type, 2:name, 3:size, 4:size_type)
+define(`PROC_ZSTRING_N', `
+	DBG(`$0($*)')
+#ifdef IS_UNICODE
+	pushdef(`NSIZE', ifelse(
+			`$4', `strlen', `UNI_STRLEN (src->$2) + 1',
+			`$4', `len',    `src->$3 + 1',
+			`',   `',       `src->$3',
+			))
+	DONE(`$2')
+	ifelse(`$1', `1', `PROC_STRING_N_EX(`dst->$2', `src->$2', defn(`NSIZE'), `$2', `zstr_uchar')
+	', `
+		if (ifelse(`$1', `', `UG(unicode)', `src->$1 == IS_UNICODE')) {
+			PROC_STRING_N_EX(`dst->$2', `src->$2', defn(`NSIZE'), `$2', `zstr_uchar')
+		}
+		else {
+			PROC_STRING_N_EX(`dst->$2', `src->$2', defn(`NSIZE'), `$2', `zstr_char')
+		}
+	')
+#else
+	DONE(`$2')
+	PROC_STRING_N_EX(`dst->$2', `src->$2', NSIZE, `$2', `zstr_char')
+#endif
+	popdef(`NSIZE')
+')
+dnl }}}
+define(`PROC_ZSTRING_L', `DBG(`$0($*)') PROC_ZSTRING_N(`$1', `$2', `$3', `len')')
+define(`PROC_ZSTRING', `DBG(`$0($*)') PROC_ZSTRING_N(`$1', `$2', , `strlen')')
Index: /tags/1.3.0-rc1/processor/hashtable.m4
===================================================================
--- /tags/1.3.0-rc1/processor/hashtable.m4	(revision 623)
+++ /tags/1.3.0-rc1/processor/hashtable.m4	(revision 623)
@@ -0,0 +1,167 @@
+dnl DEF_HASH_TABLE_FUNC(1:name, 2:datatype [, 3:dataname] [, 4:check_function])
+define(`DEF_HASH_TABLE_FUNC', `
+	DEF_STRUCT_P_FUNC(`HashTable', `$1', `
+		pushdefFUNC_NAME(`$2', `$3')
+		dnl {{{ dasm
+		IFDASM(`
+			Bucket *b;
+			zval *zv;
+			int bufsize = 2;
+			char *buf = emalloc(bufsize);
+			int keysize;
+
+#if defined(HARDENING_PATCH_HASH_PROTECT) && HARDENING_PATCH_HASH_PROTECT
+			DONE(canary)
+#endif
+			DONE(nTableSize)
+			DONE(nTableMask)
+			DONE(nNumOfElements)
+			DONE(nNextFreeElement)
+			DONE(pInternalPointer)
+			DONE(pListHead)
+			DONE(pListTail)
+			DONE(arBuckets)
+			DONE(pDestructor)
+			DONE(persistent)
+			DONE(nApplyCount)
+			DONE(bApplyProtection)
+#if ZEND_DEBUG
+			DONE(inconsistent)
+#endif
+#ifdef IS_UNICODE
+			DONE(unicode)
+#endif
+
+			DISABLECHECK(`
+			for (b = src->pListHead; b != NULL; b = b->pListNext) {
+				ALLOC_INIT_ZVAL(zv);
+				array_init(zv);
+				FUNC_NAME (zv, (($2*)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];
+				keysize = b->nKeyLength;
+#ifdef IS_UNICODE
+				if (BUCKET_KEY_TYPE(b) == IS_UNICODE) {
+					if (buf[0] == ""[0] && buf[1] == ""[0]) {
+						keysize ++;
+					}
+				} else
+#endif
+				{
+					if (buf[0] == ""[0]) {
+						keysize ++;
+					}
+				}
+				add_u_assoc_zval_ex(dst, BUCKET_KEY_TYPE(b), ZSTR(buf), keysize, zv);
+			}
+			')
+
+			efree(buf);
+			return; /* no check size */
+		', `
+		dnl }}}
+		Bucket *b, *pnew = NULL, *prev = NULL;
+		zend_bool first = 1;
+		dnl only used for copy
+		IFCOPY(`uint n;')
+		IFCALCCOPY(`int bucketsize;')
+
+#if defined(HARDENING_PATCH_HASH_PROTECT) && HARDENING_PATCH_HASH_PROTECT
+		IFASM(`dst->canary = zend_hash_canary; DONE(canary)', `
+		dnl elseif
+			IFRESTORE(`dst->canary = zend_hash_canary; DONE(canary)', `
+				dnl else
+				DISPATCH(unsigned int, canary)
+			')
+		')
+#endif
+		DISPATCH(uint, nTableSize)
+		DISPATCH(uint, nTableMask)
+		DISPATCH(uint, nNumOfElements)
+		DISPATCH(ulong, nNextFreeElement)
+		IFCOPY(`dst->pInternalPointer = NULL;	/* Used for element traversal */') DONE(pInternalPointer)
+		IFCOPY(`dst->pListHead = NULL;') DONE(pListHead)
+		CALLOC(dst->arBuckets, Bucket*, src->nTableSize)
+		DONE(arBuckets)
+		DISABLECHECK(`
+
+		for (b = src->pListHead; b != NULL; b = b->pListNext) {
+			ifelse($4, `', `', `
+				pushdef(`BUCKET', `b')
+				if ($4 == ZEND_HASH_APPLY_REMOVE) {
+					IFCOPY(`dst->nNumOfElements --;')
+					continue;
+				}
+				popdef(`BUCKET')
+			')
+
+			IFCALCCOPY(`bucketsize = BUCKET_SIZE(b);')
+			ALLOC(pnew, char, bucketsize, , Bucket)
+			IFCOPY(`memcpy(pnew, b, bucketsize);')
+			IFCOPY(`
+				n = b->h & src->nTableMask;
+				/* pnew into hash node chain */
+				pnew->pLast = NULL;
+				if (dst->arBuckets[n]) {
+					pnew->pNext = dst->arBuckets[n];
+					pnew->pNext->pLast = pnew;
+				}
+				else {
+					pnew->pNext = NULL;
+				}
+				dst->arBuckets[n] = pnew;
+			')
+			IFDPRINT(`
+				INDENT()
+				fprintf(stderr, "$2:\"");
+				xc_dprint_str_len(BUCKET_KEY_S(b), BUCKET_KEY_SIZE(b));
+				fprintf(stderr, "\" %d:h=%lu ", BUCKET_KEY_SIZE(b), b->h);
+			')
+			if (sizeof(void *) == sizeof($2)) {
+				IFCOPY(`pnew->pData = &pnew->pDataPtr;')
+				dnl no alloc
+				STRUCT_P_EX(`$2', pnew->pData, (($2*)b->pData), `', `$3', ` ')
+			}
+			else {
+				STRUCT_P_EX(`$2', pnew->pData, (($2*)b->pData), `', `$3')
+				IFCOPY(`pnew->pDataPtr = NULL;')
+			}
+
+			if (first) {
+				IFCOPY(`dst->pListHead = pnew;')
+				first = 0;
+			}
+
+			IFCOPY(`
+				/* flat link */
+				pnew->pListLast = prev;
+				pnew->pListNext = NULL;
+				if (prev) {
+					prev->pListNext = pnew;
+				}
+			')
+			prev = pnew;
+		}
+		')
+		IFCOPY(`dst->pListTail = pnew;') DONE(pListTail)
+		IFCOPY(`dst->pDestructor = src->pDestructor;') DONE(pDestructor)
+		DISPATCH(zend_bool, persistent)
+#ifdef IS_UNICODE
+		DISPATCH(zend_bool, unicode)
+#endif
+		DISPATCH(unsigned char, nApplyCount)
+		DISPATCH(zend_bool, bApplyProtection)
+#if ZEND_DEBUG
+		DISPATCH(int, inconsistent)
+#endif
+		')dnl IFDASM
+		popdef(`FUNC_NAME')
+	')
+')
Index: /tags/1.3.0-rc1/processor/dispatch.m4
===================================================================
--- /tags/1.3.0-rc1/processor/dispatch.m4	(revision 616)
+++ /tags/1.3.0-rc1/processor/dispatch.m4	(revision 616)
@@ -0,0 +1,28 @@
+dnl DISPATCH(1:type, 2:elm)
+define(`DISPATCH', `
+	DBG(`$0($*)')
+	assert(sizeof($1) == sizeof(src->$2));
+	ifelse(
+		`$1', `zend_bool',        `PROC_INT(`$2', `u',  `$1')'
+	, `$1', `zend_uchar',       `PROC_INT(`$2', `u',  `$1')'
+	, `$1', `char',             `PROC_INT(`$2', `d',  `$1')'
+	, `$1', `int32_t',          `PROC_INT(`$2', `d',  `$1')'
+	, `$1', `unsigned char',    `PROC_INT(`$2', `u',  `$1')'
+	, `$1', `zend_uint',        `PROC_INT(`$2', `u',  `$1')'
+	, `$1', `uint',             `PROC_INT(`$2', `u',  `$1')'
+	, `$1', `unsigned int',     `PROC_INT(`$2', `u',  `$1')'
+	, `$1', `zend_ulong',       `PROC_INT(`$2', `lu', `$1')'
+	, `$1', `ulong',            `PROC_INT(`$2', `lu', `$1')'
+	, `$1', `size_t',           `PROC_INT(`$2', `u', `$1')'
+	, `$1', `long',             `PROC_INT(`$2', `ld', `$1')'
+	, `$1', `time_t',           `PROC_INT(`$2', `ld', `$1')'
+	, `$1', `zend_ushort',      `PROC_INT(`$2', `hu', `$1')'
+	, `$1', `int',              `PROC_INT(`$2', `d',  `$1')'
+	, `$1', `double',           `PROC_INT(`$2', `f',  `$1')'
+	, `$1', `opcode_handler_t', `/* is copying enough? */COPY(`$2')'
+	, `$1', `zval_data_type',   `PROC_INT(`$2', `u',  `$1')'
+	, `$1', `xc_entry_type_t',  `PROC_INT(`$2', `d',  `$1')'
+	, `$1', `xc_hash_value_t',  `PROC_INT(`$2', `lu', `$1')'
+	, `', `', `m4_errprint(`Unknown type "$1"')'
+	)
+')
Index: /tags/1.3.0-rc1/processor/processor.m4
===================================================================
--- /tags/1.3.0-rc1/processor/processor.m4	(revision 646)
+++ /tags/1.3.0-rc1/processor/processor.m4	(revision 646)
@@ -0,0 +1,874 @@
+dnl ================
+/* {{{ Pre-declare */
+DECL_STRUCT_P_FUNC(`zval')
+DECL_STRUCT_P_FUNC(`zval_ptr')
+DECL_STRUCT_P_FUNC(`zend_op_array')
+DECL_STRUCT_P_FUNC(`zend_class_entry')
+#ifdef HAVE_XCACHE_CONSTANT
+DECL_STRUCT_P_FUNC(`zend_constant')
+#endif
+DECL_STRUCT_P_FUNC(`zend_function')
+DECL_STRUCT_P_FUNC(`xc_entry_t')
+#ifdef ZEND_ENGINE_2
+DECL_STRUCT_P_FUNC(`zend_property_info')
+#endif
+/* }}} */
+dnl ====================================================
+dnl {{{ zend_compiled_variable
+#ifdef IS_CV
+DEF_STRUCT_P_FUNC(`zend_compiled_variable', , `
+	DISPATCH(int, name_len)
+	PROC_ZSTRING_L(, name, name_len)
+	DISPATCH(ulong, hash_value)
+')
+#endif
+dnl }}}
+dnl {{{ zend_uint
+DEF_STRUCT_P_FUNC(`zend_uint', , `
+	IFCOPY(`dst[0] = src[0];')
+	IFDPRINT(`
+		INDENT()
+		fprintf(stderr, "%u\n", src[0]);
+	')
+	DONE_SIZE(sizeof(src[0]))
+')
+dnl }}}
+dnl {{{ int
+#ifndef ZEND_ENGINE_2
+DEF_STRUCT_P_FUNC(`int', , `
+	IFCOPY(`*dst = *src;')
+	IFDPRINT(`
+		INDENT()
+		fprintf(stderr, "%d\n", src[0]);
+	')
+	DONE_SIZE(sizeof(src[0]))
+')
+#endif
+dnl }}}
+dnl {{{ zend_try_catch_element
+#ifdef ZEND_ENGINE_2
+DEF_STRUCT_P_FUNC(`zend_try_catch_element', , `
+	DISPATCH(zend_uint, try_op)
+	DISPATCH(zend_uint, catch_op)
+')
+#endif /* ifdef ZEND_ENGINE_2 */
+dnl }}}
+dnl {{{ zend_brk_cont_element
+DEF_STRUCT_P_FUNC(`zend_brk_cont_element', , `
+#ifdef ZEND_ENGINE_2_2
+	DISPATCH(int, start)
+#endif
+	DISPATCH(int, cont)
+	DISPATCH(int, brk)
+	DISPATCH(int, parent)
+')
+dnl }}}
+DEF_HASH_TABLE_FUNC(`HashTable_zval_ptr',           `zval_ptr')
+DEF_HASH_TABLE_FUNC(`HashTable_zend_function',      `zend_function')
+#ifdef ZEND_ENGINE_2
+DEF_HASH_TABLE_FUNC(`HashTable_zend_property_info', `zend_property_info')
+#endif
+DEF_STRUCT_P_FUNC(`zval', , `dnl {{{
+	IFDASM(`do {
+		zval_dtor(dst);
+		*dst = *src;
+		zval_copy_ctor(dst);
+		Z_SET_REFCOUNT(*dst, 1);
+		DONE(value)
+		DONE(type)
+#ifdef ZEND_ENGINE_2_3
+		DONE(is_ref__gc)
+		DONE(refcount__gc)
+#else
+		DONE(is_ref)
+		DONE(refcount)
+#endif
+	} while(0);
+	return;
+	', `
+		dnl IFDASM else
+		/* Variable information */
+dnl {{{ zvalue_value
+		DISABLECHECK(`
+		switch ((Z_TYPE_P(src) & IS_CONSTANT_TYPE_MASK)) {
+			case IS_LONG:
+			case IS_RESOURCE:
+			case IS_BOOL:
+				DISPATCH(long, value.lval)
+				break;
+			case IS_DOUBLE:
+				DISPATCH(double, value.dval)
+				break;
+			case IS_NULL:
+				IFDPRINT(`INDENT()`'fprintf(stderr, "\tNULL\n");')
+				break;
+
+			case IS_CONSTANT:
+#ifdef IS_UNICODE
+				if (UG(unicode)) {
+					goto proc_unicode;
+				}
+#endif
+			case IS_STRING:
+#ifdef FLAG_IS_BC
+			case FLAG_IS_BC:
+#endif
+				DISPATCH(int, value.str.len)
+				PROC_STRING_L(value.str.val, value.str.len)
+				break;
+#ifdef IS_UNICODE
+			case IS_UNICODE:
+proc_unicode:
+				DISPATCH(int32_t, value.uni.len)
+				PROC_ZSTRING_L(1, value.uni.val, value.uni.len)
+				break;
+#endif
+
+			case IS_ARRAY:
+			case IS_CONSTANT_ARRAY:
+				STRUCT_P(HashTable, value.ht, HashTable_zval_ptr)
+				break;
+
+			case IS_OBJECT:
+				IFNOTMEMCPY(`IFCOPY(`memcpy(dst, src, sizeof(src[0]));')')
+				dnl STRUCT(value.obj)
+#ifndef ZEND_ENGINE_2
+				STRUCT_P(zend_class_entry, value.obj.ce)
+				STRUCT_P(HashTable, value.obj.properties, HashTable_zval_ptr)
+#endif
+				break;
+
+			default:
+				assert(0);
+		}
+		')
+dnl }}}
+		DONE(value)
+		DISPATCH(zval_data_type, type)
+#ifdef ZEND_ENGINE_2_3
+		DISPATCH(zend_uchar, is_ref__gc)
+#else
+		DISPATCH(zend_uchar, is_ref)
+#endif
+
+#ifdef ZEND_ENGINE_2_3
+		DISPATCH(zend_uint, refcount__gc)
+#elif defined(ZEND_ENGINE_2)
+		DISPATCH(zend_uint, refcount)
+#else
+		DISPATCH(zend_ushort, refcount)
+#endif
+	')dnl IFDASM
+')
+dnl }}}
+DEF_STRUCT_P_FUNC(`zval_ptr', , `dnl {{{
+	IFDASM(`
+		pushdefFUNC_NAME(`zval')
+		FUNC_NAME (dst, src[0] TSRMLS_CC);
+		popdef(`FUNC_NAME')
+	', `
+		do {
+			IFCALCCOPY(`
+				if (processor->reference) {
+					zval_ptr *ppzv;
+					if (zend_hash_find(&processor->zvalptrs, (char *) &src[0], sizeof(src[0]), (void **) &ppzv) == SUCCESS) {
+						IFCOPY(`
+							dst[0] = *ppzv;
+							/* *dst is updated */
+							dnl fprintf(stderr, "*dst is set to %p, KIND is_shm %d\n", dst[0], xc_is_shm(dst[0]));
+						')
+						IFCALCSTORE(`processor->have_references = 1;')
+						IFSTORE(`assert(xc_is_shm(dst[0]));')
+						IFRESTORE(`assert(!xc_is_shm(dst[0]));')
+						break;
+					}
+				}
+			')
+			
+			ALLOC(dst[0], zval)
+			IFCALCCOPY(`
+				if (processor->reference) {
+					IFCALC(`
+						/* make dummy */
+						zval_ptr pzv = (zval_ptr)-1;
+					', `
+						zval_ptr pzv = dst[0];
+						FIXPOINTER_EX(zval, pzv)
+					')
+					if (zend_hash_add(&processor->zvalptrs, (char *) &src[0], sizeof(src[0]), (void *) &pzv, sizeof(pzv), NULL) == SUCCESS) {
+						/* first add, go on */
+						dnl fprintf(stderr, "mark[%p] = %p\n", src[0], pzv);
+					}
+					else {
+						assert(0);
+					}
+				}
+			')
+			IFCOPY(`
+				dnl fprintf(stderr, "copy from %p to %p\n", src[0], dst[0]);
+			')
+			IFDPRINT(`INDENT()`'fprintf(stderr, "[%p] ", src[0]);')
+			STRUCT_P_EX(zval, dst[0], src[0], `[0]', `', ` ')
+			FIXPOINTER_EX(zval, dst[0])
+		} while (0);
+	')
+	DONE_SIZE(sizeof(zval_ptr))
+')
+dnl }}}
+dnl {{{ zend_arg_info
+#ifdef ZEND_ENGINE_2
+DEF_STRUCT_P_FUNC(`zend_arg_info', , `
+	DISPATCH(zend_uint, name_len)
+	PROC_ZSTRING_L(, name, name_len)
+	DISPATCH(zend_uint, class_name_len)
+	PROC_ZSTRING_L(, class_name, class_name_len)
+	DISPATCH(zend_bool, array_type_hint)
+	DISPATCH(zend_bool, allow_null)
+	DISPATCH(zend_bool, pass_by_reference)
+	DISPATCH(zend_bool, return_reference)
+	DISPATCH(int, required_num_args)
+')
+#endif
+dnl }}}
+#ifdef HAVE_XCACHE_CONSTANT
+DEF_STRUCT_P_FUNC(`zend_constant', , `dnl {{{
+	STRUCT(zval, value)
+	DISPATCH(int, flags)
+	DISPATCH(uint, name_len)
+	pushdef(`emalloc', `malloc($1)')
+	pushdef(`ecalloc', `calloc($1, $2)')
+	PROC_ZSTRING_N(, name, name_len)
+	popdef(`ecalloc')
+	popdef(`emalloc')
+	DISPATCH(int, module_number)
+')
+dnl }}}
+#endif
+DEF_STRUCT_P_FUNC(`zend_function', , `dnl {{{
+	DISABLECHECK(`
+	switch (src->type) {
+	case ZEND_INTERNAL_FUNCTION:
+	case ZEND_OVERLOADED_FUNCTION:
+		IFNOTMEMCPY(`IFCOPY(`memcpy(dst, src, sizeof(src[0]));')')
+		break;
+
+	case ZEND_USER_FUNCTION:
+	case ZEND_EVAL_CODE:
+		DONE(type)
+		STRUCT(zend_op_array, op_array)
+		break;
+
+	default:
+		assert(0);
+	}
+	')
+	DONE_SIZE(sizeof(src[0]))
+')
+dnl }}}
+dnl {{{ zend_property_info
+#ifdef ZEND_ENGINE_2
+DEF_STRUCT_P_FUNC(`zend_property_info', , `
+	DISPATCH(zend_uint, flags)
+	DISPATCH(int, name_length)
+	PROC_ZSTRING_L(, name, name_length)
+	DISPATCH(ulong, h)
+#ifdef ZEND_ENGINE_2_1
+	DISPATCH(int, doc_comment_len)
+	PROC_ZSTRING_L(, doc_comment, doc_comment_len)
+#endif
+	dnl isnt in php6 yet
+#if defined(ZEND_ENGINE_2_2)
+	PROC_CLASS_ENTRY_P(ce)
+#endif
+')
+#endif
+dnl }}}
+DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{
+	IFCALCCOPY(`
+		processor->active_class_entry_src = src;
+		IFCOPY(`processor->active_class_entry_dst = dst;')
+	')
+	DISPATCH(char, type)
+	DISPATCH(zend_uint, name_length)
+	PROC_ZSTRING_L(, name, name_length)
+	IFRESTORE(`
+#ifndef ZEND_ENGINE_2
+		/* just copy parent and resolve on install_class */
+		COPY(parent)
+#else
+		PROC_CLASS_ENTRY_P(parent)
+#endif
+	', `
+		PROC_CLASS_ENTRY_P(parent)
+	')
+#ifdef ZEND_ENGINE_2
+	DISPATCH(int, refcount)
+#else
+	STRUCT_P(int, refcount)
+#endif
+	DISPATCH(zend_bool, constants_updated)
+#ifdef ZEND_ENGINE_2
+	DISPATCH(zend_uint, ce_flags)
+#endif
+
+	STRUCT(HashTable, default_properties, HashTable_zval_ptr)
+	IFCOPY(`dst->builtin_functions = src->builtin_functions;')
+	DONE(builtin_functions)
+#ifdef ZEND_ENGINE_2
+	STRUCT(HashTable, properties_info, HashTable_zend_property_info)
+#	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
+	STRUCT_P(HashTable, static_members, HashTable_zval_ptr)
+#	endif
+	STRUCT(HashTable, constants_table, HashTable_zval_ptr)
+
+	dnl runtime binding: ADD_INTERFACE will deal with it
+	IFRESTORE(`
+		if (src->num_interfaces) {
+			CALLOC(dst->interfaces, zend_class_entry*, src->num_interfaces)
+			DONE(`interfaces')
+		}
+		else {
+			COPYNULL(interfaces)
+		}
+	')
+	IFDASM(`
+		if (src->num_interfaces) {
+			/*
+			zval *arr;
+			ALLOC_INIT_ZVAL(arr);
+			array_init(arr);
+			for (i = 0; i < src->num_interfaces; i ++) {
+				zval *zv;
+				ALLOC_INIT_ZVAL(zv);
+				ZVAL_STRING(src->num_interfaces);
+			}
+			add_assoc_zval_ex(dst, ZEND_STRS("interfaces"), arr);
+			*/
+			DONE(`interfaces')
+		}
+		else {
+			COPYNULL(interfaces)
+		}
+	')
+	IFRESTORE(`', `
+		IFDASM(`', `
+			DONE(`interfaces')
+		')
+	')
+	DISPATCH(zend_uint, num_interfaces)
+
+	IFRESTORE(`COPY(filename)', `PROC_STRING(filename)')
+	DISPATCH(zend_uint, line_start)
+	DISPATCH(zend_uint, line_end)
+#ifdef ZEND_ENGINE_2_1
+	DISPATCH(zend_uint, doc_comment_len)
+	PROC_ZSTRING_L(, doc_comment, doc_comment_len)
+#endif
+	/* # NOT DONE */
+	COPY(serialize_func)
+	COPY(unserialize_func)
+	COPY(iterator_funcs)
+	COPY(create_object)
+	COPY(get_iterator)
+	COPY(interface_gets_implemented)
+#ifdef ZEND_ENGINE_2_3
+	COPY(get_static_method)
+#endif
+	COPY(serialize)
+	COPY(unserialize)
+	/* deal with it inside xc_fix_method */
+	SETNULL(constructor)
+	COPY(destructor)
+	COPY(clone)
+	COPY(__get)
+	COPY(__set)
+/* should be >5.1 */
+#ifdef ZEND_ENGINE_2_1
+	COPY(__unset)
+	COPY(__isset)
+# if defined(ZEND_ENGINE_2_2) || PHP_MAJOR_VERSION >= 6
+	COPY(__tostring)
+# endif
+#endif
+	COPY(__call)
+#ifdef ZEND_CALLSTATIC_FUNC_NAME
+	COPY(__callstatic)
+#endif
+	/* # NOT DONE */
+	COPY(module)
+#else
+	COPY(handle_function_call)
+	COPY(handle_property_get)
+	COPY(handle_property_set)
+#endif
+	dnl must do after SETNULL(constructor) and dst->parent
+	STRUCT(HashTable, function_table, HashTable_zend_function)
+	IFRESTORE(`dst->function_table.pDestructor = ZEND_FUNCTION_DTOR;')
+	IFCALCCOPY(`
+		processor->active_class_entry_src = NULL;
+		IFCOPY(`processor->active_class_entry_dst = NULL;')
+	')
+')
+dnl }}}
+DEF_STRUCT_P_FUNC(`znode', , `dnl {{{
+	DISPATCH(int, op_type)
+
+#ifdef IS_CV
+#	define XCACHE_IS_CV IS_CV
+#else
+/* compatible with zend optimizer */
+#	define XCACHE_IS_CV 16
+#endif
+	assert(src->op_type == IS_CONST ||
+		src->op_type == IS_VAR ||
+		src->op_type == XCACHE_IS_CV ||
+		src->op_type == IS_TMP_VAR ||
+		src->op_type == IS_UNUSED);
+	dnl dirty dispatch
+	DISABLECHECK(`
+	switch (src->op_type) {
+		case IS_CONST:
+			STRUCT(zval, u.constant)
+			break;
+		IFCOPY(`
+			IFNOTMEMCPY(`
+				default:
+					memcpy(&dst->u, &src->u, sizeof(src->u));
+			')
+		', `
+		case IS_VAR:
+		case IS_TMP_VAR:
+		case XCACHE_IS_CV:
+			DISPATCH(zend_uint, u.var)
+			DISPATCH(zend_uint, u.EA.type)
+			break;
+		case IS_UNUSED:
+			IFDASM(`DISPATCH(zend_uint, u.var)')
+			DISPATCH(zend_uint, u.opline_num)
+#ifndef ZEND_ENGINE_2
+			DISPATCH(zend_uint, u.fetch_type)
+#endif
+			DISPATCH(zend_uint, u.EA.type)
+			break;
+		')
+	}
+	')
+	DONE(u)
+#undef XCACHE_IS_CV
+')
+dnl }}}
+DEF_STRUCT_P_FUNC(`zend_op', , `dnl {{{
+	DISPATCH(zend_uchar, opcode)
+	STRUCT(znode, result)
+	STRUCT(znode, op1)
+	STRUCT(znode, op2)
+	DISPATCH(ulong, extended_value)
+	DISPATCH(uint, lineno)
+#ifdef ZEND_ENGINE_2_1
+	IFCOPY(`
+		switch (src->opcode) {
+#ifdef ZEND_GOTO
+			case ZEND_GOTO:
+#endif
+			case ZEND_JMP:
+				dst->op1.u.jmp_addr = processor->active_opcodes_dst + (src->op1.u.jmp_addr - processor->active_opcodes_src);
+				break;
+
+			case ZEND_JMPZ:
+			case ZEND_JMPNZ:
+			case ZEND_JMPZ_EX:
+			case ZEND_JMPNZ_EX:
+#ifdef ZEND_JMP_SET
+			case ZEND_JMP_SET:
+#endif
+				dst->op2.u.jmp_addr = processor->active_opcodes_dst + (src->op2.u.jmp_addr - processor->active_opcodes_src);
+				break;
+
+			default:
+				break;
+		}
+	')
+	DISPATCH(opcode_handler_t, handler)
+#endif
+')
+dnl }}}
+DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
+	IFRESTORE(`
+	dnl shadow copy must NOT meet:
+	dnl readonly_protection=on
+	dnl main op_array && have early binding
+	zend_uint ii;
+#ifdef ZEND_COMPILE_DELAYED_BINDING
+	zend_bool need_early_binding = 0;
+#else
+	zend_bool need_early_binding = processor->xce_src->data.php->have_early_binding;
+#endif
+	if (!processor->readonly_protection && !(src == processor->xce_src->data.php->op_array && need_early_binding)) {
+		/* really fast shallow copy */
+		memcpy(dst, src, sizeof(src[0]));
+		dst->refcount[0] = 1000;
+		/* deep */
+		STRUCT_P(HashTable, static_variables, HashTable_zval_ptr)
+#ifdef ZEND_ENGINE_2
+		STRUCT_ARRAY_I(num_args, zend_arg_info, arg_info)
+		xc_gc_add_op_array(dst TSRMLS_CC);
+#endif
+		define(`SKIPASSERT_ONCE')
+	}
+	else
+	')
+	do {
+	dnl RESTORE is done above!
+	zend_uint ii;
+	int i;
+
+	/* Common elements */
+	DISPATCH(zend_uchar, type)
+	PROC_ZSTRING(, function_name)
+#ifdef ZEND_ENGINE_2
+	DISPATCH(zend_uint, fn_flags)
+	STRUCT_ARRAY_I(num_args, zend_arg_info, arg_info)
+	DISPATCH(zend_uint, num_args)
+	DISPATCH(zend_uint, required_num_args)
+	DISPATCH(zend_bool, pass_rest_by_reference)
+#else
+	if (src->arg_types) {
+		ALLOC(dst->arg_types, zend_uchar, src->arg_types[0] + 1)
+		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;
+			ALLOC_INIT_ZVAL(zv);
+			array_init(zv);
+			for (i = 0; i < src->arg_types[0]; i ++) {
+				add_next_index_long(zv, src->arg_types[i + 1]);
+			}
+			add_assoc_zval_ex(dst, ZEND_STRS("arg_types"), zv);
+		} while (0);')
+		DONE(arg_types)
+	}
+	else {
+		IFDASM(`do {
+			/* empty array */
+			zval *zv;
+			ALLOC_INIT_ZVAL(zv);
+			array_init(zv);
+			add_assoc_zval_ex(dst, ZEND_STRS("arg_types"), zv);
+		} while (0);
+		DONE(arg_types)
+		', `
+		COPYNULL(arg_types)
+		')
+	}
+#endif
+	DISPATCH(unsigned char, return_reference)
+	/* END of common elements */
+#ifdef IS_UNICODE
+	dnl SETNULL(u_twin)
+#endif
+
+	STRUCT_P(zend_uint, refcount)
+	UNFIXPOINTER(zend_uint, refcount)
+	IFSTORE(`dst->refcount[0] = 1;')
+
+	pushdef(`AFTER_ALLOC', `IFCOPY(`
+		processor->active_opcodes_dst = dst->opcodes;
+		processor->active_opcodes_src = src->opcodes;
+	')')
+	STRUCT_ARRAY_I(last, zend_op, opcodes)
+	popdef(`AFTER_ALLOC')
+	DISPATCH(zend_uint, last)
+	IFCOPY(`dst->size = src->last;DONE(size)', `DISPATCH(zend_uint, size)')
+
+#ifdef IS_CV
+	STRUCT_ARRAY(last_var, zend_compiled_variable, vars)
+	DISPATCH(int, last_var)
+	IFCOPY(`dst->size_var = src->last_var;DONE(size_var)', `DISPATCH(zend_uint, size_var)')
+#else
+	dnl zend_cv.m4 is illegal to be made public, don not ask me for it
+	IFDASM(`
+		sinclude(srcdir`/processor/zend_cv.m4')
+		')
+#endif
+
+	DISPATCH(zend_uint, T)
+
+	STRUCT_ARRAY_I(last_brk_cont, zend_brk_cont_element, brk_cont_array)
+	DISPATCH(zend_uint, last_brk_cont)
+	DISPATCH(zend_uint, current_brk_cont)
+#ifndef ZEND_ENGINE_2
+	DISPATCH(zend_bool, uses_globals)
+#endif
+
+#ifdef ZEND_ENGINE_2
+	STRUCT_ARRAY(last_try_catch, zend_try_catch_element, try_catch_array)
+	DISPATCH(int, last_try_catch)
+#endif
+
+	STRUCT_P(HashTable, static_variables, HashTable_zval_ptr)
+
+	COPY(start_op)
+	DISPATCH(int, backpatch_count)
+#ifdef ZEND_ENGINE_2_3
+	DISPATCH(zend_uint, this_var)
+#endif
+
+	DISPATCH(zend_bool, done_pass_two)
+	/* 5.0 <= ver < 5.3 */
+#if defined(ZEND_ENGINE_2) && !defined(ZEND_ENGINE_2_3)
+	DISPATCH(zend_bool, uses_this)
+#endif
+
+	IFRESTORE(`COPY(filename)', `PROC_STRING(filename)')
+#ifdef IS_UNICODE
+	IFRESTORE(`
+		COPY(script_encoding)
+	', `
+		PROC_STRING(script_encoding)
+	')
+#endif
+#ifdef ZEND_ENGINE_2
+	DISPATCH(zend_uint, line_start)
+	DISPATCH(zend_uint, line_end)
+	DISPATCH(int, doc_comment_len)
+	PROC_ZSTRING_L(, doc_comment, doc_comment_len)
+#endif
+#ifdef ZEND_COMPILE_DELAYED_BINDING
+	DISPATCH(zend_uint, early_binding);
+#endif
+
+	/* reserved */
+	DONE(reserved)
+#if defined(HARDENING_PATCH) && HARDENING_PATCH
+	DISPATCH(zend_bool, created_by_eval)
+#endif
+	} while (0);
+
+#ifdef ZEND_ENGINE_2
+	dnl mark it as -1 on store, and lookup parent on restore
+	IFSTORE(`dst->prototype = (processor->active_class_entry_src && src->prototype) ? (zend_function *) -1 : NULL; DONE(prototype)', `
+			IFRESTORE(`do {
+				zend_function *parent;
+				if (src->prototype != NULL
+				 && zend_u_hash_find(&(processor->active_class_entry_dst->parent->function_table),
+						UG(unicode) ? IS_UNICODE : IS_STRING,
+						src->function_name, xc_zstrlen(UG(unicode) ? IS_UNICODE : IS_STRING, src->function_name) + 1,
+						(void **) &parent) == SUCCESS) {
+					/* see do_inherit_method_check() */
+					if ((parent->common.fn_flags & ZEND_ACC_ABSTRACT)) {
+					  dst->prototype = parent;
+					} else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
+						/* ctors only have a prototype if it comes from an interface */
+						dst->prototype = parent->common.prototype ? parent->common.prototype : parent;
+					}
+					else {
+						dst->prototype = NULL;
+					}
+				}
+				else {
+					dst->prototype = NULL;
+				}
+				DONE(prototype)
+			} while (0);
+			', `
+				COPYNULL(prototype)
+			')
+	')
+#endif
+
+#ifdef ZEND_ENGINE_2
+	PROC_CLASS_ENTRY_P(scope)
+	IFCOPY(`
+		if (src->scope) {
+			xc_fix_method(processor, dst TSRMLS_CC);
+		}
+	')
+#endif
+
+	IFRESTORE(`
+		if (xc_have_op_array_ctor) {
+			zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) xc_zend_extension_op_array_ctor_handler, dst TSRMLS_CC);
+		}
+	')
+')
+dnl }}}
+
+#ifdef HAVE_XCACHE_CONSTANT
+DEF_STRUCT_P_FUNC(`xc_constinfo_t', , `dnl {{{
+	DISPATCH(zend_uint, key_size)
+#ifdef IS_UNICODE
+	DISPATCH(zend_uchar, type)
+#endif
+	IFRESTORE(`COPY(key)', `
+		PROC_ZSTRING_N(type, key, key_size)
+	')
+	DISPATCH(ulong, h)
+	STRUCT(zend_constant, constant)
+')
+dnl }}}
+#endif
+DEF_STRUCT_P_FUNC(`xc_funcinfo_t', , `dnl {{{
+	DISPATCH(zend_uint, key_size)
+#ifdef IS_UNICODE
+	DISPATCH(zend_uchar, type)
+#endif
+	IFRESTORE(`COPY(key)', `
+		PROC_ZSTRING_N(type, key, key_size)
+	')
+	DISPATCH(ulong, h)
+	STRUCT(zend_function, func)
+')
+dnl }}}
+DEF_STRUCT_P_FUNC(`xc_classinfo_t', , `dnl {{{
+	DISPATCH(zend_uint, key_size)
+#ifdef IS_UNICODE
+	DISPATCH(zend_uchar, type)
+#endif
+	IFRESTORE(`COPY(key)', `
+		PROC_ZSTRING_N(type, key, key_size)
+	')
+	DISPATCH(ulong, h)
+#ifdef ZEND_ENGINE_2
+	STRUCT_P(zend_class_entry, cest)
+#else
+	STRUCT(zend_class_entry, cest)
+#endif
+#ifndef ZEND_COMPILE_DELAYED_BINDING
+	DISPATCH(int, oplineno)
+#endif
+')
+dnl }}}
+#ifdef ZEND_ENGINE_2_1
+DEF_STRUCT_P_FUNC(`xc_autoglobal_t', , `dnl {{{
+	DISPATCH(zend_uint, key_len)
+#ifdef IS_UNICODE
+	DISPATCH(zend_uchar, type)
+#endif
+	IFRESTORE(`COPY(key)', `
+		PROC_ZSTRING_L(type, key, key_len)
+	')
+	DISPATCH(ulong, h)
+')
+dnl }}}
+#endif
+DEF_STRUCT_P_FUNC(`xc_entry_data_php_t', , `dnl {{{
+	zend_uint i;
+
+#ifdef HAVE_INODE
+	DISPATCH(int, device)
+	DISPATCH(int, inode)
+#endif
+	DISPATCH(size_t, sourcesize)
+
+	DISPATCH(time_t, mtime)
+
+	STRUCT_P(zend_op_array, op_array)
+
+#ifdef HAVE_XCACHE_CONSTANT
+	DISPATCH(zend_uint, constinfo_cnt)
+	STRUCT_ARRAY(constinfo_cnt, xc_constinfo_t, constinfos)
+#endif
+
+	DISPATCH(zend_uint, funcinfo_cnt)
+	STRUCT_ARRAY(funcinfo_cnt, xc_funcinfo_t, funcinfos)
+
+	DISPATCH(zend_uint, classinfo_cnt)
+	pushdef(`BEFORE_LOOP', `
+		IFCOPY(`
+			processor->active_class_num = i + 1;
+		')
+	')
+	STRUCT_ARRAY(classinfo_cnt, xc_classinfo_t, classinfos)
+	popdef(`BEFORE_LOOP')
+#ifdef ZEND_ENGINE_2_1
+	DISPATCH(zend_uint, autoglobal_cnt)
+	IFRESTORE(`
+		COPY(autoglobals)
+	', `
+		STRUCT_ARRAY(autoglobal_cnt, xc_autoglobal_t, autoglobals)
+	')
+#endif
+#ifndef ZEND_COMPILE_DELAYED_BINDING
+	DISPATCH(zend_bool, have_early_binding)
+#endif
+')
+dnl }}}
+DEF_STRUCT_P_FUNC(`xc_entry_data_var_t', , `dnl {{{
+	IFDPRINT(`INDENT()`'fprintf(stderr, "zval:value");')
+	STRUCT_P_EX(zval_ptr, dst->value, src->value, `value', `', `&')
+	DONE(value)
+')
+dnl }}}
+dnl {{{ xc_entry_t
+DEF_STRUCT_P_FUNC(`xc_entry_t', , `
+	IFCOPY(`
+		processor->xce_dst = dst;
+		processor->xce_src = src;
+	')
+	DISPATCH(xc_entry_type_t, type)
+	DISPATCH(size_t, size)
+
+	DISPATCH(xc_hash_value_t, hvalue)
+	COPY(cache)
+	/* skip */
+	DONE(next)
+
+	IFSTORE(`dst->refcount = 0; DONE(refcount)', `DISPATCH(long, refcount)')
+
+	DISPATCH(time_t, ctime)
+	DISPATCH(time_t, atime)
+	DISPATCH(time_t, dtime)
+	DISPATCH(long, ttl)
+	DISPATCH(zend_ulong, hits)
+#ifdef IS_UNICODE
+	DISPATCH(zend_uchar, name_type)
+#endif
+	dnl {{{ name
+	DISABLECHECK(`
+#ifdef IS_UNICODE
+		if (src->name_type == IS_UNICODE) {
+			DISPATCH(int32_t, name.ustr.len)
+		}
+		else {
+			DISPATCH(int, name.str.len)
+		}
+#else
+		DISPATCH(int, name.str.len)
+#endif
+		IFRESTORE(`COPY(name.str.val)', `
+#ifdef IS_UNICODE
+			PROC_ZSTRING_L(name_type, name.uni.val, name.uni.len)
+#else
+			PROC_STRING_L(name.str.val, name.str.len)
+#endif
+		')
+	')
+	DONE(name)
+	dnl }}}
+
+	dnl {{{ data
+	DISABLECHECK(`
+		switch (src->type) {
+		case XC_TYPE_PHP:
+			STRUCT_P(xc_entry_data_php_t, data.php)
+			break;
+
+		case XC_TYPE_VAR:
+			STRUCT_P(xc_entry_data_var_t, data.var)
+			break;
+
+		default:
+			assert(0);
+		}
+	')
+	DONE(data)
+	dnl }}}
+	DISPATCH(zend_bool, have_references)
+')
+dnl }}}
+dnl ====================================================
Index: /tags/1.3.0-rc1/processor/head.m4
===================================================================
--- /tags/1.3.0-rc1/processor/head.m4	(revision 646)
+++ /tags/1.3.0-rc1/processor/head.m4	(revision 646)
@@ -0,0 +1,416 @@
+dnl {{{ === program start ========================================
+divert(0)
+#include <string.h>
+#include <stdio.h>
+
+#include "php.h"
+#include "zend_extensions.h"
+#include "zend_compile.h"
+#include "zend_API.h"
+#include "zend_ini.h"
+
+#include "xcache.h"
+#include "align.h"
+#include "const_string.h"
+#include "processor.h"
+#include "stack.h"
+#include "xcache_globals.h"
+
+#if defined(HARDENING_PATCH_HASH_PROTECT) && HARDENING_PATCH_HASH_PROTECT
+extern unsigned int zend_hash_canary;
+#endif
+
+define(`SIZEOF_zend_uint', `sizeof(zend_uint)')
+define(`COUNTOF_zend_uint', `1')
+define(`SIZEOF_int', `sizeof(int)')
+define(`COUNTOF_int', `1')
+define(`SIZEOF_zend_function', `sizeof(zend_function)')
+define(`COUNTOF_zend_function', `1')
+define(`SIZEOF_zval_ptr', `sizeof(zval_ptr)')
+define(`COUNTOF_zval_ptr', `1')
+define(`SIZEOF_xc_entry_name_t', `sizeof(xc_entry_name_t)')
+define(`COUNTOF_xc_entry_name_t', `1')
+
+ifdef(`XCACHE_ENABLE_TEST', `
+#undef NDEBUG
+#include <assert.h>
+m4_errprint(`AUTOCHECK INFO: runtime autocheck Enabled (debug build)')
+', `
+m4_errprint(`AUTOCHECK INFO: runtime autocheck Disabled (optimized build)')
+')
+ifdef(`DEBUG_SIZE', `static int xc_totalsize = 0;')
+
+sinclude(builddir`/structinfo.m4')
+
+#ifndef NDEBUG
+#	undef inline
+#define inline
+#endif
+
+typedef zval *zval_ptr;
+typedef zend_uchar zval_data_type;
+#ifdef IS_UNICODE
+typedef UChar zstr_uchar;
+#endif
+typedef char  zstr_char;
+
+#define MAX_DUP_STR_LEN 256
+dnl }}}
+/* export: typedef struct _xc_processor_t xc_processor_t; :export {{{ */
+struct _xc_processor_t {
+	char *p;
+	zend_uint size;
+	HashTable strings;
+	HashTable zvalptrs;
+	zend_bool reference; /* enable if to deal with reference */
+	zend_bool have_references;
+	const xc_entry_t *xce_src;
+	const xc_entry_t *xce_dst;
+	const zend_class_entry *cache_ce;
+	zend_uint cache_class_num;
+
+	const zend_op          *active_opcodes_src;
+	zend_op                *active_opcodes_dst;
+	const zend_class_entry *active_class_entry_src;
+	zend_class_entry       *active_class_entry_dst;
+	zend_uint               active_class_num;
+
+	zend_bool readonly_protection; /* wheather it's present */
+IFASSERT(xc_stack_t allocsizes;)
+};
+/* }}} */
+#ifdef HAVE_XCACHE_DPRINT
+static void xc_dprint_indent(int indent) /* {{{ */
+{
+	int i;
+	for (i = 0; i < indent; i ++) {
+		fprintf(stderr, "  ");
+	}
+}
+/* }}} */
+static void xc_dprint_str_len(const char *str, int len) /* {{{ */
+{
+	const unsigned char *p = (const unsigned char *) str;
+	int i;
+	for (i = 0; i < len; i ++) {
+		if (p[i] < 32 || p[i] == 127) {
+			fprintf(stderr, "\\%03o", (unsigned int) p[i]);
+		}
+		else {
+			fputc(p[i], stderr);
+		}
+	}
+}
+/* }}} */
+#endif
+/* {{{ xc_zstrlen_char */
+static inline int xc_zstrlen_char(zstr s)
+{
+	return strlen(ZSTR_S(s));
+}
+/* }}} */
+#ifdef IS_UNICODE
+/* {{{ xc_zstrlen_uchar */
+static inline int xc_zstrlen_uchar(zstr s)
+{
+	return u_strlen(ZSTR_U(s));
+}
+/* }}} */
+/* {{{ xc_zstrlen */
+static inline int xc_zstrlen(int type, zstr s)
+{
+	return type == IS_UNICODE ? xc_zstrlen_uchar(s) : xc_zstrlen_char(s);
+}
+/* }}} */
+#else
+/* {{{ xc_zstrlen */
+#define xc_zstrlen(dummy, s) xc_zstrlen_char(s)
+/* }}} */
+#endif
+/* {{{ xc_calc_string_n */
+REDEF(`KIND', `calc')
+static inline void xc_calc_string_n(xc_processor_t *processor, zend_uchar type, const zstr str, long size IFASSERT(`, int relayline')) {
+	pushdef(`__LINE__', `relayline')
+	int realsize = UNISW(size, (type == IS_UNICODE) ? UBYTES(size) : size);
+	long dummy = 1;
+
+	if (realsize > MAX_DUP_STR_LEN) {
+		ALLOC(, char, realsize)
+	}
+	else if (zend_u_hash_add(&processor->strings, type, str, size, (void *) &dummy, sizeof(dummy), NULL) == SUCCESS) {
+		/* new string */
+		ALLOC(, char, realsize)
+	} 
+	IFASSERT(`
+		else {
+			dnl fprintf(stderr, "dupstr %s\n", ZSTR_S(str));
+		}
+	')
+	popdef(`__LINE__')
+}
+/* }}} */
+/* {{{ xc_store_string_n */
+REDEF(`KIND', `store')
+static inline zstr xc_store_string_n(xc_processor_t *processor, zend_uchar type, const zstr str, long size IFASSERT(`, int relayline')) {
+	pushdef(`__LINE__', `relayline')
+	int realsize = UNISW(size, (type == IS_UNICODE) ? UBYTES(size) : size);
+	zstr ret, *pret;
+
+	if (realsize > MAX_DUP_STR_LEN) {
+		ALLOC(ZSTR_V(ret), char, realsize)
+		memcpy(ZSTR_V(ret), ZSTR_V(str), realsize);
+		return ret;
+	}
+
+	if (zend_u_hash_find(&processor->strings, type, str, size, (void **) &pret) == SUCCESS) {
+		return *pret;
+	}
+
+	/* new string */
+	ALLOC(ZSTR_V(ret), char, realsize)
+	memcpy(ZSTR_V(ret), ZSTR_V(str), realsize);
+	zend_u_hash_add(&processor->strings, type, str, size, (void *) &ret, sizeof(zstr), NULL);
+	return ret;
+
+	popdef(`__LINE__')
+}
+/* }}} */
+/* {{{ xc_get_class_num
+ * return class_index + 1
+ */
+static zend_ulong xc_get_class_num(xc_processor_t *processor, zend_class_entry *ce) {
+	zend_ulong i;
+	const xc_entry_t *xce = processor->xce_src;
+	zend_class_entry *ceptr;
+
+	if (processor->cache_ce == ce) {
+		return processor->cache_class_num;
+	}
+	for (i = 0; i < xce->data.php->classinfo_cnt; i ++) {
+		ceptr = CestToCePtr(xce->data.php->classinfos[i].cest);
+		if (ZCEP_REFCOUNT_PTR(ceptr) == ZCEP_REFCOUNT_PTR(ce)) {
+			processor->cache_ce = ceptr;
+			processor->cache_class_num = i + 1;
+			return i + 1;
+		}
+	}
+	assert(0);
+	return (zend_ulong) -1;
+}
+/* }}} */
+/* {{{ xc_get_class */
+#ifdef ZEND_ENGINE_2
+static zend_class_entry *xc_get_class(xc_processor_t *processor, zend_ulong class_num) {
+	/* must be parent or currrent class */
+	assert(class_num <= processor->active_class_num);
+	return CestToCePtr(processor->xce_dst->data.php->classinfos[class_num - 1].cest);
+}
+#endif
+/* }}} */
+#ifdef ZEND_ENGINE_2
+/* fix method on store */
+static void xc_fix_method(xc_processor_t *processor, zend_op_array *dst TSRMLS_DC) /* {{{ */
+{
+	zend_function *zf = (zend_function *) dst;
+	zend_class_entry *ce = processor->active_class_entry_dst;
+	const zend_class_entry *srcce = processor->active_class_entry_src;
+
+	/* Fixing up the default functions for objects here since
+	 * we need to compare with the newly allocated functions
+	 *
+	 * caveat: a sub-class method can have the same name as the
+	 * parent~s constructor and create problems.
+	 */
+
+	if (zf->common.fn_flags & ZEND_ACC_CTOR) {
+		if (!ce->constructor) {
+			ce->constructor = zf;
+		}
+	}
+	else if (zf->common.fn_flags & ZEND_ACC_DTOR) {
+		ce->destructor = zf;
+	}
+	else if (zf->common.fn_flags & ZEND_ACC_CLONE) {
+		ce->clone = zf;
+	}
+	else {
+	pushdef(`SET_IF_SAME_NAMEs', `
+		SET_IF_SAME_NAME(__get);
+		SET_IF_SAME_NAME(__set);
+#ifdef ZEND_ENGINE_2_1
+		SET_IF_SAME_NAME(__unset);
+		SET_IF_SAME_NAME(__isset);
+#endif
+		SET_IF_SAME_NAME(__call);
+#ifdef ZEND_CALLSTATIC_FUNC_NAME
+		SET_IF_SAME_NAME(__callstatic);
+#endif
+#if defined(ZEND_ENGINE_2_2) || PHP_MAJOR_VERSION >= 6
+		SET_IF_SAME_NAME(__tostring);
+#endif
+	')
+#ifdef IS_UNICODE
+		if (UG(unicode)) {
+#define SET_IF_SAME_NAME(member) \
+			do { \
+				if (srcce->member && u_strcmp(ZSTR_U(zf->common.function_name), ZSTR_U(srcce->member->common.function_name)) == 0) { \
+					ce->member = zf; \
+				} \
+			} \
+			while(0)
+
+			SET_IF_SAME_NAMEs()
+#undef SET_IF_SAME_NAME
+		}
+		else
+#endif
+		do {
+#define SET_IF_SAME_NAME(member) \
+			do { \
+				if (srcce->member && strcmp(ZSTR_S(zf->common.function_name), ZSTR_S(srcce->member->common.function_name)) == 0) { \
+					ce->member = zf; \
+				} \
+			} \
+			while(0)
+
+			SET_IF_SAME_NAMEs()
+#undef SET_IF_SAME_NAME
+		} while (0);
+
+	popdef(`SET_IF_SAME_NAMEs')
+
+	}
+}
+/* }}} */
+#endif
+/* {{{ call op_array ctor handler */
+extern zend_bool xc_have_op_array_ctor;
+static void xc_zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
+{
+	if (extension->op_array_ctor) {
+		extension->op_array_ctor(op_array);
+	}
+}
+/* }}} */
+dnl ================ export API
+/* export: xc_entry_t *xc_processor_store_xc_entry_t(xc_entry_t *src TSRMLS_DC); :export {{{ */
+xc_entry_t *xc_processor_store_xc_entry_t(xc_entry_t *src TSRMLS_DC) {
+	xc_entry_t *dst;
+	xc_processor_t processor;
+
+	memset(&processor, 0, sizeof(processor));
+	processor.reference = 1;
+
+	IFASSERT(`xc_stack_init(&processor.allocsizes);')
+
+	/* calc size */ {
+		zend_hash_init(&processor.strings, 0, NULL, NULL, 0);
+		if (processor.reference) {
+			zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0);
+		}
+
+		processor.size = 0;
+		/* allocate */
+		processor.size = ALIGN(processor.size + sizeof(src[0]));
+
+		xc_calc_xc_entry_t(&processor, src TSRMLS_CC);
+		if (processor.reference) {
+			zend_hash_destroy(&processor.zvalptrs);
+		}
+		zend_hash_destroy(&processor.strings);
+	}
+	src->size = processor.size;
+	src->have_references = processor.have_references;
+
+	IFASSERT(`xc_stack_reverse(&processor.allocsizes);')
+	/* store {{{ */
+	{
+		IFASSERT(`char *oldp;')
+		zend_hash_init(&processor.strings, 0, NULL, NULL, 0);
+		if (processor.reference) {
+			zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0);
+		}
+
+		/* mem :) */
+		processor.p = (char *) src->cache->mem->handlers->malloc(src->cache->mem, processor.size);
+		if (processor.p == NULL) {
+			dst = NULL;
+			goto err_alloc;
+		}
+		IFASSERT(`oldp = processor.p;')
+		assert(processor.p == (char *) ALIGN(processor.p));
+
+		/* allocate */
+		dst = (xc_entry_t *) processor.p;
+		processor.p = (char *) ALIGN(processor.p + sizeof(dst[0]));
+
+		xc_store_xc_entry_t(&processor, dst, src TSRMLS_CC);
+		IFASSERT(` {
+			int real = processor.p - oldp;
+			int should = processor.size;
+			if (real != processor.size) {
+				fprintf(stderr, "real %d - should %d = %d\n", real, should, real - should);
+				abort();
+			}
+		}')
+err_alloc:
+		if (processor.reference) {
+			zend_hash_destroy(&processor.zvalptrs);
+		}
+		zend_hash_destroy(&processor.strings);
+	}
+	/* }}} */
+
+	IFASSERT(`xc_stack_destroy(&processor.allocsizes);')
+
+	return dst;
+}
+/* }}} */
+/* export: xc_entry_t *xc_processor_restore_xc_entry_t(xc_entry_t *dst, const xc_entry_t *src, zend_bool readonly_protection TSRMLS_DC); :export {{{ */
+xc_entry_t *xc_processor_restore_xc_entry_t(xc_entry_t *dst, const xc_entry_t *src, zend_bool readonly_protection TSRMLS_DC) {
+	xc_processor_t processor;
+
+	memset(&processor, 0, sizeof(processor));
+	processor.readonly_protection = readonly_protection;
+	if (src->have_references) {
+		processor.reference = 1;
+	}
+
+	if (processor.reference) {
+		zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0);
+	}
+	xc_restore_xc_entry_t(&processor, dst, src TSRMLS_CC);
+	if (processor.reference) {
+		zend_hash_destroy(&processor.zvalptrs);
+	}
+	return dst;
+}
+/* }}} */
+/* export: zval *xc_processor_restore_zval(zval *dst, const zval *src, zend_bool have_references TSRMLS_DC); :export {{{ */
+zval *xc_processor_restore_zval(zval *dst, const zval *src, zend_bool have_references TSRMLS_DC) {
+	xc_processor_t processor;
+
+	memset(&processor, 0, sizeof(processor));
+	processor.reference = have_references;
+
+	if (processor.reference) {
+		zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0);
+		dnl fprintf(stderr, "mark[%p] = %p\n", src, dst);
+		zend_hash_add(&processor.zvalptrs, (char *)src, sizeof(src), (void*)&dst, sizeof(dst), NULL);
+	}
+	xc_restore_zval(&processor, dst, src TSRMLS_CC);
+	if (processor.reference) {
+		zend_hash_destroy(&processor.zvalptrs);
+	}
+
+	return dst;
+}
+/* }}} */
+/* export: void xc_dprint(xc_entry_t *src, int indent TSRMLS_DC); :export {{{ */
+#ifdef HAVE_XCACHE_DPRINT
+void xc_dprint(xc_entry_t *src, int indent TSRMLS_DC) {
+	IFDPRINT(`INDENT()`'fprintf(stderr, "xc_entry_t:src");')
+	xc_dprint_xc_entry_t(src, indent TSRMLS_CC);
+}
+#endif
+/* }}} */
Index: /tags/1.3.0-rc1/processor/main.m4
===================================================================
--- /tags/1.3.0-rc1/processor/main.m4	(revision 626)
+++ /tags/1.3.0-rc1/processor/main.m4	(revision 626)
@@ -0,0 +1,253 @@
+divert(-1)
+dnl ================ start ======================
+dnl define(`XCACHE_ENABLE_TEST')
+dnl define(`DEBUG_SIZE')
+define(`USEMEMCPY')
+
+dnl ================ main
+
+dnl {{{ basic
+define(`REDEF', `ifdef(`$1', `undefine(`$1')') define(`$1', `$2')')
+define(`MAKE_MACRONAME', `translit(`$1', ` ():
+', `_____')')
+define(`ONCE', `ifdef(MAKE_MACRONAME(`ONCE $1'), `', `define(MAKE_MACRONAME(`ONCE $1'))$1')')
+define(`m4_errprint', `ONCE(`errprint(`$1
+')')')
+ifdef(`len', `
+define(`m4_len', defn(`len'))
+undefine(`len')
+')
+define(`ZEND_STRS', `($1), (sizeof($1))')
+define(`ZEND_STRL', `($1), (sizeof($1) - 1)')
+dnl ============
+define(`INDENT', `xc_dprint_indent(indent);')
+dnl }}}
+dnl {{{ ALLOC(1:dst, 2:type, 3:count=1, 4:clean=false, 5:forcetype=$2)
+define(`ALLOC', `
+	pushdef(`COUNT', `ifelse(`$3', `', `1', `$3')')
+	pushdef(`SIZE', `sizeof($2)ifelse(`$3', `', `', ` * $3')')
+	pushdef(`FORCETYPE', `ifelse(`$5', , `$2', `$5')')
+	/* allocate */
+	IFCALC(`
+		IFASSERT(`
+			xc_stack_push(&processor->allocsizes, (void *) (long) (SIZE));
+			xc_stack_push(&processor->allocsizes, (void *) (long) (__LINE__));
+		')
+		processor->size = (size_t) ALIGN(processor->size);
+		processor->size += SIZE;
+	')
+	IFSTORE(`
+		IFASSERT(`{
+			if (!xc_stack_count(&processor->allocsizes)) {
+				fprintf(stderr, "mismatch `$@' at line %d\n", __LINE__);
+			}
+			else {
+				unsigned long expect = (unsigned long) xc_stack_pop(&processor->allocsizes);
+				unsigned long atline = (unsigned long) xc_stack_pop(&processor->allocsizes);
+				unsigned long real = SIZE;
+				if (expect != real) {
+					fprintf(stderr, "mismatch `$@' at line %d(was %lu): real %lu - expect %lu = %lu\n", __LINE__, atline, real, expect, real - expect);
+				}
+			}
+		}')
+		ifdef(`DEBUG_SIZE', ` {
+			void *oldp = processor->p;
+		')
+		$1 = (FORCETYPE *) (processor->p = (char *) ALIGN(processor->p));
+		ifelse(`$4', `', `
+				IFASSERT(`memset($1, -1, SIZE);')
+			', `
+				memset($1, 0, SIZE);
+		')
+		processor->p += SIZE;
+
+		ifdef(`DEBUG_SIZE', `
+			xc_totalsize += (char *) processor->p - (char *) oldp;
+			fprintf(stderr, "%d\t%d\t`'SIZE()\n", (char *) processor->p - (char *) oldp, xc_totalsize);
+		}
+		')
+	')
+	IFRESTORE(`ifelse(`$4', `', `
+			ifelse(
+				FORCETYPE*COUNT, `zval*1', `ALLOC_ZVAL($1);',
+				FORCETYPE*COUNT, `HashTable*1', `ALLOC_HASHTABLE($1);',
+				`', `', `$1 = (FORCETYPE *) emalloc(SIZE);')
+			IFASSERT(`memset($1, -1, SIZE);')
+		', `
+			$1 = (FORCETYPE *) ecalloc(COUNT, sizeof($2));
+		')
+	')
+	popdef(`COUNT')
+	popdef(`SIZE')
+')
+dnl CALLOC(1:dst, 2:type [, 3:count=1 ])
+define(`CALLOC', `ALLOC(`$1', `$2', `$3', `1')')
+dnl }}}
+dnl {{{ PROC_INT(1:elm, 2:format=%d, 3:type=, 4:spec=)
+define(`PROC_INT', `
+	IFNOTMEMCPY(`IFCOPY(`dst->$1 = src->$1;')')
+	IFDPRINT(`
+		INDENT()
+		ifelse(
+			`$3 $1', `zval_data_type type', `fprintf(stderr, "$3:$1:\t%d %s\n", src->$1, xc_get_data_type(src->$1));'
+		, `$3 $1', `int op_type', `fprintf(stderr, "$3:$1:\t%d %s\n", src->$1, xc_get_op_type(src->$1));'
+		, `$3 $1', `zend_uchar opcode', `fprintf(stderr, "$3:$1:\t%d %s\n", src->$1, xc_get_opcode(src->$1));'
+		, `', `', `fprintf(stderr, "$3:$1:\t%ifelse(`$2',`',`d',`$2')\n", src->$1);')
+	')
+	IFDASM(`
+		ifelse(
+			`$3', `zend_bool', `add_assoc_bool_ex(dst, ZEND_STRS("$1"), src->$1 ? 1 : 0);'
+		, `', `', `add_assoc_long_ex(dst, ZEND_STRS("$1"), src->$1);'
+		)
+	')
+	DONE(`$1')
+')
+dnl }}}
+dnl {{{ PROC_CLASS_ENTRY_P(1:elm)
+define(`PROC_CLASS_ENTRY_P', `PROC_CLASS_ENTRY_P_EX(`dst->$1', `src->$1', `$1')`'DONE(`$1')')
+dnl PROC_CLASS_ENTRY_P_EX(1:dst, 2:src, 3:elm-name)
+define(`PROC_CLASS_ENTRY_P_EX', `
+	if ($2) {
+		IFSTORE(`$1 = (zend_class_entry *) xc_get_class_num(processor, $2);')
+		IFRESTORE(`$1 = xc_get_class(processor, (zend_ulong) $2);')
+#ifdef IS_UNICODE
+		IFDASM(`add_assoc_unicodel_ex(dst, ZEND_STRS("$3"), ZSTR_U($2->name), $2->name_length, 1);')
+#else
+		IFDASM(`add_assoc_stringl_ex(dst, ZEND_STRS("$3"), $2->name, $2->name_length, 1);')
+#endif
+	}
+	else {
+		COPYNULL_EX(`$1', `$3')
+	}
+')
+dnl }}}
+dnl {{{ IFASSERT
+define(`IFASSERT', `ifdef(`XCACHE_ENABLE_TEST', `
+#ifndef NDEBUG
+		$1
+#endif
+')')
+dnl }}}
+dnl {{{ DBG
+define(`DBG', `ifdef(`XCACHE_ENABLE_TEST', `
+	/* `$1' */
+')')
+dnl }}}
+dnl {{{ EXPORT
+define(`EXPORT', `define(`EXPORT_$1')')
+dnl }}}
+dnl {{{ FIXPOINTER
+define(`FIXPOINTER', `FIXPOINTER_EX(`$1', `dst->$2')')
+define(`FIXPOINTER_EX', `IFSTORE(`
+	$2 = ($1 *) processor->xce_src->cache->shm->handlers->to_readonly(processor->xce_src->cache->shm, (char *)$2);
+')')
+define(`UNFIXPOINTER', `UNFIXPOINTER_EX(`$1', `dst->$2')')
+define(`UNFIXPOINTER_EX', `IFSTORE(`
+	$2 = ($1 *) processor->xce_src->cache->shm->handlers->to_readwrite(processor->xce_src->cache->shm, (char *)$2);
+')')
+dnl }}}
+dnl {{{ COPY
+define(`COPY', `IFNOTMEMCPY(`IFCOPY(`dst->$1 = src->$1;')')DONE(`$1')')
+dnl }}}
+dnl {{{ SETNULL_EX
+define(`SETNULL_EX', `IFCOPY(`$1 = NULL;')')
+define(`SETNULL', `SETNULL_EX(`dst->$1')DONE(`$1')')
+dnl }}}
+dnl {{{ COPYNULL_EX(1:dst, 2:elm-name)
+define(`COPYNULL_EX', `
+	IFDASM(`add_assoc_null_ex(dst, ZEND_STRS("$2"));')
+	IFNOTMEMCPY(`IFCOPY(`$1 = NULL;')')
+')
+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')
+')
+dnl }}}
+dnl {{{ LIST_DIFF(1:left-list, 2:right-list)
+define(`foreach',
+       `pushdef(`$1')_foreach(`$1', `$2', `$3')popdef(`$1')')
+define(`_arg1', `$1')
+define(`_foreach',                             
+       `ifelse(`$2', `()', ,                       
+       `define(`$1', _arg1$2)$3`'_foreach(`$1',
+                                                       (shift$2),
+                                                       `$3')')')
+define(`LIST_DIFF', `dnl
+foreach(`i', `($1)', `pushdef(`item_'defn(`i'))')dnl allocate variable for items in $1 
+foreach(`i', `($2)', `pushdef(`item_'defn(`i'))undefine(`item_'defn(`i'))')dnl allocate variable for items in $2, and undefine it 
+foreach(`i', `($1)', `ifdef(`item_'defn(`i'), `defn(`i') ')')dnl see what is still defined
+foreach(`i', `($2)', `define(`item_'defn(`i'))popdef(`item_'defn(`i'))')dnl
+foreach(`i', `($1)', `popdef(`item_'defn(`i'))')dnl
+')
+dnl }}}
+dnl {{{ DONE_*
+define(`DONE_SIZE', `IFASSERT(`
+	done_size += $1`';
+	done_count ++;
+')')
+define(`DONE', `
+	define(`ELEMENTS_DONE', defn(`ELEMENTS_DONE')`,$1')
+	DONE_SIZE(`sizeof(src->$1)')
+')
+define(`DISABLECHECK', `
+	pushdef(`DONE_SIZE')
+	pushdef(`DONE')
+$1
+	popdef(`DONE_SIZE')
+	popdef(`DONE')
+')
+dnl }}}
+dnl {{{ IF**
+define(`IFCALC', `ifelse(KIND, `calc', `$1', `$2')')
+define(`IFSTORE', `ifelse(KIND, `store', `$1', `$2')')
+define(`IFCALCSTORE', `IFSTORE(`$1', `IFCALC(`$1', `$2')')')
+define(`IFRESTORE', `ifelse(KIND, `restore', `$1', `$2')')
+define(`IFCOPY', `IFSTORE(`$1', `IFRESTORE(`$1', `$2')')')
+define(`IFCALCCOPY', `IFCALC(`$1', `IFCOPY(`$1', `$2')')')
+define(`IFDPRINT', `ifelse(KIND, `dprint', `$1', `$2')')
+define(`IFASM', `ifelse(KIND, `asm', `$1', `$2')')
+define(`IFDASM', `ifelse(KIND, `dasm', `$1', `$2')')
+dnl }}}
+EXPORT(`zend_op')
+EXPORT(`zend_op_array')
+EXPORT(`zend_function')
+EXPORT(`HashTable_zend_function')
+EXPORT(`zend_class_entry')
+EXPORT(`xc_classinfo_t')
+EXPORT(`xc_funcinfo_t')
+EXPORT(`xc_entry_t')
+EXPORT(`zval')
+
+include(srcdir`/processor/hashtable.m4')
+include(srcdir`/processor/string.m4')
+include(srcdir`/processor/struct.m4')
+include(srcdir`/processor/dispatch.m4')
+include(srcdir`/processor/head.m4')
+
+define(`IFNOTMEMCPY', `ifdef(`USEMEMCPY', `', `$1')')
+REDEF(`KIND', `calc') include(srcdir`/processor/processor.m4')
+REDEF(`KIND', `store') include(srcdir`/processor/processor.m4')
+REDEF(`KIND', `restore') include(srcdir`/processor/processor.m4')
+
+REDEF(`IFNOTMEMCPY', `$1')
+#ifdef HAVE_XCACHE_DPRINT
+REDEF(`KIND', `dprint') include(srcdir`/processor/processor.m4')
+#endif /* HAVE_XCACHE_DPRINT */
+#ifdef HAVE_XCACHE_DISASSEMBLER
+REDEF(`KIND', `dasm') include(srcdir`/processor/processor.m4')
+#endif /* HAVE_XCACHE_DISASSEMBLER */
+#ifdef HAVE_XCACHE_ASSEMBLER
+REDEF(`KIND', `asm') include(srcdir`/processor/processor.m4')
+#endif /* HAVE_XCACHE_ASSEMBLER */
+
+ifdef(`EXIT_PENDING', `m4exit(EXIT_PENDING)')
Index: /tags/1.3.0-rc1/processor/struct.m4
===================================================================
--- /tags/1.3.0-rc1/processor/struct.m4	(revision 623)
+++ /tags/1.3.0-rc1/processor/struct.m4	(revision 623)
@@ -0,0 +1,209 @@
+define(`pushdefFUNC_NAME', `
+	pushdef(`FUNC_NAME', `xc_`'KIND`'_`'ifelse(`$2', `', `$1', `$2')')
+')
+dnl {{{ DECL_STRUCT_P_FUNC(1:type, 2:name, 3:comma=;)
+define(`DECL_STRUCT_P_FUNC', `translit(
+	pushdefFUNC_NAME(`$1', `$2')
+	define(`DEFINED_'ifelse(`$2', `', `$1', `$2'), `')
+	ifdef(`EXPORT_'ifelse(`$2', `', `$1', `$2'), `void', `static void inline')
+	FUNC_NAME`'(
+		IFDPRINT( `const $1 * const src, int indent')
+		IFCALC(   `xc_processor_t *processor, const $1 * const src')
+		IFSTORE(  `xc_processor_t *processor, $1 *dst, const $1 * const src')
+		IFRESTORE(`xc_processor_t *processor, $1 *dst, const $1 * const src')
+		IFDASM(   `zval *dst, const $1 * const src')
+		IFASM(    `$1 *dst, const $1 * const src')
+		TSRMLS_DC
+	)ifelse(`$3', `', `;')
+	popdef(`FUNC_NAME')dnl
+, `
+', ` ')')
+dnl }}}
+dnl {{{ DEF_STRUCT_P_FUNC(1:type, 2:name, 3:body)
+define(`DEF_STRUCT_P_FUNC', `
+	pushdefFUNC_NAME(`$1', `$2')
+/* {`{'{ FUNC_NAME */
+	ifdef(`EXPORT_'ifelse(`$2', `', `$1', `$2'), `
+		/* export: DECL_STRUCT_P_FUNC(`$1', `$2') :export */
+	')
+DECL_STRUCT_P_FUNC(`$1', `$2', 1)
+	{
+		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)')
+			dnl SIZEOF_x COUNTOF_x can be both defined or both not
+			ifdef(`SIZEOF_$1', `
+				ifdef(`COUNTOF_$1', , `m4_errprint(`AUTOCHECK WARN: missing COUNTOF_$1')')
+			', `
+				define(`SIZEOF_$1', 0)
+			')
+			ifdef(`COUNTOF_$1', `
+				ifdef(`SIZEOF_$1', , `m4_errprint(`AUTOCHECK WARN: missing SIZEOF_$1')')
+			', `
+				define(`COUNTOF_$1', 0)
+			')
+			int assert_size = SIZEOF_$1, assert_count = COUNTOF_$1;
+			int done_size = 0, done_count = 0;
+			/* }}} */
+			IFRESTORE(`assert(xc_is_shm(src));')
+			IFCALCSTORE(`assert(!xc_is_shm(src));')
+			do {
+		')
+
+		ifdef(`USEMEMCPY', `IFCOPY(`
+			memcpy(dst, src, sizeof($1));
+			do {
+		')')
+
+		IFDPRINT(`
+			fprintf(stderr, "%s", "{\n");
+			indent ++;
+		')
+		$3`'
+		IFDPRINT(`
+			indent --;
+			INDENT()fprintf(stderr, "}\n");
+		')
+		ifdef(`SKIPASSERT_ONCE', `undefine(`SKIPASSERT_ONCE')', `
+			IFASSERT(`
+				/* {{{ check assert */
+				if (done_count != assert_count) {
+					fprintf(stderr
+						, "count assertion failed at %s `#'%d FUNC_NAME`' : unexpected:%d - expecting:%d = %d != 0\n"
+						, __FILE__, __LINE__
+						, done_count, assert_count, done_count - assert_count
+						);
+				}
+				if (done_size != assert_size) {
+					fprintf(stderr
+						, "size assertion failed at %s `#'%d FUNC_NAME`' : unexpected:%d - expecting:%d = %d != 0\n"
+						, __FILE__, __LINE__
+						, done_size, assert_size, done_size - assert_size
+						);
+				}
+				if (done_count != assert_count || done_size != assert_size) {
+					assert(0);
+				}
+				/* }}} */
+			')
+			ifdef(`ELEMENTSOF_$1', `
+				pushdef(`ELEMENTS_UNDONE', LIST_DIFF(defn(`ELEMENTSOF_$1'), defn(`ELEMENTS_DONE')))
+				ifelse(defn(`ELEMENTS_UNDONE'), , `m4_errprint(`AUTOCHECK INFO: $1: processor looks good')', `
+					m4_errprint(`AUTOCHECK ERROR: ====' KIND `$1 =================')
+					m4_errprint(`AUTOCHECK expected:' defn(`ELEMENTSOF_$1'))
+					m4_errprint(`AUTOCHECK missing :' defn(`ELEMENTS_UNDONE'))
+					define(`EXIT_PENDING', 1)
+				')
+				popdef(`ELEMENTS_UNDONE')
+			')
+		')
+		ifdef(`USEMEMCPY', `IFCOPY(`
+			} while (0);
+		')')
+		IFASSERT(`
+			} while (0);
+		')
+		popdef(`ELEMENTS_DONE')
+	}
+/* }`}'} */
+	popdef(`FUNC_NAME')
+')
+dnl }}}
+dnl {{{ STRUCT_P_EX(1:type, 2:dst, 3:src, 4:elm-name, 5:name=type, 6:&)
+define(`STRUCT_P_EX', `
+	DBG(`$0($*)')
+	pushdefFUNC_NAME(`$1', `$5')
+	ifdef(`DEFINED_'ifelse(`$5', `', `$1', `$5'), `', `m4_errprint(`Unknown struct "'ifelse(`$5', `', `$1', `$5')`"')')
+	assert(sizeof($1) == sizeof(($6 $3)[0]));
+	ifelse(`$6', `', `ALLOC(`$2', `$1')')
+	IFDASM(`do {
+		zval *zv;
+		ALLOC_INIT_ZVAL(zv);
+		array_init(zv);
+	')
+	FUNC_NAME`'(
+		IFDPRINT( `           $6 $3, indent')
+		IFCALC(   `processor, $6 $3')
+		IFSTORE(  `processor, $6 $2, $6 $3')
+		IFRESTORE(`processor, $6 $2, $6 $3')
+		IFDASM(   `zv, $6 $3')
+		IFASM(    `$6 $2, $6 $3')
+		TSRMLS_CC
+	);
+	IFDASM(`
+		add_assoc_zval_ex(dst, ZEND_STRS("$4"), zv);
+	} while (0);
+	')
+	popdef(`FUNC_NAME')
+	ifelse(`$6', , `FIXPOINTER_EX(`$1', `$2')')
+')
+dnl }}}
+dnl {{{ STRUCT_P(1:type, 2:elm, 3:name=type)
+define(`STRUCT_P', `
+	DBG(`$0($*)')
+	if (src->$2) {
+		IFDPRINT(`INDENT()`'fprintf(stderr, "$1:$2 ");')
+		STRUCT_P_EX(`$1', `dst->$2', `src->$2', `$2', `$3')
+	}
+	else {
+		IFDPRINT(`INDENT()`'fprintf(stderr, "$1:$2:\tNULL\n");')
+		COPYNULL_EX(`dst->$2', `$2')
+	}
+	DONE(`$2')
+')
+dnl }}}
+dnl {{{ STRUCT(1:type, 2:elm, 3:name=type)
+define(`STRUCT', `
+	DBG(`$0($*)')
+	assert(sizeof($1) == sizeof(src->$2));
+	IFDPRINT(`INDENT()`'fprintf(stderr, "$1:$2 ");')
+	STRUCT_P_EX(`$1', `dst->$2', `src->$2', `$2', `$3', `&')
+	DONE(`$2')
+')
+dnl }}}
+dnl {{{ STRUCT_ARRAY_I(1:count, 2:type, 3:elm, 4:name=type)
+define(`STRUCT_ARRAY_I', `
+pushdef(`i', `ii')
+STRUCT_ARRAY(`$1', `$2', `$3', `$4')
+popdef(`i')
+')
+dnl }}}
+dnl {{{ STRUCT_ARRAY(1:count, 2:type, 3:elm, 4:name=type)
+define(`STRUCT_ARRAY', `
+	if (src->$3) {
+		pushdefFUNC_NAME(`$2', `$4')
+		IFDASM(`
+			zval *arr;
+			ALLOC_INIT_ZVAL(arr);
+			array_init(arr);
+			for (i = 0; i < src->$1; i ++) {
+				zval *zv;
+
+				ALLOC_INIT_ZVAL(zv);
+				array_init(zv);
+				FUNC_NAME (zv, &(src->$3[i]) TSRMLS_CC);
+				add_next_index_zval(arr, zv);
+			}
+			add_assoc_zval_ex(dst, ZEND_STRS("$3"), arr);
+		', `
+			ALLOC(`dst->$3', `$2', `src->$1')
+			ifdef(`AFTER_ALLOC', AFTER_ALLOC)
+			for (i = 0; i < src->$1; i ++) {
+				DISABLECHECK(`
+					ifdef(`BEFORE_LOOP', `BEFORE_LOOP')
+					STRUCT(`$2', `$3[i]', `$4')
+				')
+			}
+		')dnl IFDASM
+		DONE(`$3')
+		popdef(`FUNC_NAME')
+	}
+	else {
+		COPYNULL(`$3')
+		ifdef(`AFTER_ALLOC', AFTER_ALLOC)
+	}
+')
+dnl }}}
Index: /tags/1.3.0-rc1/utils.c
===================================================================
--- /tags/1.3.0-rc1/utils.c	(revision 652)
+++ /tags/1.3.0-rc1/utils.c	(revision 652)
@@ -0,0 +1,841 @@
+
+#include "xcache.h"
+#include "stack.h"
+#include "xcache_globals.h"
+#include "utils.h"
+#ifdef ZEND_ENGINE_2_1
+#include "zend_vm.h"
+#endif
+#include "opcode_spec.h"
+#undef NDEBUG
+#include "assert.h"
+
+#ifndef max
+#define max(a, b) ((a) < (b) ? (b) : (a))
+#endif
+
+#ifndef ZEND_VM_SET_OPCODE_HANDLER
+#	define ZEND_VM_SET_OPCODE_HANDLER(opline) do { } while (0)
+#endif
+
+#define OP_ZVAL_DTOR(op) do { \
+	Z_UNSET_ISREF((op).u.constant); \
+	zval_dtor(&(op).u.constant); \
+} while(0)
+xc_compile_result_t *xc_compile_result_init(xc_compile_result_t *cr, /* {{{ */
+		zend_op_array *op_array,
+		HashTable *function_table,
+		HashTable *class_table)
+{
+	if (cr) {
+		cr->alloc = 0;
+	}
+	else {
+		cr = emalloc(sizeof(xc_compile_result_t));
+		cr->alloc = 1;
+	}
+	cr->op_array       = op_array;
+	cr->function_table = function_table;
+	cr->class_table    = class_table;
+	return cr;
+}
+/* }}} */
+xc_compile_result_t *xc_compile_result_init_cur(xc_compile_result_t *cr, zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	return xc_compile_result_init(cr, op_array, CG(function_table), CG(class_table));
+}
+/* }}} */
+void xc_compile_result_free(xc_compile_result_t *cr) /* {{{ */
+{
+	if (cr->alloc) {
+		efree(cr);
+	}
+}
+/* }}} */
+
+int xc_apply_function(zend_function *zf, apply_func_t applyer TSRMLS_DC) /* {{{ */
+{
+	switch (zf->type) {
+	case ZEND_USER_FUNCTION:
+	case ZEND_EVAL_CODE:
+		return applyer(&zf->op_array TSRMLS_CC);
+		break;
+
+	case ZEND_INTERNAL_FUNCTION:
+	case ZEND_OVERLOADED_FUNCTION:
+		break;
+
+	EMPTY_SWITCH_DEFAULT_CASE();
+	}
+	return 0;
+}
+/* }}} */
+typedef struct {
+	apply_func_t applyer;
+	zend_class_entry *ce;
+} xc_apply_method_info;
+int xc_apply_method(zend_function *zf, xc_apply_method_info *mi TSRMLS_DC) /* {{{ */
+{
+	/* avoid duplicate apply for shadowed method */
+#ifdef ZEND_ENGINE_2
+	if (mi->ce != zf->common.scope) {
+		/* fprintf(stderr, "avoided duplicate %s\n", zf->common.function_name); */
+		return 0;
+	}
+#else
+	char *name = zf->common.function_name;
+	int name_s = strlen(name) + 1;
+	zend_class_entry *ce;
+	zend_function *ptr;
+
+	for (ce = mi->ce->parent; ce; ce = ce->parent) {
+		if (zend_hash_find(&ce->function_table, name, name_s, (void **) &ptr) == SUCCESS) {
+			if (ptr->op_array.refcount == zf->op_array.refcount) {
+				return 0;
+			}
+		}
+	}
+#endif
+	return xc_apply_function(zf, mi->applyer TSRMLS_CC);
+}
+/* }}} */
+#if 0
+int xc_apply_class(zend_class_entry *ce, apply_func_t applyer TSRMLS_DC) /* {{{ */
+{
+	xc_apply_method_info mi;
+
+	mi.applyer = applyer;
+	mi.ce      = ce;
+	zend_hash_apply_with_argument(&(ce->function_table), (apply_func_arg_t) xc_apply_method, &mi TSRMLS_CC);
+	return 0;
+}
+/* }}} */
+#endif
+static int xc_apply_cest(xc_cest_t *cest, apply_func_t applyer TSRMLS_DC) /* {{{ */
+{
+	xc_apply_method_info mi;
+
+	mi.applyer = applyer;
+	mi.ce      = CestToCePtr(*cest);
+	zend_hash_apply_with_argument(&(CestToCePtr(*cest)->function_table), (apply_func_arg_t) xc_apply_method, &mi TSRMLS_CC);
+	return 0;
+}
+/* }}} */
+int xc_apply_op_array(xc_compile_result_t *cr, apply_func_t applyer TSRMLS_DC) /* {{{ */
+{
+	zend_hash_apply_with_argument(cr->function_table, (apply_func_arg_t) xc_apply_function, (void *) applyer TSRMLS_CC);
+	zend_hash_apply_with_argument(cr->class_table, (apply_func_arg_t) xc_apply_cest, (void *) applyer TSRMLS_CC);
+
+	return applyer(cr->op_array TSRMLS_CC);
+}
+/* }}} */
+
+int xc_undo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	zend_op *opline, *end;
+
+	if (!op_array->done_pass_two) {
+		return 0;
+	}
+
+	opline = op_array->opcodes;
+	end = opline + op_array->last;
+	while (opline < end) {
+#ifdef ZEND_ENGINE_2_1
+		switch (opline->opcode) {
+#ifdef ZEND_GOTO
+			case ZEND_GOTO:
+#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);
+				break;
+			case ZEND_JMPZ:
+			case ZEND_JMPNZ:
+			case ZEND_JMPZ_EX:
+			case ZEND_JMPNZ_EX:
+#ifdef ZEND_JMP_SET
+			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);
+				break;
+		}
+#endif
+		opline++;
+	}
+	op_array->done_pass_two = 0;
+
+	return 0;
+}
+/* }}} */
+int xc_redo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	zend_op *opline, *end;
+
+	if (op_array->done_pass_two) {
+		return 0;
+	}
+
+	/*
+	op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
+	op_array->size = op_array->last;
+	*/
+
+	opline = op_array->opcodes;
+	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);
+		}
+#ifdef ZEND_ENGINE_2_1
+		switch (opline->opcode) {
+#ifdef ZEND_GOTO
+			case ZEND_GOTO:
+#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;
+				break;
+			case ZEND_JMPZ:
+			case ZEND_JMPNZ:
+			case ZEND_JMPZ_EX:
+			case ZEND_JMPNZ_EX:
+#ifdef ZEND_JMP_SET
+			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;
+				break;
+		}
+		ZEND_VM_SET_OPCODE_HANDLER(opline);
+#endif
+		opline++;
+	}
+
+	op_array->done_pass_two = 1;
+	return 0;
+}
+/* }}} */
+
+#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) /* {{{ */
+{
+#ifdef ZEND_ENGINE_2
+	if ((znode->op_type != IS_UNUSED && (spec == OPSPEC_UCLASS || spec == OPSPEC_CLASS)) ||
+			spec == OPSPEC_FETCH) {
+		if (tofix) {
+			switch (znode->op_type) {
+			case IS_VAR:
+			case IS_TMP_VAR:
+				break;
+
+			default:
+				/* TODO: data lost, find a way to keep it */
+				/* assert(znode->op_type == IS_CONST); */
+				znode->op_type = IS_TMP_VAR;
+			}
+		}
+	}
+	switch (znode->op_type) {
+	case IS_TMP_VAR:
+	case IS_VAR:
+		if (tofix) {
+			znode->u.var /= sizeof(temp_variable);
+		}
+		else {
+			znode->u.var *= sizeof(temp_variable);
+		}
+	}
+#endif
+}
+/* }}} */
+
+static void xc_fix_opcode_ex(zend_op_array *op_array, int tofix TSRMLS_DC) /* {{{ */
+{
+	zend_op *opline;
+	zend_uint i;
+
+	opline = op_array->opcodes;
+	for (i = 0; i < op_array->last; i ++, opline ++) {
+		/* 3rd optimizer may have ... */
+		if (opline->opcode < xc_get_opcode_spec_count()) {
+			const xc_opcode_spec_t *spec;
+			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);
+		}
+	}
+}
+/* }}} */
+int xc_fix_opcode(zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	xc_fix_opcode_ex(op_array, 1 TSRMLS_CC);
+	return 0;
+}
+/* }}} */
+int xc_undo_fix_opcode(zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	xc_fix_opcode_ex(op_array, 0 TSRMLS_CC);
+
+	return 0;
+}
+/* }}} */
+#endif
+
+int xc_foreach_early_binding_class(zend_op_array *op_array, void (*callback)(zend_op *opline, int oplineno, void *data TSRMLS_DC), void *data TSRMLS_DC) /* {{{ */
+{
+	zend_op *opline, *begin, *end, *next = NULL;
+
+	opline = begin = op_array->opcodes;
+	end = opline + op_array->last;
+	while (opline < end) {
+		switch (opline->opcode) {
+#ifdef ZEND_GOTO
+			case ZEND_GOTO:
+#endif
+			case ZEND_JMP:
+				next = begin + opline->op1.u.opline_num;
+				break;
+
+			case ZEND_JMPZNZ:
+				next = begin + max(opline->op2.u.opline_num, opline->extended_value);
+				break;
+
+			case ZEND_JMPZ:
+			case ZEND_JMPNZ:
+			case ZEND_JMPZ_EX:
+			case ZEND_JMPNZ_EX:
+#ifdef ZEND_JMP_SET
+			case ZEND_JMP_SET:
+#endif
+				next = begin + opline->op2.u.opline_num;
+				break;
+
+			case ZEND_RETURN:
+				opline = end;
+				break;
+
+#ifdef ZEND_ENGINE_2
+			case ZEND_DECLARE_INHERITED_CLASS:
+				callback(opline, opline - begin, data TSRMLS_CC);
+				break;
+#else
+			case ZEND_DECLARE_FUNCTION_OR_CLASS:
+				if (opline->extended_value == ZEND_DECLARE_INHERITED_CLASS) {
+					callback(opline, opline - begin, data TSRMLS_CC);
+				}
+				break;
+#endif
+		}
+
+		if (opline < next) {
+			opline = next;
+		}
+		else {
+			opline ++;
+		}
+	}
+	return SUCCESS;
+}
+/* }}} */
+#ifndef ZEND_COMPILE_DELAYED_BINDING
+static int xc_do_early_binding(zend_op_array *op_array, HashTable *class_table, int oplineno TSRMLS_DC) /* {{{ */
+{
+	zend_op *opline;
+
+	TRACE("binding %d", oplineno);
+	assert(oplineno >= 0);
+
+	/* do early binding */
+	opline = &(op_array->opcodes[oplineno]);
+
+	switch (opline->opcode) {
+#ifdef ZEND_ENGINE_2
+	case ZEND_DECLARE_INHERITED_CLASS:
+		{
+			zval *parent_name;
+			zend_class_entry **pce;
+
+			/* don't early-bind classes that implement interfaces */
+			if ((opline + 1)->opcode == ZEND_FETCH_CLASS && (opline + 2)->opcode == ZEND_ADD_INTERFACE) {
+				return FAILURE;
+			}
+
+			parent_name = &(opline - 1)->op2.u.constant;
+			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) {
+				return FAILURE;
+			}
+
+			if (do_bind_inherited_class(opline, class_table, *pce, 1 TSRMLS_CC) == NULL) {
+				return FAILURE;
+			}
+		}
+
+		/* clear unnecessary ZEND_FETCH_CLASS opcode */
+		if (opline > op_array->opcodes
+		 && (opline - 1)->opcode == ZEND_FETCH_CLASS) {
+			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));
+			OP_ZVAL_DTOR(fetch_class_opline->op2);
+			fetch_class_opline->opcode = ZEND_NOP;
+			ZEND_VM_SET_OPCODE_HANDLER(fetch_class_opline);
+			memset(&fetch_class_opline->op1, 0, sizeof(znode));
+			memset(&fetch_class_opline->op2, 0, sizeof(znode));
+			SET_UNUSED(fetch_class_opline->op1);
+			SET_UNUSED(fetch_class_opline->op2);
+			SET_UNUSED(fetch_class_opline->result);
+		}
+
+		/* clear unnecessary ZEND_VERIFY_ABSTRACT_CLASS opcode */
+		if ((opline + 1)->opcode == ZEND_VERIFY_ABSTRACT_CLASS) {
+			zend_op *abstract_op = opline + 1;
+			memset(abstract_op, 0, sizeof(abstract_op[0]));
+			abstract_op->lineno = 0;
+			SET_UNUSED(abstract_op->op1);
+			SET_UNUSED(abstract_op->op2);
+			SET_UNUSED(abstract_op->result);
+			abstract_op->opcode = ZEND_NOP;
+			ZEND_VM_SET_OPCODE_HANDLER(abstract_op);
+		}
+#else
+	case ZEND_DECLARE_FUNCTION_OR_CLASS:
+		if (do_bind_function_or_class(opline, NULL, class_table, 1) == FAILURE) {
+			return FAILURE;
+		}
+#endif
+		break;
+
+	default:
+		return FAILURE;
+	}
+
+	zend_hash_del(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len);
+	OP_ZVAL_DTOR(opline->op1);
+	OP_ZVAL_DTOR(opline->op2);
+	opline->opcode = ZEND_NOP;
+	ZEND_VM_SET_OPCODE_HANDLER(opline);
+	memset(&opline->op1, 0, sizeof(znode));
+	memset(&opline->op2, 0, sizeof(znode));
+	SET_UNUSED(opline->op1);
+	SET_UNUSED(opline->op2);
+	return SUCCESS;
+}
+/* }}} */
+#endif
+
+#ifdef HAVE_XCACHE_CONSTANT
+void xc_install_constant(char *filename, zend_constant *constant, zend_uchar type, zstr key, uint len, ulong h TSRMLS_DC) /* {{{ */
+{
+	if (zend_u_hash_add(EG(zend_constants), type, key, len,
+				constant, sizeof(zend_constant),
+				NULL
+				) == FAILURE) {
+		CG(zend_lineno) = 0;
+#ifdef IS_UNICODE
+		zend_error(E_NOTICE, "Constant %R already defined", type, key);
+#else
+		zend_error(E_NOTICE, "Constant %s already defined", key);
+#endif
+		free(ZSTR_V(constant->name));
+		if (!(constant->flags & CONST_PERSISTENT)) {
+			zval_dtor(&constant->value);
+		}
+	}
+}
+/* }}} */
+#endif
+void xc_install_function(char *filename, zend_function *func, zend_uchar type, zstr key, uint len, ulong h TSRMLS_DC) /* {{{ */
+{
+	zend_bool istmpkey;
+
+	if (func->type == ZEND_USER_FUNCTION) {
+#ifdef IS_UNICODE
+		istmpkey = (type == IS_STRING && ZSTR_S(key)[0] == 0) || ZSTR_U(key)[0] == 0;
+#else
+		istmpkey = ZSTR_S(key)[0] == 0;
+#endif
+		if (istmpkey) {
+			zend_u_hash_update(CG(function_table), type, key, len,
+						func, sizeof(zend_op_array),
+						NULL
+						);
+		}
+		else if (zend_u_hash_add(CG(function_table), type, key, len,
+					func, sizeof(zend_op_array),
+					NULL
+					) == FAILURE) {
+			CG(zend_lineno) = ZESW(func->op_array.opcodes[0].lineno, func->op_array.line_start);
+#ifdef IS_UNICODE
+			zend_error(E_ERROR, "Cannot redeclare %R()", type, key);
+#else
+			zend_error(E_ERROR, "Cannot redeclare %s()", key);
+#endif
+		}
+	}
+}
+/* }}} */
+ZESW(xc_cest_t *, void) xc_install_class(char *filename, xc_cest_t *cest, int oplineno, zend_uchar type, zstr key, uint len, ulong h TSRMLS_DC) /* {{{ */
+{
+	zend_bool istmpkey;
+	zend_class_entry *cep = CestToCePtr(*cest);
+	ZESW(void *stored_ce_ptr, NOTHING);
+
+#ifdef IS_UNICODE
+	istmpkey = (type == IS_STRING && ZSTR_S(key)[0] == 0) || ZSTR_U(key)[0] == 0;
+#else
+	istmpkey = ZSTR_S(key)[0] == 0;
+#endif
+	if (istmpkey) {
+		zend_u_hash_quick_update(CG(class_table), type, key, len, h,
+					cest, sizeof(xc_cest_t),
+					ZESW(&stored_ce_ptr, NULL)
+					);
+#ifndef ZEND_COMPILE_DELAYED_BINDING
+		if (oplineno != -1) {
+			xc_do_early_binding(CG(active_op_array), CG(class_table), oplineno TSRMLS_CC);
+		}
+#endif
+	}
+	else if (zend_u_hash_quick_add(CG(class_table), type, key, len, h,
+				cest, sizeof(xc_cest_t),
+				ZESW(&stored_ce_ptr, NULL)
+				) == FAILURE) {
+		CG(zend_lineno) = ZESW(0, cep->line_start);
+#ifdef IS_UNICODE
+		zend_error(E_ERROR, "Cannot redeclare class %R", type, cep->name);
+#else
+		zend_error(E_ERROR, "Cannot redeclare class %s", cep->name);
+#endif
+		assert(oplineno == -1);
+	}
+	ZESW(return (xc_cest_t *) stored_ce_ptr, NOTHING);
+}
+/* }}} */
+
+/* sandbox {{{ */
+#undef TG
+#undef OG
+#define TG(x) (sandbox->tmp_##x)
+#define OG(x) (sandbox->orig_##x)
+/* }}} */
+#ifdef ZEND_ENGINE_2_1
+static zend_bool xc_auto_global_callback(char *name, uint name_len TSRMLS_DC) /* {{{ */
+{
+	zend_auto_global *auto_global;
+	if (zend_u_hash_find(CG(auto_globals), UG(unicode) ? IS_UNICODE : IS_STRING, ZSTR(name), name_len + 1, (void **) &auto_global) == FAILURE) {
+		return 1;
+	}
+	return 0;
+}
+/* }}} */
+static int xc_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
+{
+	if (auto_global->auto_global_callback) {
+		auto_global->armed = 1;
+		auto_global->auto_global_callback = xc_auto_global_callback;
+	}
+	else {
+		auto_global->armed = 0;
+	}
+	return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+#endif
+
+void xc_hash_copy_if(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, xc_if_func_t checker) /* {{{ */
+{
+	Bucket *p;
+	void *new_entry;
+	zend_bool setTargetPointer;
+
+	setTargetPointer = !target->pInternalPointer;
+	p = source->pListHead;
+	while (p) {
+		if (checker(p->pData)) {
+			if (setTargetPointer && source->pInternalPointer == p) {
+				target->pInternalPointer = NULL;
+			}
+			if (p->nKeyLength) {
+				zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &new_entry);
+			} else {
+				zend_hash_index_update(target, p->h, p->pData, size, &new_entry);
+			}
+			if (pCopyConstructor) {
+				pCopyConstructor(new_entry);
+			}
+		}
+		p = p->pListNext;
+	}
+	if (!target->pInternalPointer) {
+		target->pInternalPointer = target->pListHead;
+	}
+}
+/* }}} */
+#ifdef HAVE_XCACHE_CONSTANT
+static zend_bool xc_is_internal_zend_constant(zend_constant *c) /* {{{ */
+{
+	return (c->flags & CONST_PERSISTENT) ? 1 : 0;
+}
+/* }}} */
+void xc_zend_constant_ctor(zend_constant *c) /* {{{ */
+{
+	assert((c->flags & CONST_PERSISTENT));
+#ifdef IS_UNICODE
+	c->name.u = zend_ustrndup(c->name.u, c->name_len - 1);
+#else
+	c->name = zend_strndup(c->name, c->name_len - 1);
+#endif
+}
+/* }}} */
+void xc_zend_constant_dtor(zend_constant *c) /* {{{ */
+{
+	free(ZSTR_U(c->name));
+}
+/* }}} */
+void xc_copy_internal_zend_constants(HashTable *target, HashTable *source) /* {{{ */
+{
+	zend_constant tmp_const;
+	xc_hash_copy_if(target, source, (copy_ctor_func_t) xc_zend_constant_ctor, (void *) &tmp_const, sizeof(zend_constant), (xc_if_func_t) xc_is_internal_zend_constant);
+}
+/* }}} */
+#endif
+xc_sandbox_t *xc_sandbox_init(xc_sandbox_t *sandbox, char *filename TSRMLS_DC) /* {{{ */
+{
+	HashTable *h;
+
+	if (sandbox) {
+		memset(sandbox, 0, sizeof(sandbox[0]));
+	}
+	else {
+		ECALLOC_ONE(sandbox);
+		sandbox->alloc = 1;
+	}
+
+	memcpy(&OG(included_files), &EG(included_files), sizeof(EG(included_files)));
+
+#ifdef HAVE_XCACHE_CONSTANT
+	OG(zend_constants) = EG(zend_constants);
+	EG(zend_constants) = &TG(zend_constants);
+#endif
+
+	OG(function_table) = CG(function_table);
+	CG(function_table) = &TG(function_table);
+
+	OG(class_table) = CG(class_table);
+	CG(class_table) = &TG(class_table);
+	EG(class_table) = CG(class_table);
+
+#ifdef ZEND_ENGINE_2_1
+	OG(auto_globals) = CG(auto_globals);
+	CG(auto_globals) = &TG(auto_globals);
+#endif
+
+	TG(included_files) = &EG(included_files);
+
+	zend_hash_init_ex(TG(included_files), 5, NULL, NULL, 0, 1);
+#ifdef HAVE_XCACHE_CONSTANT
+	h = OG(zend_constants);
+	zend_hash_init_ex(&TG(zend_constants),  20, NULL, h->pDestructor, h->persistent, h->bApplyProtection);
+	xc_copy_internal_zend_constants(&TG(zend_constants), &XG(internal_constant_table));
+	{
+		zend_constant tmp_const;
+		zend_hash_copy(&TG(zend_constants), &XG(internal_constant_table), (copy_ctor_func_t) xc_zend_constant_ctor, (void *) &tmp_const, sizeof(tmp_const));
+	}
+	TG(internal_constant_tail) = TG(zend_constants).pListTail;
+#endif
+	h = OG(function_table);
+	zend_hash_init_ex(&TG(function_table), 128, NULL, h->pDestructor, h->persistent, h->bApplyProtection);
+	{
+		zend_function tmp_func;
+		zend_hash_copy(&TG(function_table), &XG(internal_function_table), NULL, (void *) &tmp_func, sizeof(tmp_func));
+	}
+	TG(internal_function_tail) = TG(function_table).pListTail;
+
+	h = OG(class_table);
+	zend_hash_init_ex(&TG(class_table),     16, NULL, h->pDestructor, h->persistent, h->bApplyProtection);
+#if 0 && TODO
+	{
+		xc_cest_t tmp_cest;
+		zend_hash_copy(&TG(class_table), &XG(internal_class_table), NULL, (void *) &tmp_cest, sizeof(tmp_cest));
+	}
+#endif
+	TG(internal_class_tail) = TG(class_table).pListTail;
+
+#ifdef ZEND_ENGINE_2_1
+	/* shallow copy, don't destruct */
+	h = OG(auto_globals);
+	zend_hash_init_ex(&TG(auto_globals),     8, NULL,           NULL, h->persistent, h->bApplyProtection);
+	{
+		zend_auto_global tmp_autoglobal;
+
+		zend_hash_copy(&TG(auto_globals), OG(auto_globals), NULL, (void *) &tmp_autoglobal, sizeof(tmp_autoglobal));
+		zend_hash_apply(&TG(auto_globals), (apply_func_t) xc_auto_global_arm TSRMLS_CC);
+	}
+#endif
+
+	sandbox->filename = filename;
+
+#ifdef E_STRICT
+	sandbox->orig_user_error_handler_error_reporting = EG(user_error_handler_error_reporting);
+	EG(user_error_handler_error_reporting) &= ~E_STRICT;
+#endif
+
+#ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES
+	sandbox->orig_compiler_options = CG(compiler_options);
+	/* Using ZEND_COMPILE_IGNORE_INTERNAL_CLASSES for ZEND_FETCH_CLASS_RT_NS_CHECK
+	 */
+	CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES | ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_DELAYED_BINDING;
+#endif
+
+	return sandbox;
+}
+/* }}} */
+#ifndef ZEND_COMPILE_DELAYED_BINDING
+static void xc_early_binding_cb(zend_op *opline, int oplineno, void *data TSRMLS_DC) /* {{{ */
+{
+	xc_sandbox_t *sandbox = (xc_sandbox_t *) data;
+	xc_do_early_binding(CG(active_op_array), OG(class_table), oplineno TSRMLS_CC);
+}
+/* }}} */
+#endif
+static void xc_sandbox_install(xc_sandbox_t *sandbox, xc_install_action_t install TSRMLS_DC) /* {{{ */
+{
+	zend_uint i;
+	Bucket *b;
+
+#ifdef HAVE_XCACHE_CONSTANT
+	b = TG(internal_constant_tail) ? TG(internal_constant_tail)->pListNext : TG(zend_constants).pListHead;
+	/* install constants */
+	while (b != NULL) {
+		zend_constant *c = (zend_constant*) b->pData;
+		xc_install_constant(sandbox->filename, c,
+				BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC);
+		b = b->pListNext;
+	}
+#endif
+
+	b = TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead;
+	/* install function */
+	while (b != NULL) {
+		zend_function *func = (zend_function*) b->pData;
+		xc_install_function(sandbox->filename, func,
+				BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC);
+		b = b->pListNext;
+	}
+
+	b = TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead;
+	/* install class */
+	while (b != NULL) {
+		xc_install_class(sandbox->filename, (xc_cest_t*) b->pData, -1,
+				BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC);
+		b = b->pListNext;
+	}
+
+#ifdef ZEND_ENGINE_2_1
+	/* trigger auto_globals jit */
+	for (b = TG(auto_globals).pListHead; b != NULL; b = b->pListNext) {
+		zend_auto_global *auto_global = (zend_auto_global *) b->pData;
+		/* check if actived */
+		if (auto_global->auto_global_callback && !auto_global->armed) {
+			zend_u_is_auto_global(BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), auto_global->name_len TSRMLS_CC);
+		}
+	}
+#endif
+
+	if (install != XC_InstallNoBinding) {
+#ifdef ZEND_COMPILE_DELAYED_BINDING
+		zend_do_delayed_early_binding(CG(active_op_array) TSRMLS_CC);
+#else
+		xc_undo_pass_two(CG(active_op_array) TSRMLS_CC);
+		xc_foreach_early_binding_class(CG(active_op_array), xc_early_binding_cb, (void *) sandbox TSRMLS_CC);
+		xc_redo_pass_two(CG(active_op_array) TSRMLS_CC);
+#endif
+	}
+
+	i = 1;
+	zend_hash_add(&OG(included_files), sandbox->filename, strlen(sandbox->filename) + 1, (void *)&i, sizeof(int), NULL);
+}
+/* }}} */
+void xc_sandbox_free(xc_sandbox_t *sandbox, xc_install_action_t install TSRMLS_DC) /* {{{ */
+{
+	/* restore first first install function/class */
+#ifdef HAVE_XCACHE_CONSTANT
+	EG(zend_constants) = OG(zend_constants);
+#endif
+	CG(function_table) = OG(function_table);
+	CG(class_table)    = OG(class_table);
+	EG(class_table)    = CG(class_table);
+#ifdef ZEND_ENGINE_2_1
+	CG(auto_globals)   = OG(auto_globals);
+#endif
+
+	if (install != XC_NoInstall) {
+		CG(in_compilation)    = 1;
+		CG(compiled_filename) = sandbox->filename;
+		CG(zend_lineno)       = 0;
+		xc_sandbox_install(sandbox, install TSRMLS_CC);
+		CG(in_compilation)    = 0;
+		CG(compiled_filename) = NULL;
+
+		/* no free as it's installed */
+#ifdef HAVE_XCACHE_CONSTANT
+		TG(zend_constants).pDestructor = NULL;
+#endif
+		TG(function_table).pDestructor = NULL;
+		TG(class_table).pDestructor = NULL;
+	}
+
+	/* destroy all the tmp */
+#ifdef HAVE_XCACHE_CONSTANT
+	zend_hash_destroy(&TG(zend_constants));
+#endif
+	zend_hash_destroy(&TG(function_table));
+	zend_hash_destroy(&TG(class_table));
+#ifdef ZEND_ENGINE_2_1
+	zend_hash_destroy(&TG(auto_globals));
+#endif
+	zend_hash_destroy(TG(included_files));
+
+	/* restore orig here, as EG/CG holded tmp before */
+	memcpy(&EG(included_files), &OG(included_files), sizeof(EG(included_files)));
+
+#ifdef E_STRICT
+	EG(user_error_handler_error_reporting) = sandbox->orig_user_error_handler_error_reporting;
+#endif
+
+#ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES
+	CG(compiler_options) = sandbox->orig_compiler_options;
+#endif
+
+	if (sandbox->alloc) {
+		efree(sandbox);
+	}
+}
+/* }}} */
+int xc_vtrace(const char *fmt, va_list args) /* {{{ */
+{
+	return vfprintf(stderr, fmt, args);
+}
+/* }}} */
+int xc_trace(const char *fmt, ...) /* {{{ */
+{
+	va_list args;
+	int ret;
+
+	va_start(args, fmt);
+	ret = xc_vtrace(fmt, args);
+	va_end(args);
+	return ret;
+}
+/* }}} */
Index: /tags/1.3.0-rc1/mkopcode.awk
===================================================================
--- /tags/1.3.0-rc1/mkopcode.awk	(revision 626)
+++ /tags/1.3.0-rc1/mkopcode.awk	(revision 626)
@@ -0,0 +1,77 @@
+#! /usr/bin/awk -f
+# vim:ts=4:sw=4
+# process zend_vm_def.h or zend_compile.h
+BEGIN {
+	FS=" "
+	max = 0;
+}
+
+/^ZEND_VM_HANDLER\(/ {
+	# regex from php5.1+/Zend/zend_vm_gen.php
+	gsub(/ +/, "");
+	if (!match($0, /^ZEND_VM_HANDLER\(([0-9]+),([A-Z_]+),([A-Z|]+),([A-Z|]+)\)/)) {
+		print "error unmatch $0";
+		exit;
+	}
+	# life is hard without 3rd argument of match()
+	sub(/^ZEND_VM_HANDLER\(/, "");
+	id = $0;
+	sub(/,.*/, "", id); # chop
+	id = 0 + id;
+	sub(/^([0-9]+),/, "");
+	sub(/,.*/, ""); # chop
+	name = $0;
+	if (max < id) {
+		max = id;
+	}
+	opcodes[id] = name;
+	next;
+}
+
+/^#define +ZEND_[A-Z_]+[\t ]+[[:digit:]]+$/ {
+	id = 0 + $3;
+	name = $2;
+	if (max < id) {
+		max = id;
+	}
+	opcodes[id] = name;
+	next;
+}
+
+/end of block/ {
+	exit;
+}
+
+END {
+	mymax = 112;
+	if (max < mymax) {
+		for (i = max + 1; i <= mymax; i ++) {
+			opcodes[i] = "UNDEF";
+		}
+		max = mymax;
+		opcodes[110] = "ZEND_DO_FCALL_BY_FUNC";
+		opcodes[111] = "ZEND_INIT_FCALL_BY_FUNC";
+		opcodes[112] = "UNDEF";
+	}
+	printf "/* size = %d */\n", max + 1;
+	print "static const char *const xc_opcode_names[] = {";
+	for (i = 0; i <= max; i ++) {
+		if (i != 0) {
+			print ",";
+		}
+		printf "/* %d */\t", i
+		if (i in opcodes) {
+			name = opcodes[i];
+			sub(/^ZEND_/, "", name);
+			printf "\"%s\"", name;
+		}
+		else if (i == 137) {
+			printf "\"%s\"", "OP_DATA";
+		}
+		else {
+			printf "\"UNDEF\"";
+		}
+	}
+	print "";
+	print "};";
+}
Index: /tags/1.3.0-rc1/AUTHORS
===================================================================
--- /tags/1.3.0-rc1/AUTHORS	(revision 394)
+++ /tags/1.3.0-rc1/AUTHORS	(revision 394)
@@ -0,0 +1,1 @@
+mOo <phpxcache@gmail.com>
Index: /tags/1.3.0-rc1/stack.c
===================================================================
--- /tags/1.3.0-rc1/stack.c	(revision 593)
+++ /tags/1.3.0-rc1/stack.c	(revision 593)
@@ -0,0 +1,62 @@
+#include <stdlib.h>
+#include <assert.h>
+#include "stack.h"
+typedef xc_stack_t* S;
+
+void xc_stack_init_ex(S stack, int initsize)
+{
+	stack->cnt = 0;
+	stack->size = initsize;
+	stack->data = malloc(sizeof(void *) * stack->size);
+}
+
+void xc_stack_destroy(S stack)
+{
+	free(stack->data);
+}
+
+void xc_stack_push(S stack, void *item)
+{
+	if (stack->cnt == stack->size) {
+		stack->size <<= 1;
+		stack->data = realloc(stack->data, sizeof(void *) * stack->size);
+	}
+	stack->data[stack->cnt++] = item;
+}
+
+void* xc_stack_pop(S stack)
+{
+	assert(stack != NULL && stack->size > 0);
+	return stack->data[--stack->cnt];
+}
+
+void* xc_stack_top(S stack)
+{
+	assert(stack != NULL && stack->cnt > 0);
+	return stack->data[stack->cnt-1];
+}
+
+void* xc_stack_get(S stack, int n)
+{
+	assert(stack != NULL && stack->cnt > 0);
+	return stack->data[n];
+}
+
+int xc_stack_count(S stack)
+{
+	assert(stack != NULL);
+	return stack->cnt;
+}
+
+void xc_stack_reverse(S stack)
+{
+	int i, j;
+	void *tmp;
+
+	assert(stack != NULL);
+	for (i = 0, j = stack->cnt - 1; i < j; i ++, j --) {
+		tmp = stack->data[i];
+		stack->data[i] = stack->data[j];
+		stack->data[j] = tmp;
+	}
+}
Index: /tags/1.3.0-rc1/utils.h
===================================================================
--- /tags/1.3.0-rc1/utils.h	(revision 641)
+++ /tags/1.3.0-rc1/utils.h	(revision 641)
@@ -0,0 +1,129 @@
+#include "php.h"
+#include "xcache.h"
+
+#ifdef XCACHE_DEBUG
+#	define IFDEBUG(x) (x)
+int xc_vtrace(const char *fmt, va_list args);
+int xc_trace(const char *fmt, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
+
+#	ifdef ZEND_WIN32
+static inline int TRACE(const char *fmt, ...) 
+{
+	va_list args;
+	int ret;
+
+	va_start(args, fmt);
+	ret = xc_vtrace(fmt, args);
+	va_end(args);
+	return ret;
+}
+#	else
+#		define TRACE(fmt, ...) \
+		xc_trace("%s:%d: " fmt "\r\n", __FILE__, __LINE__, __VA_ARGS__)
+#	endif /* ZEND_WIN32 */
+#   undef NDEBUG
+#   undef inline
+#   define inline
+#else /* XCACHE_DEBUG */
+
+#	ifdef ZEND_WIN32
+static inline int TRACE_DUMMY(const char *fmt, ...)
+{
+	return 0;
+}
+#		define TRACE 1 ? 0 : TRACE_DUMMY
+#	else
+#		define TRACE(fmt, ...) do { } while (0)
+#	endif /* ZEND_WIN32 */
+
+#	define IFDEBUG(x) do { } while (0)
+#   ifndef NDEBUG
+#       define NDEBUG
+#   endif
+#endif /* XCACHE_DEBUG */
+#include <assert.h>
+
+typedef struct {
+	int alloc;
+	zend_op_array *op_array;
+	HashTable *function_table;
+	HashTable *class_table;
+} xc_compile_result_t;
+
+xc_compile_result_t *xc_compile_result_init(xc_compile_result_t *cr,
+		zend_op_array *op_array,
+		HashTable *function_table,
+		HashTable *class_table);
+void xc_compile_result_free(xc_compile_result_t *cr);
+xc_compile_result_t *xc_compile_result_init_cur(xc_compile_result_t *cr, zend_op_array *op_array TSRMLS_DC);
+/* apply func */
+int xc_apply_function(zend_function *zf, apply_func_t applyer TSRMLS_DC);
+int xc_apply_class(zend_class_entry *ce, apply_func_t applyer TSRMLS_DC);
+int xc_apply_op_array(xc_compile_result_t *cr, apply_func_t applyer TSRMLS_DC);
+
+int xc_undo_pass_two(zend_op_array *op_array TSRMLS_DC);
+int xc_redo_pass_two(zend_op_array *op_array TSRMLS_DC);
+int xc_fix_opcode(zend_op_array *op_array TSRMLS_DC);
+int xc_undo_fix_opcode(zend_op_array *op_array TSRMLS_DC);
+zend_uchar xc_get_fixed_opcode(zend_uchar opcode, int line);
+
+int xc_foreach_early_binding_class(zend_op_array *op_array, void (*callback)(zend_op *opline, int oplineno, void *data TSRMLS_DC), void *data TSRMLS_DC);
+
+/* installer */
+#ifdef HAVE_XCACHE_CONSTANT
+void xc_install_constant(char *filename, zend_constant *constant, zend_uchar type, zstr key, uint len, ulong h TSRMLS_DC);
+#endif
+void xc_install_function(char *filename, zend_function *func, zend_uchar type, zstr key, uint len, ulong h TSRMLS_DC);
+ZESW(xc_cest_t *, void) xc_install_class(char *filename, xc_cest_t *cest, int oplineno, zend_uchar type, zstr key, uint len, ulong h TSRMLS_DC);
+
+/* sandbox */
+typedef struct {
+	int alloc;
+	char *filename;
+
+	HashTable orig_included_files;
+	HashTable *tmp_included_files;
+
+#ifdef HAVE_XCACHE_CONSTANT
+	HashTable *orig_zend_constants;
+	HashTable tmp_zend_constants;
+#endif
+	HashTable *orig_function_table;
+	HashTable *orig_class_table;
+	HashTable *orig_auto_globals;
+	HashTable tmp_function_table;
+	HashTable tmp_class_table;
+	HashTable tmp_auto_globals;
+#ifdef HAVE_XCACHE_CONSTANT
+	Bucket    *tmp_internal_constant_tail;
+#endif
+	Bucket    *tmp_internal_function_tail;
+	Bucket    *tmp_internal_class_tail;
+
+#ifdef E_STRICT
+	int orig_user_error_handler_error_reporting;
+#endif
+
+#ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES
+	zend_uint orig_compiler_options;
+#endif
+} xc_sandbox_t;
+
+typedef enum _xc_install_action_t {
+    XC_NoInstall,
+    XC_Install,
+    XC_InstallNoBinding
+} xc_install_action_t;
+
+void xc_zend_class_add_ref(zend_class_entry ZESW(*ce, **ce));
+xc_sandbox_t *xc_sandbox_init(xc_sandbox_t *sandbox, char *filename TSRMLS_DC);
+void xc_sandbox_free(xc_sandbox_t *sandbox, xc_install_action_t install TSRMLS_DC);
+
+typedef zend_bool (*xc_if_func_t)(void *data);
+
+void xc_hash_copy_if(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, xc_if_func_t checker);
+#ifdef HAVE_XCACHE_CONSTANT
+void xc_zend_constant_ctor(zend_constant *c);
+void xc_zend_constant_dtor(zend_constant *c);
+void xc_copy_internal_zend_constants(HashTable *target, HashTable *source);
+#endif
Index: /tags/1.3.0-rc1/THANKS
===================================================================
--- /tags/1.3.0-rc1/THANKS	(revision 604)
+++ /tags/1.3.0-rc1/THANKS	(revision 604)
@@ -0,0 +1,9 @@
+
+Jan <jan@kneschke.de>, host XCache website
+Alex <ale@freebsd.org>, redist to FreeBSD
+darix <darix@irssi.org>, redist to openSUSE
+judas_iscariote <judas.iscariote@gmail.com>, redist/test with openSUSE
+Finjon Kiang <kiange@gmail.com>, Chinese Traditional translation
+
+There is also many ppl on IRC or forum helped me a lot testing XCache.
+Without them, XCache may not even be released.
Index: /tags/1.3.0-rc1/stack.h
===================================================================
--- /tags/1.3.0-rc1/stack.h	(revision 593)
+++ /tags/1.3.0-rc1/stack.h	(revision 593)
@@ -0,0 +1,18 @@
+
+typedef struct {
+	void **data;
+	int cnt;
+	int size;
+} xc_stack_t;
+
+#define S xc_stack_t*
+void xc_stack_init_ex(S stack, int initsize);
+#define xc_stack_init(stack) xc_stack_init_ex(stack, 8)
+void xc_stack_destroy(S stack);
+void xc_stack_push(S stack, void *item);
+void *xc_stack_pop(S stack);
+void *xc_stack_top(S stack);
+void *xc_stack_get(S stack, int n);
+int xc_stack_count(S stack);
+void xc_stack_reverse(S stack);
+#undef S
Index: /tags/1.3.0-rc1/Makefile.frag
===================================================================
--- /tags/1.3.0-rc1/Makefile.frag	(revision 644)
+++ /tags/1.3.0-rc1/Makefile.frag	(revision 644)
@@ -0,0 +1,44 @@
+XCACHE_PROC_SRC=$(srcdir)/processor/main.m4
+XCACHE_PROC_OUT=$(builddir)/processor.out
+XCACHE_PROC_C=$(builddir)/processor_real.c
+XCACHE_PROC_H=$(builddir)/processor.h
+XCACHE_INCLUDES_SRC=$(srcdir)/includes.c
+XCACHE_INCLUDES_I=$(builddir)/includes.i
+XCACHE_STRUCTINFO_OUT=$(builddir)/structinfo.m4
+
+$(XCACHE_INCLUDES_I): $(XCACHE_INCLUDES_SRC) $(srcdir)/xcache.h
+	$(CC) -I. -I$(srcdir) $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -E $(XCACHE_INCLUDES_SRC) -o $(XCACHE_INCLUDES_I)
+
+$(XCACHE_STRUCTINFO_OUT): $(XCACHE_INCLUDES_I) $(srcdir)/mkstructinfo.awk
+	@echo $(XCACHE_STRUCTINFO_OUT) is optional if XCache test is not enabled, feel free if it awk failed to produce it
+	-$(XCACHE_AWK) -f $(srcdir)/mkstructinfo.awk < $(XCACHE_INCLUDES_I) > $(XCACHE_STRUCTINFO_OUT).tmp && mv $(XCACHE_STRUCTINFO_OUT).tmp $(XCACHE_STRUCTINFO_OUT)
+
+$(XCACHE_PROC_OUT): $(XCACHE_PROC_SRC) $(XCACHE_STRUCTINFO_OUT) $(XCACHE_PROC_SOURCES)
+	$(M4) -D srcdir='`'"$(srcdir)'" -D builddir='`'"$(builddir)'" $(XCACHE_ENABLE_TEST) $(XCACHE_PROC_SRC) > $(XCACHE_PROC_OUT).tmp
+	mv $(XCACHE_PROC_OUT).tmp $(XCACHE_PROC_OUT)
+
+$(XCACHE_PROC_H): $(XCACHE_PROC_OUT)
+	$(GREP) 'export: ' $(XCACHE_PROC_OUT) | $(SED) 's/.*export:\(.*\):export.*/\1/g' > $(XCACHE_PROC_H)
+	-$(XCACHE_INDENT) < $(XCACHE_PROC_H) > $(XCACHE_PROC_H).tmp && mv $(XCACHE_PROC_H).tmp $(XCACHE_PROC_H)
+
+$(XCACHE_PROC_C): $(XCACHE_PROC_OUT) $(XCACHE_PROC_H)
+	cp $(XCACHE_PROC_OUT) $(XCACHE_PROC_C)
+	-$(XCACHE_INDENT) < $(XCACHE_PROC_OUT) > $(XCACHE_PROC_C).tmp && mv $(XCACHE_PROC_C).tmp $(XCACHE_PROC_C)
+
+$(builddir)/processor.lo: $(XCACHE_PROC_C) $(XCACHE_PROC_H) $(srcdir)/processor.c
+processor.lo: $(XCACHE_PROC_C) $(XCACHE_PROC_H) $(srcdir)/processor.c
+
+$(builddir)/disassembler.lo: $(XCACHE_PROC_H) $(srcdir)/processor.c
+disassembler.lo: $(XCACHE_PROC_H) $(srcdir)/processor.c
+
+$(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
+
+xcachesvnclean: clean
+	cat $(srcdir)/.cvsignore | grep -v ^Makefile | grep -v ^config.nice | xargs rm -rf
+
+xcachetest:
+	$(SED) "s#\\./modules/#$(top_builddir)/modules/#" < $(srcdir)/xcache-test.ini > $(top_builddir)/tmp-php.ini
+	TEST_PHP_SRCDIR=$(top_srcdir) \
+	CC="$(CC)" \
+		$(srcdir)/run-xcachetest -d 'open_basedir=' -d 'safe_mode=0' -d 'output_buffering=0' -d 'memory_limit=-1' $(top_srcdir)/run-tests.php $(TESTS) $(TEST_ARGS) -c $(top_builddir)/tmp-php.ini
Index: /tags/1.3.0-rc1/mkopcode_spec.awk
===================================================================
--- /tags/1.3.0-rc1/mkopcode_spec.awk	(revision 626)
+++ /tags/1.3.0-rc1/mkopcode_spec.awk	(revision 626)
@@ -0,0 +1,46 @@
+#! /usr/bin/awk -f
+# vim:ts=4:sw=4
+# process eaccelerator/opcodes.c
+BEGIN {
+	FS=" "
+	max = 0;
+	started = 0
+}
+
+/OPDEF/ {
+	if (started) {
+		name = "";
+		if (match($0, /"([^"]+)"/, m)) { 
+			name = m[1]; 
+		} 
+		sub(/"[^"]*"/, "");
+		if (!match($0, /EXT_([^ |]+).*OP[1S]_([^ |]+).*OP2_([^ |]+).*RES_([^ |)]+).*/, array)) {
+			print "error" $0
+			exit
+		}
+		id = "";
+		if (match($0, /\/\* *([0-9]+) *\*\//, comments)) {
+			id = comments[1];
+		}
+		printf "\tOPSPEC(%10s, %10s, %10s, %10s) /* %s %-30s */\n", array[1], array[2], array[3], array[4], id, name;
+		next
+	}
+}
+/^}/ {
+	print $0
+	exit;
+}
+/^[ ]*,[ ]*$/ {
+	next
+}
+{
+	if (started) {
+		print $0
+		next
+	}
+}
+
+/^static/ {
+	started = 1;
+	print "static const xc_opcode_spec_t xc_opcode_spec[] = {"
+}
Index: /tags/1.3.0-rc1/coverager.c
===================================================================
--- /tags/1.3.0-rc1/coverager.c	(revision 625)
+++ /tags/1.3.0-rc1/coverager.c	(revision 625)
@@ -0,0 +1,591 @@
+#if 0
+#define XCACHE_DEBUG
+#endif
+
+#include <stdio.h>
+#include "xcache.h"
+#include "ext/standard/flock_compat.h"
+#ifdef HAVE_SYS_FILE_H
+#	include <sys/file.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "stack.h"
+#include "xcache_globals.h"
+#include "coverager.h"
+#include "utils.h"
+typedef HashTable *coverager_t;
+#define PCOV_HEADER_MAGIC 0x564f4350
+
+static char *xc_coveragedump_dir = NULL;
+static zend_compile_file_t *old_compile_file = NULL;
+
+/* dumper */
+static void xc_destroy_coverage(void *pDest) /* {{{ */
+{
+	coverager_t cov = *(coverager_t*) pDest;
+	TRACE("destroy %p", cov);
+	zend_hash_destroy(cov);
+	efree(cov);
+}
+/* }}} */
+void xcache_mkdirs_ex(char *root, int rootlen, char *path, int pathlen TSRMLS_DC) /* {{{ */
+{
+	char *fullpath;
+	struct stat st;
+	ALLOCA_FLAG(use_heap)
+
+	TRACE("mkdirs %s %d %s %d", root, rootlen, path, pathlen);
+	fullpath = my_do_alloca(rootlen + pathlen + 1, use_heap);
+	memcpy(fullpath, root, rootlen);
+	memcpy(fullpath + rootlen, path, pathlen);
+	fullpath[rootlen + pathlen] = '\0';
+
+	if (stat(fullpath, &st) != 0) {
+		char *chr;
+
+		chr = strrchr(path, PHP_DIR_SEPARATOR);
+		if (chr && chr != path) {
+			*chr = '\0';
+			xcache_mkdirs_ex(root, rootlen, path, chr - path TSRMLS_CC);
+			*chr = PHP_DIR_SEPARATOR;
+		}
+		TRACE("mkdir %s", fullpath);
+#if PHP_MAJOR_VERSION > 5
+		php_stream_mkdir(fullpath, 0700, REPORT_ERRORS, NULL);
+#else
+		mkdir(fullpath, 0700);
+#endif
+	}
+	my_free_alloca(fullpath, use_heap);
+}
+/* }}} */
+static void xc_coverager_save_cov(char *srcfile, char *outfilename, coverager_t cov TSRMLS_DC) /* {{{ */
+{
+	long *buf = NULL, *p;
+	long covlines, *phits;
+	int fd = -1;
+	int size;
+	int newfile;
+	struct stat srcstat, outstat;
+	HashPosition pos;
+	char *contents = NULL;
+	long len;
+
+	if (stat(srcfile, &srcstat) != 0) {
+		return;
+	}
+
+	newfile = 0;
+	if (stat(outfilename, &outstat) != 0) {
+		newfile = 1;
+	}
+	else {
+		if (srcstat.st_mtime > outstat.st_mtime) {
+			newfile = 1;
+		}
+	}
+
+	fd = open(outfilename, O_RDWR | O_CREAT, 0600);
+	if (fd < 0) {
+		char *chr;
+		chr = strrchr(srcfile, PHP_DIR_SEPARATOR);
+		if (chr) {
+			*chr = '\0';
+			xcache_mkdirs_ex(xc_coveragedump_dir, strlen(xc_coveragedump_dir), srcfile, chr - srcfile TSRMLS_CC);
+			*chr = PHP_DIR_SEPARATOR;
+		}
+		fd = open(outfilename, O_RDWR | O_CREAT, 0600);
+		if (fd < 0) {
+			goto bailout;
+		}
+	}
+	if (flock(fd, LOCK_EX) != SUCCESS) {
+		goto bailout;
+	}
+
+	if (newfile) {
+		TRACE("%s", "new file");
+	}
+	else if (outstat.st_size) {
+		len = outstat.st_size;
+		contents = emalloc(len);
+		if (read(fd, (void *) contents, len) != len) {
+			goto bailout;
+		}
+		TRACE("oldsize %d", (int) len);
+		do {
+			p = (long *) contents;
+			len -= sizeof(long);
+			if (len < 0) {
+				break;
+			}
+			if (*p++ != PCOV_HEADER_MAGIC) {
+				TRACE("wrong magic in file %s", outfilename);
+				break;
+			}
+
+			p += 2; /* skip covliens */
+			len -= sizeof(long) * 2;
+			if (len < 0) {
+				break;
+			}
+
+			for (; len >= sizeof(long) * 2; len -= sizeof(long) * 2, p += 2) {
+				if (zend_hash_index_find(cov, p[0], (void**)&phits) == SUCCESS) {
+					if (p[1] == -1) {
+						/* OPTIMIZE: already marked */
+						continue;
+					}
+					if (*phits != -1) {
+						p[1] += *phits;
+					}
+				}
+				zend_hash_index_update(cov, p[0], &p[1], sizeof(p[1]), NULL);
+			}
+		} while (0);
+		efree(contents);
+		contents = NULL;
+	}
+
+
+	/* serialize */
+	size = (zend_hash_num_elements(cov) + 1) * sizeof(long) * 2 + sizeof(long);
+	p = buf = emalloc(size);
+	*p++ = PCOV_HEADER_MAGIC;
+	p += 2; /* for covlines */
+	covlines = 0;
+
+	zend_hash_internal_pointer_reset_ex(cov, &pos);
+	while (zend_hash_get_current_data_ex(cov, (void**)&phits, &pos) == SUCCESS) {
+		*p++ = pos->h;
+		*p++ = *phits;
+		if (*phits > 0) {
+			covlines ++;
+		}
+		zend_hash_move_forward_ex(cov, &pos);
+	}
+	p = buf + 1;
+	p[0] = 0;
+	p[1] = covlines;
+
+	ftruncate(fd, 0);
+	lseek(fd, 0, SEEK_SET);
+	write(fd, (char *) buf, size);
+
+bailout:
+	if (contents) efree(contents);
+	if (fd >= 0) close(fd);
+	if (buf) efree(buf);
+}
+/* }}} */
+
+static void xc_coverager_initenv(TSRMLS_D) /* {{{ */
+{
+	if (!XG(coverages)) {
+		XG(coverages) = emalloc(sizeof(HashTable));
+		zend_hash_init(XG(coverages), 0, NULL, xc_destroy_coverage, 0);
+	}
+}
+/* }}} */
+static void xc_coverager_clean(TSRMLS_D) /* {{{ */
+{
+	if (XG(coverages)) {
+		HashPosition pos;
+		coverager_t *pcov;
+
+		zend_hash_internal_pointer_reset_ex(XG(coverages), &pos);
+		while (zend_hash_get_current_data_ex(XG(coverages), (void **) &pcov, &pos) == SUCCESS) {
+			long *phits;
+			coverager_t cov;
+			HashPosition pos2;
+
+			cov = *pcov;
+
+			zend_hash_internal_pointer_reset_ex(cov, &pos2);
+			while (zend_hash_get_current_data_ex(cov, (void**)&phits, &pos2) == SUCCESS) {
+				long hits = *phits;
+
+				if (hits != -1) {
+					hits = -1;
+					zend_hash_index_update(cov, pos2->h, &hits, sizeof(hits), NULL);
+				}
+				zend_hash_move_forward_ex(cov, &pos2);
+			}
+
+			zend_hash_move_forward_ex(XG(coverages), &pos);
+		}
+	}
+}
+/* }}} */
+static void xc_coverager_cleanup(TSRMLS_D) /* {{{ */
+{
+	if (XG(coverages)) {
+		zend_hash_destroy(XG(coverages));
+		efree(XG(coverages));
+		XG(coverages) = NULL;
+	}
+}
+/* }}} */
+
+static void xc_coverager_enable(TSRMLS_D) /* {{{ */
+{
+	XG(coverage_enabled) = 1;
+}
+/* }}} */
+static void xc_coverager_disable(TSRMLS_D) /* {{{ */
+{
+	XG(coverage_enabled) = 0;
+}
+/* }}} */
+
+void xc_coverager_request_init(TSRMLS_D) /* {{{ */
+{
+	if (XG(coverager)) {
+		xc_coverager_enable(TSRMLS_C);
+#ifdef ZEND_COMPILE_EXTENDED_INFO
+		CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
+#else
+		CG(extended_info) = 1;
+#endif
+	}
+	else {
+		XG(coverage_enabled) = 0;
+	}
+}
+/* }}} */
+static void xc_coverager_autodump(TSRMLS_D) /* {{{ */
+{
+	coverager_t *pcov;
+	zstr s;
+	char *outfilename;
+	int dumpdir_len, outfilelen, alloc_len = 0;
+	uint size;
+	HashPosition pos;
+
+	if (XG(coverages) && xc_coveragedump_dir) {	
+		dumpdir_len = strlen(xc_coveragedump_dir);
+		alloc_len = dumpdir_len + 1 + 128;
+		outfilename = emalloc(alloc_len);
+		strcpy(outfilename, xc_coveragedump_dir);
+
+		zend_hash_internal_pointer_reset_ex(XG(coverages), &pos);
+		while (zend_hash_get_current_data_ex(XG(coverages), (void **) &pcov, &pos) == SUCCESS) {
+			zend_hash_get_current_key_ex(XG(coverages), &s, &size, NULL, 0, &pos);
+			outfilelen = dumpdir_len + size + 5;
+			if (alloc_len < outfilelen) {
+				alloc_len = outfilelen + 128;
+				outfilename = erealloc(outfilename, alloc_len);
+			}
+			strcpy(outfilename + dumpdir_len, ZSTR_S(s));
+			strcpy(outfilename + dumpdir_len + size - 1, ".pcov");
+
+			TRACE("outfilename %s", outfilename);
+			xc_coverager_save_cov(ZSTR_S(s), outfilename, *pcov TSRMLS_CC);
+			zend_hash_move_forward_ex(XG(coverages), &pos);
+		}
+		efree(outfilename);
+	}
+}
+/* }}} */
+static void xc_coverager_dump(zval *return_value TSRMLS_DC) /* {{{ */
+{
+	coverager_t *pcov;
+	HashPosition pos;
+
+	if (XG(coverages)) {
+		array_init(return_value);
+
+		zend_hash_internal_pointer_reset_ex(XG(coverages), &pos);
+		while (zend_hash_get_current_data_ex(XG(coverages), (void **) &pcov, &pos) == SUCCESS) {
+			zval *lines;
+			long *phits;
+			coverager_t cov;
+			HashPosition pos2;
+			zstr filename;
+			uint size;
+
+			cov = *pcov;
+			zend_hash_get_current_key_ex(XG(coverages), &filename, &size, NULL, 0, &pos);
+
+			MAKE_STD_ZVAL(lines);
+			array_init(lines);
+			zend_hash_internal_pointer_reset_ex(cov, &pos2);
+			while (zend_hash_get_current_data_ex(cov, (void**)&phits, &pos2) == SUCCESS) {
+				long hits = *phits;
+				add_index_long(lines, pos2->h, hits >= 0 ? hits : 0);
+				zend_hash_move_forward_ex(cov, &pos2);
+			}
+			add_assoc_zval_ex(return_value, ZSTR_S(filename), strlen(ZSTR_S(filename)) + 1, lines);
+
+			zend_hash_move_forward_ex(XG(coverages), &pos);
+		}
+	}
+	else {
+		RETVAL_NULL();
+	}
+}
+/* }}} */
+void xc_coverager_request_shutdown(TSRMLS_D) /* {{{ */
+{
+	if (XG(coverager)) {
+		xc_coverager_autodump(TSRMLS_C);
+		xc_coverager_cleanup(TSRMLS_C);
+	}
+}
+/* }}} */
+
+/* helper func to store hits into coverages */
+static coverager_t xc_coverager_get(char *filename TSRMLS_DC) /* {{{ */
+{
+	int len = strlen(filename) + 1;
+	coverager_t cov, *pcov;
+
+	if (zend_hash_find(XG(coverages), filename, len, (void **) &pcov) == SUCCESS) {
+		TRACE("got coverage %s %p", filename, *pcov);
+		return *pcov;
+	}
+	else {
+		cov = emalloc(sizeof(HashTable));
+		zend_hash_init(cov, 0, NULL, NULL, 0);
+		zend_hash_add(XG(coverages), filename, len, (void **) &cov, sizeof(cov), NULL);
+		TRACE("new coverage %s %p", filename, cov);
+		return cov;
+	}
+}
+/* }}} */
+static void xc_coverager_add_hits(HashTable *cov, long line, long hits TSRMLS_DC) /* {{{ */
+{
+	long *poldhits;
+
+	if (line == 0) {
+		return;
+	}
+	if (zend_hash_index_find(cov, line, (void**)&poldhits) == SUCCESS) {
+		if (hits == -1) {
+			/* OPTIMIZE: -1 == init-ing, but it's already initized */
+			return;
+		}
+		if (*poldhits != -1) {
+			hits += *poldhits;
+		}
+	}
+	zend_hash_index_update(cov, line, &hits, sizeof(hits), NULL);
+}
+/* }}} */
+
+static int xc_coverager_get_op_array_size_no_tail(zend_op_array *op_array) /* {{{ */
+{
+	zend_uint size;
+
+	size = op_array->size;
+	do {
+next_op:
+		if (size == 0) {
+			break;
+		}
+		switch (op_array->opcodes[size - 1].opcode) {
+#ifdef ZEND_HANDLE_EXCEPTION
+			case ZEND_HANDLE_EXCEPTION:
+#endif
+			case ZEND_RETURN:
+			case ZEND_EXT_STMT:
+				size --;
+				goto next_op;
+		}
+	} while (0);
+	return size;
+}
+/* }}} */
+
+/* prefill */
+static int xc_coverager_init_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	zend_uint size;
+	coverager_t cov;
+	zend_uint i;
+
+	if (op_array->type != ZEND_USER_FUNCTION) {
+		return 0;
+	}
+
+	size = xc_coverager_get_op_array_size_no_tail(op_array);
+	cov = xc_coverager_get(op_array->filename TSRMLS_CC);
+	for (i = 0; i < size; i ++) {
+		switch (op_array->opcodes[i].opcode) {
+			case ZEND_EXT_STMT:
+#if 0
+			case ZEND_EXT_FCALL_BEGIN:
+			case ZEND_EXT_FCALL_END:
+#endif
+				xc_coverager_add_hits(cov, op_array->opcodes[i].lineno, -1 TSRMLS_CC);
+				break;
+		}
+	}
+	return 0;
+}
+/* }}} */
+static void xc_coverager_init_compile_result(zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	xc_compile_result_t cr;
+
+	xc_compile_result_init_cur(&cr, op_array TSRMLS_CC);
+	xc_apply_op_array(&cr, (apply_func_t) xc_coverager_init_op_array TSRMLS_CC);
+	xc_compile_result_free(&cr);
+}
+/* }}} */
+static zend_op_array *xc_compile_file_for_coverage(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */
+{
+	zend_op_array *op_array;
+
+	op_array = old_compile_file(h, type TSRMLS_CC);
+	if (op_array) {
+		if (XG(coverager)) {
+			xc_coverager_initenv(TSRMLS_C);
+			xc_coverager_init_compile_result(op_array TSRMLS_CC);
+		}
+	}
+	return op_array;
+}
+/* }}} */
+
+/* hits */
+void xc_coverager_handle_ext_stmt(zend_op_array *op_array, zend_uchar op) /* {{{ */
+{
+	TSRMLS_FETCH();
+
+	if (XG(coverages) && XG(coverage_enabled)) {
+		int size = xc_coverager_get_op_array_size_no_tail(op_array);
+		int oplineno = (*EG(opline_ptr)) - op_array->opcodes;
+		if (oplineno < size) {
+			xc_coverager_add_hits(xc_coverager_get(op_array->filename TSRMLS_CC), (*EG(opline_ptr))->lineno, 1 TSRMLS_CC);
+		}
+	}
+}
+/* }}} */
+
+/* init/destroy */
+int xc_coverager_init(int module_number TSRMLS_DC) /* {{{ */
+{
+	old_compile_file = zend_compile_file;
+	zend_compile_file = xc_compile_file_for_coverage;
+
+	if (cfg_get_string("xcache.coveragedump_directory", &xc_coveragedump_dir) == SUCCESS && xc_coveragedump_dir) {
+		int len;
+		xc_coveragedump_dir = pestrdup(xc_coveragedump_dir, 1);
+		len = strlen(xc_coveragedump_dir);
+		if (len) {
+			if (xc_coveragedump_dir[len - 1] == '/') {
+				xc_coveragedump_dir[len - 1] = '\0';
+			}
+		}
+		if (!strlen(xc_coveragedump_dir)) {
+			pefree(xc_coveragedump_dir, 1);
+			xc_coveragedump_dir = NULL;
+		}
+	}
+
+	return SUCCESS;
+}
+/* }}} */
+void xc_coverager_destroy() /* {{{ */
+{
+	if (old_compile_file == xc_compile_file_for_coverage) {
+		zend_compile_file = old_compile_file;
+	}
+	if (xc_coveragedump_dir) {
+		pefree(xc_coveragedump_dir, 1);
+		xc_coveragedump_dir = NULL;
+	}
+}
+/* }}} */
+
+/* user api */
+/* {{{ proto array xcache_coverager_decode(string data)
+ * decode specified data which is saved by auto dumper to array
+ */
+PHP_FUNCTION(xcache_coverager_decode)
+{
+	char *str;
+	int len;
+	long *p;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) == FAILURE) {
+		return;
+	}
+
+	array_init(return_value);
+
+	p = (long*) str;
+	len -= sizeof(long);
+	if (len < 0) {
+		return;
+	}
+	if (*p++ != PCOV_HEADER_MAGIC) {
+		TRACE("%s", "wrong magic in xcache_coverager_decode");
+		return;
+	}
+
+	for (; len >= sizeof(long) * 2; len -= sizeof(long) * 2, p += 2) {
+		add_index_long(return_value, p[0], p[1] < 0 ? 0 : p[1]);
+	}
+}
+/* }}} */
+/* {{{ proto void xcache_coverager_start([bool clean = true])
+ * starts coverager data collecting
+ */
+PHP_FUNCTION(xcache_coverager_start)
+{
+	zend_bool clean = 1;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) {
+		return;
+	}
+
+	if (clean) {
+		xc_coverager_clean(TSRMLS_C);
+	}
+
+	if (XG(coverager)) {
+		xc_coverager_enable(TSRMLS_C);
+	}
+	else {
+		php_error(E_WARNING, "You can only start coverager after you set 'xcache.coverager' to 'On' in ini");
+	}
+}
+/* }}} */
+/* {{{ proto void xcache_coverager_stop([bool clean = false])
+ * stop coverager data collecting
+ */
+PHP_FUNCTION(xcache_coverager_stop)
+{
+	zend_bool clean = 0;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) {
+		return;
+	}
+
+	xc_coverager_disable(TSRMLS_C);
+	if (clean) {
+		xc_coverager_clean(TSRMLS_C);
+	}
+}
+/* }}} */
+/* {{{ proto array xcache_coverager_get([bool clean = false])
+ * get coverager data collected
+ */
+PHP_FUNCTION(xcache_coverager_get)
+{
+	zend_bool clean = 0;
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) {
+		return;
+	}
+
+	xc_coverager_dump(return_value TSRMLS_CC);
+	if (clean) {
+		xc_coverager_clean(TSRMLS_C);
+	}
+}
+/* }}} */
Index: /tags/1.3.0-rc1/prepare.devel.inc.example
===================================================================
--- /tags/1.3.0-rc1/prepare.devel.inc.example	(revision 617)
+++ /tags/1.3.0-rc1/prepare.devel.inc.example	(revision 617)
@@ -0,0 +1,11 @@
+# copy this file as devel.prepare.inc before modifying
+PHP4_x_DIR=
+PHP5_0_DIR=
+PHP5_1_DIR=
+PHP5_3_DIR=
+PHP6_x_DIR=
+
+PHP_DEVEL_DIR=
+
+# path to eaccelerator source dir
+EA_DIR=
Index: /tags/1.3.0-rc1/coverager.h
===================================================================
--- /tags/1.3.0-rc1/coverager.h	(revision 394)
+++ /tags/1.3.0-rc1/coverager.h	(revision 394)
@@ -0,0 +1,12 @@
+#include "php.h"
+#include "xcache.h"
+
+void xc_coverager_handle_ext_stmt(zend_op_array *op_array, zend_uchar op);
+int xc_coverager_init(int module_number TSRMLS_DC);
+void xc_coverager_destroy();
+void xc_coverager_request_init(TSRMLS_D);
+void xc_coverager_request_shutdown(TSRMLS_D);
+PHP_FUNCTION(xcache_coverager_decode);
+PHP_FUNCTION(xcache_coverager_start);
+PHP_FUNCTION(xcache_coverager_stop);
+PHP_FUNCTION(xcache_coverager_get);
Index: /tags/1.3.0-rc1/optimizer.c
===================================================================
--- /tags/1.3.0-rc1/optimizer.c	(revision 394)
+++ /tags/1.3.0-rc1/optimizer.c	(revision 394)
@@ -0,0 +1,29 @@
+#include "optimizer.h"
+#include "utils.h"
+
+static int xc_optimize_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	if (op_array->type != ZEND_USER_FUNCTION) {
+		return 0;
+	}
+#if 0
+	xc_undo_pass_two(op_array TSRMLS_CC);
+	xc_redo_pass_two(op_array TSRMLS_CC);
+	xc_dprint_zend_op_array(op_array, 0);
+#endif
+	return 0;
+}
+/* }}} */
+void xc_optimize(zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	xc_compile_result_t cr;
+
+	xc_compile_result_init_cur(&cr, op_array TSRMLS_CC);
+
+	xc_apply_op_array(&cr, (apply_func_t) xc_undo_pass_two TSRMLS_CC);
+	xc_apply_op_array(&cr, (apply_func_t) xc_optimize_op_array TSRMLS_CC);
+	xc_apply_op_array(&cr, (apply_func_t) xc_redo_pass_two TSRMLS_CC);
+
+	xc_compile_result_free(&cr);
+}
+/* }}} */
Index: /tags/1.3.0-rc1/opcode_spec.c
===================================================================
--- /tags/1.3.0-rc1/opcode_spec.c	(revision 394)
+++ /tags/1.3.0-rc1/opcode_spec.c	(revision 394)
@@ -0,0 +1,43 @@
+#include "xcache.h"
+#include "opcode_spec.h"
+#include "const_string.h"
+
+#ifdef HAVE_XCACHE_OPCODE_SPEC_DEF
+/* {{{ opcode_spec */
+#define OPSPEC(ext, op1, op2, res) { OPSPEC_##ext, OPSPEC_##op1, OPSPEC_##op2, OPSPEC_##res },
+#ifdef ZEND_ENGINE_2
+#	define OPSPEC_VAR_2 OPSPEC_STD
+#else
+#	define OPSPEC_VAR_2 OPSPEC_VAR
+#endif
+#include "opcode_spec_def.h"
+
+zend_uchar xc_get_opcode_spec_count()
+{
+	return sizeof(xc_opcode_spec) / sizeof(xc_opcode_spec[0]);
+}
+
+const xc_opcode_spec_t *xc_get_opcode_spec(zend_uchar opcode)
+{
+	assert(xc_get_opcode_count() == xc_get_opcode_spec_count());
+	assert(opcode < xc_get_opcode_spec_count());
+	return &xc_opcode_spec[opcode];
+}
+/* }}} */
+#endif
+/* {{{ op_spec */
+
+#define OPSPECS_DEF_NAME(name) #name,
+static const char *xc_op_spec[] = { OPSPECS(OPSPECS_DEF_NAME) };
+
+zend_uchar xc_get_op_spec_count()
+{
+	return sizeof(xc_op_spec) / sizeof(xc_op_spec[0]);
+}
+
+const char *xc_get_op_spec(zend_uchar spec)
+{
+	assert(spec < xc_get_op_spec_count());
+	return xc_op_spec[spec];
+}
+/* }}} */
Index: /tags/1.3.0-rc1/COPYING
===================================================================
--- /tags/1.3.0-rc1/COPYING	(revision 610)
+++ /tags/1.3.0-rc1/COPYING	(revision 610)
@@ -0,0 +1,31 @@
+
+
+Copyright (c) 2005-2009, mOo, phpxcache@gmail.com, XCache
+ All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+- Neither the name of the 'XCache' nor the names of its contributors may
+  be used to endorse or promote products derived from this software without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
Index: /tags/1.3.0-rc1/optimizer.h
===================================================================
--- /tags/1.3.0-rc1/optimizer.h	(revision 394)
+++ /tags/1.3.0-rc1/optimizer.h	(revision 394)
@@ -0,0 +1,4 @@
+#include "php.h"
+#include "xcache.h"
+
+void xc_optimize(zend_op_array *op_array TSRMLS_DC);
Index: /tags/1.3.0-rc1/opcode_spec.h
===================================================================
--- /tags/1.3.0-rc1/opcode_spec.h	(revision 598)
+++ /tags/1.3.0-rc1/opcode_spec.h	(revision 598)
@@ -0,0 +1,43 @@
+#include "php.h"
+
+#define OPSPECS(OPSPEC) \
+	OPSPEC(STD) \
+	OPSPEC(UNUSED) \
+	OPSPEC(OPLINE) \
+	OPSPEC(FCALL) \
+	OPSPEC(INIT_FCALL) \
+	OPSPEC(ARG) \
+	OPSPEC(CAST) \
+	OPSPEC(FETCH) \
+	OPSPEC(DECLARE) \
+	OPSPEC(SEND) \
+	OPSPEC(SEND_NOREF) \
+	OPSPEC(FCLASS) \
+	OPSPEC(UCLASS) \
+	OPSPEC(CLASS) \
+	OPSPEC(FE) \
+	OPSPEC(IFACE) \
+	OPSPEC(ISSET) \
+	OPSPEC(BIT) \
+	OPSPEC(VAR) \
+	OPSPEC(TMP) \
+	OPSPEC(JMPADDR) \
+	OPSPEC(BRK) \
+	OPSPEC(CONT) \
+	OPSPEC(INCLUDE) \
+	OPSPEC(ASSIGN)
+
+#define OPSPECS_DEF_ENUM(name) OPSPEC_##name,
+typedef enum { OPSPECS(OPSPECS_DEF_ENUM) OPSPEC_DUMMY } xc_op_spec_t;
+
+typedef struct {
+	xc_op_spec_t ext;
+	xc_op_spec_t op1;
+	xc_op_spec_t op2;
+	xc_op_spec_t res;
+} xc_opcode_spec_t;
+
+const xc_opcode_spec_t *xc_get_opcode_spec(zend_uchar opcode);
+zend_uchar xc_get_opcode_spec_count();
+zend_uchar xc_get_op_spec_count();
+const char *xc_get_op_spec(zend_uchar spec);
Index: /tags/1.3.0-rc1/NEWS
===================================================================
--- /tags/1.3.0-rc1/NEWS	(revision 626)
+++ /tags/1.3.0-rc1/NEWS	(revision 626)
@@ -0,0 +1,44 @@
+1.3.0 2009-??-??
+========
+ * PHP 5.3 support
+ * many cacher/coverager bug fixes
+ * improved admin pages
+ * admin page is now magic quote gpc aware
+
+1.2.2 2007-12-29
+========
+ * live with wrong system time: allow caching files with mtime in further
+ * bug fix for compatibility with Zend Optimizer and other non-cachable
+ * a rare segv bug with token_get_all
+ * minor bug fixes
+
+1.2.1 2007-07-01
+========
+ * compatibility fix for apache 1.x, which init XCache module correctly
+ * full Zend Optimizer compatibility
+ * ini settings changed
+ * other bug fixes
+
+1.2.0 2006-12-10
+========
+ * full 5.2 support
+ * minor admin/coverage-viewer page improves
+ * compatible with suhosin/ZendOptimizer
+ * xcache_get reference handling
+ * new apis for coverager
+ * some ini settings changed
+
+1.1.0 2006-11-11
+========
+ * fix xcache_get issue on ttl 0 data
+ * avoid crash when php failed to compile file when coverager enabled
+ * gc expired items, new ini
+ * Partial php 5.2 support
+ * "Cannot redeclare ()" bug
+ * bug fixes
+ * Chinese Simplified/Traditional translations
+ * admin page fixes and applied phpinfo style
+ * coverage viewer page use phpinfo style
+ * fix build on rare arch and Mac OS X
+ * zts build
+ * includes all fixes from <=1.0.2
Index: /tags/1.3.0-rc1/.cvsignore
===================================================================
--- /tags/1.3.0-rc1/.cvsignore	(revision 604)
+++ /tags/1.3.0-rc1/.cvsignore	(revision 604)
@@ -0,0 +1,34 @@
+acinclude.m4
+aclocal.m4
+build
+config.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.nice
+config.status
+config.sub
+configure
+configure.in
+conftest
+conftest.c
+.deps
+include
+includes.i
+install-sh
+libtool
+ltmain.sh
+Makefile
+Makefile.fragments
+Makefile.global
+Makefile.objects
+missing
+mkinstalldirs
+modules
+processor.h
+processor.out
+processor_real.c
+run-tests.php
+structinfo.m4
+autom4te.cache
Index: /tags/1.3.0-rc1/config.w32
===================================================================
--- /tags/1.3.0-rc1/config.w32	(revision 644)
+++ /tags/1.3.0-rc1/config.w32	(revision 644)
@@ -0,0 +1,150 @@
+// vim:ft=javascript
+
+
+ARG_ENABLE("xcache", "Include XCache support", "yes,shared");
+
+if (PHP_XCACHE != "no") {
+	// {{{ check for xcache-constant 
+	ARG_ENABLE("xcache-constant", "XCache: Handle new constants made by php compiler (e.g.: for __halt_compiler)", "yes");
+	if (PHP_XCACHE_CONSTANT != "no") {
+		AC_DEFINE("HAVE_XCACHE_CONSTANT", 1, "Define to enable XCache handling of compile time constants");
+	}
+	// }}}
+
+	var xcache_sources = "processor.c \
+	                      xcache.c \
+	                      mmap.c \
+	                      mem.c \
+	                      xc_shm.c \
+	                      const_string.c \
+	                      opcode_spec.c \
+	                      stack.c \
+	                      utils.c \
+	                      lock.c \
+	                      ";
+	// {{{ add sources on enabled
+	ARG_ENABLE("xcache-optimizer",    "(N/A)", "no");
+	ARG_ENABLE("xcache-coverager",    "Enable code coverage dumper, useful for testing php scripts", "no");
+	ARG_ENABLE("xcache-assembler",    "(N/A)", "no");
+	ARG_ENABLE("xcache-disassembler", "Enable opcode to php variable dumper, NOT for production server", "no");
+	ARG_ENABLE("xcache-encoder",      "(N/A)", "no");
+	ARG_ENABLE("xcache-decoder",      "(N/A)", "no");
+
+	var XCACHE_MODULES = "cacher";
+	var options = ["optimizer",
+	               "coverager",
+	               "assembler", "disassembler",
+	               "encoder", "decoder"];
+	for (var i in options) {
+		var name = options[i];
+		var uname = name.toUpperCase();
+		var withval = eval("PHP_XCACHE_" + uname);
+		if (withval != "no") {
+			xcache_sources += " " + name + ".c";
+			XCACHE_MODULES += " " + name;
+			STDOUT.WriteLine("Enabling XCache Module: " + name);
+			AC_DEFINE("HAVE_XCACHE_" + uname, 1, "Define for XCache: " + name)
+		}
+	}
+	AC_DEFINE("XCACHE_MODULES", XCACHE_MODULES);
+	// }}}
+	// {{{ check for programs needed
+	var apps = ["m4", "grep", "sed"];
+	for (var i in apps) {
+		if (!PATH_PROG(apps[i])) {
+			ERROR(apps[i] + " is currently required to build XCache");
+		}
+	}
+	PATH_PROG("gawk", null, "XCACHE_AWK") || PATH_PROG("awk", null, "XCACHE_AWK");
+
+	// the cygwin indent is known broken on our output
+	var indent = false; // PATH_PROG("indent");
+	if (indent) {
+		indent += " -kr --use-tabs --tab-size 4 -sob -nce";
+	}
+	else {
+		indent = PATH_PROG("cat");
+		if (!indent) {
+			indent = '';
+		}
+	}
+	DEFINE("XCACHE_INDENT", indent);
+	// }}}
+	// {{{ check for xcache-test
+	ARG_ENABLE("xcache-test", "XCache: Enable self test - FOR DEVELOPERS ONLY!!", "no");
+	if (PHP_XCACHE_TEST != "no") {
+		ADD_FLAG("XCACHE_ENABLE_TEST", "-DXCACHE_ENABLE_TEST");
+		xcache_sources += " xc_malloc.c";
+		AC_DEFINE("HAVE_XCACHE_TEST", 1, "Define to enable XCache self test");
+	}
+	else {
+		ADD_FLAG("XCACHE_ENABLE_TEST", "");
+	}
+	// }}}
+	// {{{ check for xcache-test
+	ARG_ENABLE("xcache-dprint", "XCache: Enable self debug print functions - FOR DEVELOPERS ONLY!!", "no");
+	if (PHP_XCACHE_DPRINT != "no") {
+		AC_DEFINE("HAVE_XCACHE_DPRINT", 1, "Define to enable XCache debug print functions");
+	}
+	// }}}
+	// {{{ create extension
+	EXTENSION("xcache", xcache_sources);
+	var srcdir = configure_module_dirname;
+	// it's a bit harder to get builddir
+	var mfofile = "Makefile.objects";
+	MFO.Close();
+
+	var mfo = file_get_contents(mfofile);
+	mfo.match(/(.*)\\xcache.obj:/);
+	var builddir = RegExp.$1;
+	mfo.match(/(.*\$\(CC\).* )\/c.*\\xcache.c.*/i);
+	var ccrule = RegExp.$1;
+
+	MFO = FSO.OpenTextFile(mfofile, 8);
+	mfo = null;
+	// }}}
+	// {{{ add make fragments
+	var file = srcdir + "\\Makefile.frag";
+	STDOUT.WriteLine("Adding Makefile.frag: " + file);
+	var frag = file_get_contents(file);
+	frag = frag.replace(/\$\(srcdir\)\//g,   srcdir + '\\');
+	frag = frag.replace(/\$\(srcdir\)/g,     srcdir);
+	frag = frag.replace(/\$\(builddir\)\//g, builddir + '\\');
+	frag = frag.replace(/\$\(builddir\)/g,   builddir);
+	frag = frag.replace(/processor\//g,      "processor\\");
+	frag = frag.replace(/\.lo:/g, ".obj:");
+	frag = frag.replace(/.*\$\(CC\).* -E (.*) -o (.*)/, ccrule + " /E $1 > $2");
+	frag = frag.replace(/ -o /g, " /Fo");
+	frag = frag.replace(/cp /g, "copy ");
+	frag = frag.replace(/mv /g, "move ");
+	frag = frag.replace(/ \|\| /g, "\r\n\tif errorlevel 1 ");
+	frag = frag.replace(/ && /g, "\r\n\tif not errorlevel 1 ");
+	if (indent == '') {
+		frag = frag.replace(/\| +\$\(XCACHE_INDENT\)/, '');
+		frag = frag.replace(/\$\(XCACHE_INDENT\) < /, 'type ');
+	}
+	MFO.WriteLine(frag);
+	ADD_FLAG("CFLAGS_XCACHE", "/I " + builddir);
+	/// }}}
+	XCACHE_PROC_SOURCES=glob(srcdir + "\\processor\\*.m4").join(' ');
+	ADD_FLAG("XCACHE_PROC_SOURCES", XCACHE_PROC_SOURCES);
+	// {{{ check for opcode_spec_def.h
+	STDOUT.Write("Checking if you have opcode_spec_def.h for XCache ... ");
+	var file = srcdir + "\\opcode_spec_def.h";
+	if (FSO.FileExists(file)) {
+		STDOUT.WriteLine("yes");
+		AC_DEFINE("HAVE_XCACHE_OPCODE_SPEC_DEF", 1, "Define if you have opcode_spec_def.h for XCache");
+	}
+	else {
+		STDOUT.WriteLine("no");
+
+		// check for features depend on opcode_spec_def.h
+		var xcache_require_opcode_spec_def = function(withval, name) {
+			if (withval != "no") {
+				ERROR(file + " is required to enable XCache " + name);
+			}
+		}
+		xcache_require_opcode_spec_def(PHP_XCACHE_DISASSEMBLER, "disassembler");
+	}
+	// }}}
+}
Index: /tags/1.3.0-rc1/ChangeLog
===================================================================
--- /tags/1.3.0-rc1/ChangeLog	(revision 626)
+++ /tags/1.3.0-rc1/ChangeLog	(revision 626)
@@ -0,0 +1,133 @@
+1.3.0 2009-??-??
+== ChangeLog ==
+ * PHP 5.3 support
+ * fixed #138: no segv if cache is not initialized correctly
+ * default to 64M for xcache.size in xcache.ini
+ * could not show module info in admin page when XCache is the last module
+ * wrong http auth realm
+ * coverager: font-size and newline fix for firefox
+ * admin page is now magic quote gpc aware
+
+1.2.2 2007-12-29
+== ChangeLog ==
+ * added module dependency
+ * live with wrong system time: allow caching files with mtime in further
+ * bug fix for compatibility with Zend Optimizer and other non-cachable
+ * #59: Maximum execution time of 60 seconds exceeded
+ * #102: segv when var cacher is too small
+ * #55: segv php tokenizer on certain special situation
+
+1.2.1 2007-07-01
+== Ini Settings Changes ==
+ * new: xcache.admin.enable_auth = On
+
+== ChangeLog ==
+ * #86: remove/edit variable in admin page
+ * fixed #109: fast inc/dec was trying to break ro protection
+ * fixed #101, #105: Fixed compatibility issue for apache 1.x
+ * fixed #94: Garbage collector disabled when xcache.cacher set to off
+ * fixed #92: Zend Optimizer compatibility issue
+ * fixed #77: hits/misses was not updated
+ * fixed #59: pass by reference for internal function was broken
+ * fixed #56: xcache_set segfaults when xcache.var_size=0
+
+========
+1.2.0 2006-12-10
+Ini Settings Changes
+========
+ * new: xcache.stat = On
+ * new: xcache.coverager =  Off
+ * chg: xcache.coveragedump_directory default to ""
+ * del: xcache.coveragedumper = Off
+
+New APIs
+========
+ * array xcache_coverager_decode(string data)
+ * void  xcache_coverager_start([bool clean = true])
+ * void  xcache_coverager_stop([bool clean = false])
+ * array xcache_coverager_get([bool clean = false])
+
+ChangeLog
+========
+ * [290] [291] [292] build with the m4 on solaris
+ * [283] removed zend_append_version_info. not needed after [282] 
+ * [282] fix possible alloca() scope problem in lock 
+ * [281] keep config.nice on make xcachesvnclean 
+ * [279] fixed #48, was leaking info when cacher is not enabled by size 
+ * [280] [278] trunk: fix coredump on shutdown when loaded as "extension" and after "suhosin" or "zend optimizer". thanks to Alex, Cristian and Esser 
+ * [271] fix auto detection of php-cli/php-cgi for test 
+ * [270] make [269] pass test cases 
+ * [269] do not destruct shallow copied tmp_auto_globals. also improve copying of other hash tables
+ * [268] full compatible with auto_globals_jit, no need to disable it in ini from now on 
+ * [250] fixed css class on switcher
+ * [231] fix zval reference handling
+ * [230] update dprint support, added configure option: --enable-xcache-dprint
+ * [228] more robust coverager
+ * [227] cacher: remove redundant open_basedir check which broke php-src/ext/standard/tests/file/bug24313.phpt 
+ * [221] cacher: fix eleak in op_array non-shadow-copy (readonly_protection=on)
+ * [220] fixed #36, Bug in inherited static class variables
+ * [219] fix prototype for readonly_protection=off, fix testcase Zend/tests/bug37632.phpt 
+ * [217] kill leak warning on debug build
+ * [216] avoid crash on php compiler error
+ * [215] add `make xcachetest` to run xcache enabled test
+ * [214] [212] fixed #41, early class binding
+ * [272] [267] [263] [200] fixes for php6
+ * [224] [193] kill 64bit warning when self test is enabled 
+ * [190] trick to load and work with zend optimizer 
+ * [189] call op_array_ctor handler on restore to be more compatible with other zend_extension 
+ * [257] [183] xcache module is not required by coverage viewer any more
+ * [165] xcache.stat support to allow tuning off stat (new ini)
+ * [164] better way to handle system level ini settings so it can be display in phpinfo standardly
+
+1.1.0 2006-11-11
+ * merged [254] fix xcache.var_ttl displaying in info, fix xcache_get for ttl-unlimited
+ * merged [250] admin: fix switcher class on active
+ * merged [249] return 0 s instead of empty for deltatime
+ * merged [201] coverager: avoid crash when upstream failed to compile file
+ * merged from trunk: 159,161-162,167-180,182,184,186-187,194
+   * [194] PHP_5_2: new element in zend_brk_cont_element
+   * [186] [187] fix build on some rare arch
+   * [184] fix tplcov
+   * [178] fix type processor_t conflict with Mac OS X
+ * remove redundant open_basedir check, it's done before compiling
+ * trick in_compilation state, don't trigger __autoload at compile time
+ * FIX conflict between sandbox and user error handler 
+ * [154] fix segv on MSHUTDOWN
+ * [153] win32/vc build fix
+ * [150] avoid crash when OOM on mem_realloc
+ * [148] reconstruct shm/allocator
+ * [147] show module info in statistics page
+ * [146] avoid reading of uninitialized data. thanks to valgrind
+ * [144] compat size displaying in admin page func
+ * [143] fixed string parameter parsing arg type for disassembler functions. thanks to check_paramaters.php
+ * [141] fix cache clear corruption bug
+ * [140] fix refcount on cache #1 #2 …
+ * [133] admin-page: be more friendly if XCache isn't loaded
+ * [132] fix zts on calling destroy_op_array
+ * [131] move open_files out of sandbox, it's not needed
+ * [130] improve locking for compile
+ * [137] [138] changed the coding way of unlinking list. fixed ttl expires dead loop
+ * [114] gc expired items, new ini: xcache.ttl xcache.gc_interval xcache.var_ttl …
+ * [126] fix xcache_isset reported by http://forum.lighttpd.net/topic/1397
+ * [119] fix leak in xcache.test=1; XCACHE_VERSION/XCACHE_MODULES length off-by-one
+ * [118] show gc countdown in admin page
+ * [113] zts build fix
+ * [112] avoid crash when OOM on mem_(calloc|realloc|strndup)
+ * [108] update percent bar to vertical/avail
+ * [107] show XCache version in admin page
+ * [105] trigger jit on $_SERVER when needed
+ * [101] note: xcache.mmap_path is a file
+ * [100] FIX: alloc'ed wrong size for string on restore
+ * [99]  sohosin compatible & TSRM fix.
+ * [96]  remove tailing \0 in filename of administration html output. reported by …
+ * [94]  PHP_5_2: __tostring cache was MFH by php
+ * [93]  try to show both count/size assert before abort
+ * [92]  PHP_5_2: auto module_global is maintained by php engine
+ * [90] [91] kill compiler warnings
+ * [87]  XCACHE_INDENT fallback
+ * [84]  handle without inodes
+ * [79]  fix messy XCACHE_MAP_FAILED checking
+ * [78]  catch up with PHP_5_2, zend_property_info.ce
+ * [77]  leakcheck
+
+ (not all changesets is list here)
Index: /tags/1.3.0-rc1/includes.c
===================================================================
--- /tags/1.3.0-rc1/includes.c	(revision 394)
+++ /tags/1.3.0-rc1/includes.c	(revision 394)
@@ -0,0 +1,2 @@
+#include "xcache.h"
+#include "zend_compile.h"
Index: /tags/1.3.0-rc1/run-xcachetest
===================================================================
--- /tags/1.3.0-rc1/run-xcachetest	(revision 627)
+++ /tags/1.3.0-rc1/run-xcachetest	(revision 627)
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+getAbsolutePath() {
+	which readlink >/dev/null 2>&1 && readlink -f "$@" || echo "$@"
+}
+
+# use symlink first
+if test -x ./php-cli ; then
+	php_cli=`getAbsolutePath ./php-cli`
+elif test ! -z "$TEST_PHP_EXECUTABLE" && test -x "$TEST_PHP_EXECUTABLE"; then
+	php_cli="$TEST_PHP_EXECUTABLE"
+else
+	php_cli="`which php`"
+fi
+
+if test -x ./php-cgi ; then
+	php_cgi=`getAbsolutePath ./php-cgi`
+else
+	php_cgi="`which php-cgi`"
+fi
+
+test -z "$PHP_SRC" && PHP_SRC=`getAbsolutePath ./php-src`
+
+TEST_PHP_EXECUTABLE="$php_cli"
+TEST_PHP_CGI_EXECUTABLE="$php_cgi"
+TEST_PHP_SRCDIR="$PHP_SRC"
+
+export TEST_PHP_EXECUTABLE
+export TEST_PHP_CGI_EXECUTABLE
+export TEST_PHP_SRCDIR
+
+echo "XCache test running with:"
+echo "TEST_PHP_CGI_EXECUTABLE: $TEST_PHP_CGI_EXECUTABLE"
+echo "TEST_PHP_EXECUTABLE:     $TEST_PHP_EXECUTABLE"
+
+exec "$php_cli" "$@"
Index: /tags/1.3.0-rc1/const_string.c
===================================================================
--- /tags/1.3.0-rc1/const_string.c	(revision 626)
+++ /tags/1.3.0-rc1/const_string.c	(revision 626)
@@ -0,0 +1,84 @@
+#include "xcache.h"
+#include "const_string.h"
+
+/* {{{ xc_get_op_type */
+static const char *const op_type_names[] = {
+	/* 0 */ "NULL?",
+	/* 1 */ "IS_CONST",
+	/* 2 */ "IS_TMP_VAR",
+	/* 3 */ NULL,
+	/* 4 */ "IS_VAR",
+	/* 5 */ NULL,
+	/* 6 */ NULL,
+	/* 7 */ NULL,
+	/* 8 */ "IS_UNUSED",
+#ifdef IS_CV
+	/* 9  */ NULL,
+	/* 10 */ NULL,
+	/* 11 */ NULL,
+	/* 12 */ NULL,
+	/* 13 */ NULL,
+	/* 14 */ NULL,
+	/* 15 */ NULL,
+	/* 16 */ "IS_CV"
+#endif
+};
+
+zend_uchar xc_get_op_type_count()
+{
+	return sizeof(op_type_names) / sizeof(op_type_names[0]);
+}
+
+const char *xc_get_op_type(zend_uchar op_type)
+{
+	assert(op_type < xc_get_op_type_count());
+	return op_type_names[op_type];
+}
+/* }}} */
+/* {{{ xc_get_data_type */
+static const char *const data_type_names[] = {
+	/* 0 */ "IS_NULL",
+	/* 1 */ "IS_LONG",
+	/* 2 */ "IS_DOUBLE",
+	/* 3 */ "IS_BOOL",
+	/* 4 */ "IS_ARRAY",
+	/* 5 */ "IS_OBJECT",
+	/* 6 */ "IS_STRING",
+	/* 7 */ "IS_RESOURCE",
+	/* 8 */ "IS_CONSTANT",
+	/* 9 */ "IS_CONSTANT_ARRAY",
+	/* 10 */ "IS_UNICODE"
+};
+
+zend_uchar xc_get_data_type_count()
+{
+	return sizeof(data_type_names) / sizeof(data_type_names[0]);
+}
+
+const char *xc_get_data_type(zend_uchar data_type)
+{
+	return data_type_names[(data_type & IS_CONSTANT_TYPE_MASK)];
+}
+/* }}} */
+/* {{{ xc_get_opcode */
+#if PHP_MAJOR_VERSION >= 6
+#	include "const_string_opcodes_php6.x.h"
+#elif defined(ZEND_ENGINE_2_1)
+#	include "const_string_opcodes_php5.1.h"
+#elif defined(ZEND_ENGINE_2)
+#	include "const_string_opcodes_php5.0.h"
+#else
+#	include "const_string_opcodes_php4.x.h"
+#endif
+
+zend_uchar xc_get_opcode_count()
+{
+	return sizeof(xc_opcode_names) / sizeof(xc_opcode_names[0]);
+}
+
+const char *xc_get_opcode(zend_uchar opcode)
+{
+	assert(opcode < xc_get_opcode_count());
+	return xc_opcode_names[opcode];
+}
+/* }}} */
Index: /tags/1.3.0-rc1/mem.c
===================================================================
--- /tags/1.3.0-rc1/mem.c	(revision 625)
+++ /tags/1.3.0-rc1/mem.c	(revision 625)
@@ -0,0 +1,405 @@
+#ifdef TEST
+#include <limits.h>
+#include <stdio.h>
+#	define XCACHE_DEBUG
+#else
+#include <php.h>
+#endif
+
+#ifdef XCACHE_DEBUG
+#	define ALLOC_DEBUG_BLOCK_CHECK
+#endif
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#define XC_MEMBLOCK_IMPL _xc_mem_block_t
+#define XC_MEM_IMPL _xc_mem_mem_t
+#include "xc_shm.h"
+#include "align.h"
+#include "utils.h"
+
+#if 0
+#undef ALLOC_DEBUG_BLOCK_CHECK
+#endif
+
+#define CHAR_PTR(p) ((char *) (p))
+#define PADD(p, a) (CHAR_PTR(p) + a)
+#define PSUB(p1, p2) (CHAR_PTR(p1) - CHAR_PTR(p2))
+
+/* {{{ mem */
+struct _xc_mem_block_t {
+#ifdef ALLOC_DEBUG_BLOCK_CHECK
+	unsigned int magic;
+#endif
+	xc_memsize_t size; /* reserved even after alloc */
+	xc_block_t *next;  /* not used after alloc */
+};
+
+struct _xc_mem_mem_t {
+	const xc_mem_handlers_t *handlers;
+	xc_shm_t                *shm;
+	xc_memsize_t size;
+	xc_memsize_t avail;       /* total free */
+	xc_block_t headblock[1];  /* just as a pointer to first block*/
+};
+
+#ifndef XtOffsetOf
+#	include <linux/stddef.h>
+#	define XtOffsetOf(s_type, field) offsetof(s_type, field)
+#endif
+
+#define SizeOf(type, field) sizeof( ((type *) 0)->field )
+#define BLOCK_HEADER_SIZE() (ALIGN( XtOffsetOf(xc_block_t, size) + SizeOf(xc_block_t, size) ))
+
+#define BLOCK_MAGIC ((unsigned int) 0x87655678)
+
+/* }}} */
+static inline void xc_block_setup(xc_block_t *b, xc_memsize_t size, xc_block_t *next) /* {{{ */
+{
+#ifdef ALLOC_DEBUG_BLOCK_CHECK
+	b->magic = BLOCK_MAGIC;
+#endif
+	b->size = size;
+	b->next = next;
+}
+/* }}} */
+#ifdef ALLOC_DEBUG_BLOCK_CHECK
+static void xc_block_check(xc_block_t *b) /* {{{ */
+{
+	if (b->magic != BLOCK_MAGIC) {
+		fprintf(stderr, "0x%X != 0x%X magic wrong \n", b->magic, BLOCK_MAGIC);
+	}
+}
+/* }}} */
+#else
+#	define xc_block_check(b) do { } while(0)
+#endif
+
+
+static XC_MEM_MALLOC(xc_mem_malloc) /* {{{ */
+{
+	xc_block_t *prev, *cur;
+	xc_block_t *newb, *b;
+	xc_memsize_t realsize;
+	xc_memsize_t minsize;
+	void *p;
+	/* [xc_block_t:size|size] */
+	realsize = BLOCK_HEADER_SIZE() + size;
+	/* realsize is ALIGNed so next block start at ALIGNed address */
+	realsize = ALIGN(realsize);
+
+	TRACE("avail: %d (%dKB). Allocate size: %d realsize: %d (%dKB)"
+			, mem->avail, mem->avail / 1024
+			, size
+			, realsize, realsize / 1024
+			);
+	do {
+		p = NULL;
+		if (mem->avail < realsize) {
+			TRACE("%s", " oom");
+			break;
+		}
+
+		b = NULL;
+		minsize = INT_MAX;
+
+		/* prev|cur */
+
+		for (prev = mem->headblock; prev->next; prev = cur) {
+			/* while (prev->next != 0) { */
+			cur = prev->next;
+			xc_block_check(cur);
+			if (cur->size == realsize) {
+				/* found a perfect fit, stop searching */
+				b = prev;
+				break;
+			}
+			/* make sure we can split on the block */
+			else if (cur->size > (sizeof(xc_block_t) + realsize) &&
+					cur->size < minsize) {
+				/* cur is acceptable and memller */
+				b = prev;
+				minsize = cur->size;
+			}
+			prev = cur;
+		}
+
+		if (b == NULL) {
+			TRACE("%s", " no fit chunk");
+			break;
+		}
+
+		prev = b;
+
+		cur = prev->next;
+		p = PADD(cur, BLOCK_HEADER_SIZE());
+
+		/* update the block header */
+		mem->avail -= realsize;
+
+		/* perfect fit, just unlink */
+		if (cur->size == realsize) {
+			prev->next = cur->next;
+			TRACE(" perfect fit. Got: %p", p);
+			break;
+		}
+
+		/* make new free block after alloced space */
+
+		/* save, as it might be overwrited by newb (cur->size is ok) */
+		b = cur->next;
+
+		/* prev|cur     |next=b */
+
+		newb = (xc_block_t *)PADD(cur, realsize);
+		xc_block_setup(newb, cur->size - realsize, b);
+		cur->size = realsize;
+		/* prev|cur|newb|next
+		 *            `--^
+		 */
+
+		TRACE(" -> avail: %d (%dKB). new next: %p offset: %d %dKB. Got: %p"
+				, mem->avail, mem->avail / 1024
+				, newb
+				, PSUB(newb, mem), PSUB(newb, mem) / 1024
+				, p
+				);
+		prev->next = newb;
+		/* prev|cur|newb|next
+		 *    `-----^
+		 */
+
+	} while (0);
+
+	return p;
+}
+/* }}} */
+static XC_MEM_FREE(xc_mem_free) /* {{{ return block size freed */
+{
+	xc_block_t *cur, *b;
+	int size;
+
+	cur = (xc_block_t *) (CHAR_PTR(p) - BLOCK_HEADER_SIZE());
+	TRACE("freeing: %p, size=%d", p, cur->size);
+	xc_block_check(cur);
+	assert((char*)mem < (char*)cur && (char*)cur < (char*)mem + mem->size);
+
+	/* find free block right before the p */
+	b = mem->headblock;
+	while (b->next != 0 && b->next < cur) {
+		b = b->next;
+	}
+
+	/* restore block */
+	cur->next = b->next;
+	b->next = cur;
+	size = cur->size;
+
+	TRACE(" avail %d (%dKB)", mem->avail, mem->avail / 1024);
+	mem->avail += size;
+
+	/* combine prev|cur */
+	if (PADD(b, b->size) == (char *)cur) {
+		b->size += cur->size;
+		b->next = cur->next;
+		cur = b;
+		TRACE("%s", " combine prev");
+	}
+
+	/* combine cur|next */
+	b = cur->next;
+	if (PADD(cur, cur->size) == (char *)b) {
+		cur->size += b->size;
+		cur->next = b->next;
+		TRACE("%s", " combine next");
+	}
+	TRACE(" -> avail %d (%dKB)", mem->avail, mem->avail / 1024);
+	return size;
+}
+/* }}} */
+static XC_MEM_CALLOC(xc_mem_calloc) /* {{{ */
+{
+	xc_memsize_t realsize = memb * size;
+	void *p = xc_mem_malloc(mem, realsize);
+
+	if (p) {
+		memset(p, 0, realsize);
+	}
+	return p;
+}
+/* }}} */
+static XC_MEM_REALLOC(xc_mem_realloc) /* {{{ */
+{
+	void *newp = xc_mem_malloc(mem, size);
+	if (p && newp) {
+		memcpy(newp, p, size);
+		xc_mem_free(mem, p);
+	}
+	return newp;
+}
+/* }}} */
+static XC_MEM_STRNDUP(xc_mem_strndup) /* {{{ */
+{
+	void *p = xc_mem_malloc(mem, len + 1);
+	if (p) {
+		memcpy(p, str, len + 1);
+	}
+	return p;
+}
+/* }}} */
+static XC_MEM_STRDUP(xc_mem_strdup) /* {{{ */
+{
+	return xc_mem_strndup(mem, str, strlen(str));
+}
+/* }}} */
+
+static XC_MEM_AVAIL(xc_mem_avail) /* {{{ */
+{
+	return mem->avail;
+}
+/* }}} */
+static XC_MEM_SIZE(xc_mem_size) /* {{{ */
+{
+	return mem->size;
+}
+/* }}} */
+
+static XC_MEM_FREEBLOCK_FIRST(xc_mem_freeblock_first) /* {{{ */
+{
+	return mem->headblock->next;
+}
+/* }}} */
+XC_MEM_FREEBLOCK_NEXT(xc_mem_freeblock_next) /* {{{ */
+{
+	return block->next;
+}
+/* }}} */
+XC_MEM_BLOCK_SIZE(xc_mem_block_size) /* {{{ */
+{
+	return block->size;
+}
+/* }}} */
+XC_MEM_BLOCK_OFFSET(xc_mem_block_offset) /* {{{ */
+{
+	return ((char *) block) - ((char *) mem);
+}
+/* }}} */
+
+static XC_MEM_INIT(xc_mem_init) /* {{{ */
+{
+	xc_block_t *b;
+#define MINSIZE (ALIGN(sizeof(xc_mem_t)) + sizeof(xc_block_t))
+	/* requires at least the header and 1 tail block */
+	if (size < MINSIZE) {
+		fprintf(stderr, "xc_mem_init requires %lu bytes at least\n", (unsigned long) MINSIZE);
+		return NULL;
+	}
+	mem->shm = shm;
+	mem->size = size;
+	mem->avail = size - MINSIZE;
+
+	/* pointer to first block, right after ALIGNed header */
+	b = mem->headblock;
+	xc_block_setup(b, 0, (xc_block_t *) PADD(mem, ALIGN(sizeof(xc_mem_t))));
+
+	/* first block*/
+	b = b->next;
+	xc_block_setup(b, mem->avail, 0);
+#undef MINSIZE
+
+	return mem;
+}
+/* }}} */
+static XC_MEM_DESTROY(xc_mem_destroy) /* {{{ */
+{
+}
+/* }}} */
+
+#ifdef TEST
+/* {{{ */
+#undef CHECK
+#define CHECK(a, msg) do { if ((a) == NULL) { puts(msg); return -1; } } while (0)
+#include <time.h>
+
+int main()
+{
+	int count = 0;
+	void *p;
+	void *memory;
+	xc_mem_t *mem;
+	void **ptrs;
+	int size, i;
+
+#if 0
+	fprintf(stderr, "%s", "Input test size: ");
+	scanf("%d", &size);
+#else
+	size = 100;
+#endif
+	CHECK(memory = malloc(size), "OOM");
+	CHECK(ptrs   = malloc(size * sizeof(void*)), "OOM");
+	CHECK(mem    = xc_mem_init(memory, size), "Failed init memory allocator");
+
+	while ((p = xc_mem_malloc(mem, 1))) {
+		ptrs[count ++] = p;
+	}
+	fprintf(stderr, "count=%d, random freeing\n", count);
+	srandom(time(NULL));
+	while (count) {
+		i = (random() % count);
+		fprintf(stderr, "freeing %d: ", i);
+		xc_mem_free(mem, ptrs[i]);
+		ptrs[i] = ptrs[count - 1];
+		count --;
+	}
+
+	free(ptrs);
+	free(memory);
+	return 0;
+}
+/* }}} */
+#endif
+
+typedef struct {
+	const char              *name;
+	const xc_mem_handlers_t *handlers;
+} xc_mem_scheme_t;
+static xc_mem_scheme_t xc_mem_schemes[10];
+
+int xc_mem_scheme_register(const char *name, const xc_mem_handlers_t *handlers) /* {{{ */
+{
+	int i;
+	for (i = 0; i < 10; i ++) {
+		if (!xc_mem_schemes[i].name) {
+			xc_mem_schemes[i].name = name;
+			xc_mem_schemes[i].handlers = handlers;
+			return 1;
+		}
+	}
+	return 0;
+}
+/* }}} */
+const xc_mem_handlers_t *xc_mem_scheme_find(const char *name) /* {{{ */
+{
+	int i;
+	for (i = 0; i < 10 && xc_mem_schemes[i].name; i ++) {
+		if (strcmp(xc_mem_schemes[i].name, name) == 0) {
+			return xc_mem_schemes[i].handlers;
+		}
+	}
+	return NULL;
+}
+/* }}} */
+
+static xc_mem_handlers_t xc_mem_mem_handlers = XC_MEM_HANDLERS(mem);
+void xc_shm_mem_init() /* {{{ */
+{
+	memset(xc_mem_schemes, 0, sizeof(xc_mem_schemes));
+
+	if (xc_mem_scheme_register("mem", &xc_mem_mem_handlers) == 0) {
+		zend_error(E_ERROR, "XCache: failed to register mem mem_scheme");
+	}
+}
+/* }}} */
Index: /tags/1.3.0-rc1/xc_shm.c
===================================================================
--- /tags/1.3.0-rc1/xc_shm.c	(revision 479)
+++ /tags/1.3.0-rc1/xc_shm.c	(revision 479)
@@ -0,0 +1,99 @@
+#ifdef TEST
+#include <limits.h>
+#include <stdio.h>
+#else
+#include <php.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "xc_shm.h"
+
+struct _xc_shm_scheme_t {
+	const char              *name;
+	const xc_shm_handlers_t *handlers;
+};
+static xc_shm_scheme_t xc_shm_schemes[10];
+
+void xc_shm_init_modules() /* {{{ */
+{
+	extern void xc_shm_mem_init();
+#ifdef HAVE_XCACHE_TEST
+	extern void xc_shm_malloc_register();
+#endif
+	extern void xc_shm_mmap_register();
+
+	memset(xc_shm_schemes, 0, sizeof(xc_shm_schemes));
+	xc_shm_mem_init();
+#ifdef HAVE_XCACHE_TEST
+	xc_shm_malloc_register();
+#endif
+	xc_shm_mmap_register();
+}
+/* }}} */
+int xc_shm_scheme_register(const char *name, const xc_shm_handlers_t *handlers) /* {{{ */
+{
+	int i;
+	for (i = 0; i < 10; i ++) {
+		if (!xc_shm_schemes[i].name) {
+			xc_shm_schemes[i].name = name;
+			xc_shm_schemes[i].handlers = handlers;
+			return 1;
+		}
+	}
+	return 0;
+}
+/* }}} */
+const xc_shm_handlers_t *xc_shm_scheme_find(const char *name) /* {{{ */
+{
+	int i;
+	for (i = 0; i < 10 && xc_shm_schemes[i].name; i ++) {
+		if (strcmp(xc_shm_schemes[i].name, name) == 0) {
+			return xc_shm_schemes[i].handlers;
+		}
+	}
+	return NULL;
+}
+/* }}} */
+xc_shm_scheme_t *xc_shm_scheme_first() /* {{{ */
+{
+	return xc_shm_schemes;
+}
+/* }}} */
+xc_shm_scheme_t *xc_shm_scheme_next(xc_shm_scheme_t *scheme) /* {{{ */
+{
+	scheme ++;
+	return scheme->name ? scheme : NULL;
+}
+/* }}} */
+const char *xc_shm_scheme_name(xc_shm_scheme_t *scheme) /* {{{ */
+{
+	assert(scheme);
+	return scheme->name;
+}
+/* }}} */
+xc_shm_t *xc_shm_init(const char *type, xc_shmsize_t size, int readonly_protection, const void *arg1, const void *arg2) /* {{{ */
+{
+	const xc_shm_handlers_t *handlers = xc_shm_scheme_find(type);
+
+	if (handlers) {
+		xc_shm_t *shm = handlers->init(size, readonly_protection, arg1, arg2);
+		if (shm) {
+			shm->handlers = handlers;
+		}
+		return shm;
+	}
+
+	return NULL;
+}
+/* }}} */
+void xc_shm_destroy(xc_shm_t *shm) /* {{{ */
+{
+	shm->handlers->destroy(shm);
+}
+/* }}} */
Index: /tags/1.3.0-rc1/phpdop.phpr
===================================================================
--- /tags/1.3.0-rc1/phpdop.phpr	(revision 604)
+++ /tags/1.3.0-rc1/phpdop.phpr	(revision 604)
@@ -0,0 +1,121 @@
+#! /usr/bin/php
+<?php
+
+$srcdir = dirname(__FILE__);
+if (file_exists("$srcdir/phpdc.debug.php")) {
+	include("$srcdir/phpdc.debug.php");
+}
+
+function get_op($op)
+{
+	switch ($op['op_type']) {
+	case 1: // CONST
+		return var_export($op['u.constant'], true);
+
+	case 2: // IS_TMP_VAR
+		return 't@' . $op['u.var'];
+
+	case 4:
+		return 'v$' . $op['u.var'];
+
+	case 8: // UNUSED
+		if (isset($op['u.opline_num'])) {
+			return 'l#' . $op['u.opline_num'];
+		}
+		else {
+			return '-';
+		}
+
+	default:
+		return $op['op_type'] . $op['u.var'];
+	}
+}
+
+function dump_opcodes($op_array, $indent = '')
+{
+	$types = array('result' => 5, 'op1' => 20, 'op2' => 20);
+	foreach ($op_array as $line => $op) {
+		echo $indent;
+		echo sprintf("%3d ", $op['lineno']);
+		echo sprintf("%3x ", $line);
+		$name = xcache_get_opcode($op['opcode']);
+
+		if (substr($name, 0, 5) == 'ZEND_') {
+			$name = substr($name, 5);
+		}
+		echo str_pad($name, 25);
+
+		foreach ($types as $t => $len) {
+			echo str_pad(isset($op[$t]) ? get_op($op[$t]) : "", $len);
+		}
+		printf("%5s", isset($op['extended_value']) ?  $op['extended_value'] : "");
+
+		echo "\n";
+	}
+}
+
+function dump_function($name, $func, $indent = '')
+{
+	if (isset($func['op_array'])) {
+		$op_array = $func['op_array'];
+		unset($func['op_array']);
+	}
+	else {
+		$op_array = null;
+	}
+	var_dump($func);
+	echo $indent, 'function ', $name, "\n";
+	if (isset($op_array)) {
+		dump_opcodes($op_array['opcodes'], "  " . $indent);
+	}
+}
+
+function dump_class($name, $class, $indent = '')
+{
+	if (isset($class['function_table'])) {
+		$funcs = $class['function_table'];
+		unset($class['function_table']);
+	}
+	else {
+		$funcs = null;
+	}
+	echo $indent, 'class ', $name, "\n";
+	if (isset($funcs)) {
+		foreach ($funcs as $name => $func) {
+			dump_function($name, $func, "  " . $indent);
+		}
+	}
+}
+
+if (!isset($argv[1])) {
+	die("Usage: $argv[0] <file>\n");
+}
+$pk = xcache_dasm_file($argv[1]);
+$op_array = $funcs = $classes = null;
+if (isset($pk['op_array'])) {
+	$op_array = $pk['op_array'];
+	unset($pk['op_array']);
+}
+if (isset($pk['function_table'])) {
+	$funcs = $pk['function_table'];
+	unset($pk['function_table']);
+}
+if (isset($pk['class_table'])) {
+	$classes = $pk['class_table'];
+	unset($pk['class_table']);
+}
+var_dump($pk);
+if (isset($op_array)) {
+	dump_opcodes($op_array['opcodes']);
+}
+if (isset($funcs)) {
+	foreach ($funcs as $name => $func) {
+		dump_function($name, $func);
+	}
+}
+if (isset($classes)) {
+	foreach ($classes as $name => $class) {
+		dump_class($name, $class);
+	}
+}
+
Index: /tags/1.3.0-rc1/const_string.h
===================================================================
--- /tags/1.3.0-rc1/const_string.h	(revision 394)
+++ /tags/1.3.0-rc1/const_string.h	(revision 394)
@@ -0,0 +1,8 @@
+#include "php.h"
+
+zend_uchar xc_get_op_type_count();
+const char *xc_get_op_type(zend_uchar op_type);
+zend_uchar xc_get_data_type_count();
+const char *xc_get_data_type(zend_uchar data_type);
+zend_uchar xc_get_opcode_count();
+const char *xc_get_opcode(zend_uchar opcode);
Index: /tags/1.3.0-rc1/mem.h
===================================================================
--- /tags/1.3.0-rc1/mem.h	(revision 394)
+++ /tags/1.3.0-rc1/mem.h	(revision 394)
@@ -0,0 +1,72 @@
+typedef struct _xc_mem_handlers_t xc_mem_handlers_t;
+
+#ifndef XC_MEM_IMPL
+struct _xc_mem_t {
+	const xc_mem_handlers_t *handlers;
+	xc_shm_t                *shm;
+};
+#   define XC_MEM_IMPL _xc_mem_t
+#endif
+
+#ifndef XC_MEMBLOCK_IMPL
+#   define XC_MEMBLOCK_IMPL _xc_block_t
+#endif
+typedef struct XC_MEM_IMPL xc_mem_t;
+typedef struct XC_MEMBLOCK_IMPL xc_block_t;
+typedef unsigned int xc_memsize_t;
+
+/* shm::mem */
+#define XC_MEM_MALLOC(func)          void *func(xc_mem_t *mem, xc_memsize_t size)
+#define XC_MEM_FREE(func)            xc_memsize_t  func(xc_mem_t *mem, const void *p)
+#define XC_MEM_CALLOC(func)          void *func(xc_mem_t *mem, xc_memsize_t memb, xc_memsize_t size)
+#define XC_MEM_REALLOC(func)         void *func(xc_mem_t *mem, const void *p, xc_memsize_t size)
+#define XC_MEM_STRNDUP(func)         char *func(xc_mem_t *mem, const char *str, xc_memsize_t len)
+#define XC_MEM_STRDUP(func)          char *func(xc_mem_t *mem, const char *str)
+#define XC_MEM_AVAIL(func)           xc_memsize_t      func(xc_mem_t *mem)
+#define XC_MEM_SIZE(func)            xc_memsize_t      func(xc_mem_t *mem)
+#define XC_MEM_FREEBLOCK_FIRST(func) const xc_block_t *func(xc_mem_t *mem)
+#define XC_MEM_FREEBLOCK_NEXT(func)  const xc_block_t *func(const xc_block_t *block)
+#define XC_MEM_BLOCK_SIZE(func)      xc_memsize_t      func(const xc_block_t *block)
+#define XC_MEM_BLOCK_OFFSET(func)    xc_memsize_t      func(const xc_mem_t *mem, const xc_block_t *block)
+
+#define XC_MEM_INIT(func)            xc_mem_t *func(xc_shm_t *shm, xc_mem_t *mem, xc_memsize_t size)
+#define XC_MEM_DESTROY(func)         void func(xc_mem_t *mem)
+
+#define XC_MEM_HANDLERS(name)   {  \
+	xc_##name##_malloc             \
+	, xc_##name##_free             \
+	, xc_##name##_calloc           \
+	, xc_##name##_realloc          \
+	, xc_##name##_strndup          \
+	, xc_##name##_strdup           \
+	, xc_##name##_avail            \
+	, xc_##name##_size             \
+	, xc_##name##_freeblock_first  \
+	, xc_##name##_freeblock_next   \
+	, xc_##name##_block_size       \
+	, xc_##name##_block_offset     \
+\
+	, xc_##name##_init             \
+	, xc_##name##_destroy          \
+}
+
+struct _xc_mem_handlers_t {
+	XC_MEM_MALLOC((*malloc));
+	XC_MEM_FREE((*free));
+	XC_MEM_CALLOC((*calloc));
+	XC_MEM_REALLOC((*realloc));
+	XC_MEM_STRNDUP((*strndup));
+	XC_MEM_STRDUP((*strdup));
+	XC_MEM_AVAIL((*avail));
+	XC_MEM_SIZE((*size));
+	XC_MEM_FREEBLOCK_FIRST((*freeblock_first));
+	XC_MEM_FREEBLOCK_NEXT((*freeblock_next));
+	XC_MEM_BLOCK_SIZE((*block_size));
+	XC_MEM_BLOCK_OFFSET((*block_offset));
+
+	XC_MEM_INIT((*init));
+	XC_MEM_DESTROY((*destroy));
+};
+
+int xc_mem_scheme_register(const char *name, const xc_mem_handlers_t *handlers);
+const xc_mem_handlers_t *xc_mem_scheme_find(const char *name);
Index: /tags/1.3.0-rc1/xc_shm.h
===================================================================
--- /tags/1.3.0-rc1/xc_shm.h	(revision 593)
+++ /tags/1.3.0-rc1/xc_shm.h	(revision 593)
@@ -0,0 +1,70 @@
+#ifndef XC_SHM_H
+#define XC_SHM_H
+typedef struct _xc_shm_handlers_t xc_shm_handlers_t;
+
+#ifndef XC_SHM_IMPL
+struct _xc_shm_t {
+	const xc_shm_handlers_t *handlers;
+};
+#define XC_SHM_IMPL _xc_shm_t
+#endif
+
+typedef struct XC_SHM_IMPL xc_shm_t;
+typedef size_t xc_shmsize_t;
+
+#include "mem.h"
+
+/* shm */
+#define XC_SHM_CAN_READONLY(func) int   func(xc_shm_t *shm)
+#define XC_SHM_IS_READWRITE(func) int   func(xc_shm_t *shm, const void *p)
+#define XC_SHM_IS_READONLY(func)  int   func(xc_shm_t *shm, const void *p)
+#define XC_SHM_TO_READWRITE(func) void *func(xc_shm_t *shm, void *p)
+#define XC_SHM_TO_READONLY(func)  void *func(xc_shm_t *shm, void *p)
+
+#define XC_SHM_INIT(func)         xc_shm_t *func(xc_shmsize_t size, int readonly_protection, const void *arg1, const void *arg2)
+#define XC_SHM_DESTROY(func)      void func(xc_shm_t *shm)
+
+#define XC_SHM_MEMINIT(func)      xc_mem_t *func(xc_shm_t *shm, xc_memsize_t size)
+#define XC_SHM_MEMDESTROY(func)   void func(xc_mem_t *mem)
+
+#define XC_SHM_HANDLERS(name)    { \
+	NULL                           \
+	, xc_##name##_can_readonly     \
+	, xc_##name##_is_readwrite     \
+	, xc_##name##_is_readonly      \
+	, xc_##name##_to_readwrite     \
+	, xc_##name##_to_readonly      \
+\
+	, xc_##name##_init             \
+	, xc_##name##_destroy          \
+\
+	, xc_##name##_meminit          \
+	, xc_##name##_memdestroy       \
+}
+
+struct _xc_shm_handlers_t {
+	const xc_mem_handlers_t *memhandlers;
+	XC_SHM_CAN_READONLY((*can_readonly));
+	XC_SHM_IS_READWRITE((*is_readwrite));
+	XC_SHM_IS_READONLY((*is_readonly));
+	XC_SHM_TO_READWRITE((*to_readwrite));
+	XC_SHM_TO_READONLY((*to_readonly));
+	XC_SHM_INIT((*init));
+	XC_SHM_DESTROY((*destroy));
+
+	XC_SHM_MEMINIT((*meminit));
+	XC_SHM_MEMDESTROY((*memdestroy));
+};
+
+typedef struct _xc_shm_scheme_t xc_shm_scheme_t;
+
+void xc_shm_init_modules();
+int xc_shm_scheme_register(const char *name, const xc_shm_handlers_t *handlers);
+const xc_shm_handlers_t *xc_shm_scheme_find(const char *name);
+xc_shm_scheme_t *xc_shm_scheme_first();
+xc_shm_scheme_t *xc_shm_scheme_next(xc_shm_scheme_t *scheme);
+const char *xc_shm_scheme_name(xc_shm_scheme_t *scheme);
+
+xc_shm_t *xc_shm_init(const char *type, xc_shmsize_t size, int readonly_protection, const void *arg1, const void *arg2);
+void xc_shm_destroy(xc_shm_t *shm);
+#endif
Index: /tags/1.3.0-rc1/const_string_opcodes_php5.1.h
===================================================================
--- /tags/1.3.0-rc1/const_string_opcodes_php5.1.h	(revision 626)
+++ /tags/1.3.0-rc1/const_string_opcodes_php5.1.h	(revision 626)
@@ -0,0 +1,157 @@
+/* size = 154 */
+static const char *const xc_opcode_names[] = {
+/* 0 */	"NOP",
+/* 1 */	"ADD",
+/* 2 */	"SUB",
+/* 3 */	"MUL",
+/* 4 */	"DIV",
+/* 5 */	"MOD",
+/* 6 */	"SL",
+/* 7 */	"SR",
+/* 8 */	"CONCAT",
+/* 9 */	"BW_OR",
+/* 10 */	"BW_AND",
+/* 11 */	"BW_XOR",
+/* 12 */	"BW_NOT",
+/* 13 */	"BOOL_NOT",
+/* 14 */	"BOOL_XOR",
+/* 15 */	"IS_IDENTICAL",
+/* 16 */	"IS_NOT_IDENTICAL",
+/* 17 */	"IS_EQUAL",
+/* 18 */	"IS_NOT_EQUAL",
+/* 19 */	"IS_SMALLER",
+/* 20 */	"IS_SMALLER_OR_EQUAL",
+/* 21 */	"CAST",
+/* 22 */	"QM_ASSIGN",
+/* 23 */	"ASSIGN_ADD",
+/* 24 */	"ASSIGN_SUB",
+/* 25 */	"ASSIGN_MUL",
+/* 26 */	"ASSIGN_DIV",
+/* 27 */	"ASSIGN_MOD",
+/* 28 */	"ASSIGN_SL",
+/* 29 */	"ASSIGN_SR",
+/* 30 */	"ASSIGN_CONCAT",
+/* 31 */	"ASSIGN_BW_OR",
+/* 32 */	"ASSIGN_BW_AND",
+/* 33 */	"ASSIGN_BW_XOR",
+/* 34 */	"PRE_INC",
+/* 35 */	"PRE_DEC",
+/* 36 */	"POST_INC",
+/* 37 */	"POST_DEC",
+/* 38 */	"ASSIGN",
+/* 39 */	"ASSIGN_REF",
+/* 40 */	"ECHO",
+/* 41 */	"PRINT",
+/* 42 */	"JMP",
+/* 43 */	"JMPZ",
+/* 44 */	"JMPNZ",
+/* 45 */	"JMPZNZ",
+/* 46 */	"JMPZ_EX",
+/* 47 */	"JMPNZ_EX",
+/* 48 */	"CASE",
+/* 49 */	"SWITCH_FREE",
+/* 50 */	"BRK",
+/* 51 */	"CONT",
+/* 52 */	"BOOL",
+/* 53 */	"INIT_STRING",
+/* 54 */	"ADD_CHAR",
+/* 55 */	"ADD_STRING",
+/* 56 */	"ADD_VAR",
+/* 57 */	"BEGIN_SILENCE",
+/* 58 */	"END_SILENCE",
+/* 59 */	"INIT_FCALL_BY_NAME",
+/* 60 */	"DO_FCALL",
+/* 61 */	"DO_FCALL_BY_NAME",
+/* 62 */	"RETURN",
+/* 63 */	"RECV",
+/* 64 */	"RECV_INIT",
+/* 65 */	"SEND_VAL",
+/* 66 */	"SEND_VAR",
+/* 67 */	"SEND_REF",
+/* 68 */	"NEW",
+/* 69 */	"INIT_NS_FCALL_BY_NAME",
+/* 70 */	"FREE",
+/* 71 */	"INIT_ARRAY",
+/* 72 */	"ADD_ARRAY_ELEMENT",
+/* 73 */	"INCLUDE_OR_EVAL",
+/* 74 */	"UNSET_VAR",
+/* 75 */	"UNSET_DIM",
+/* 76 */	"UNSET_OBJ",
+/* 77 */	"FE_RESET",
+/* 78 */	"FE_FETCH",
+/* 79 */	"EXIT",
+/* 80 */	"FETCH_R",
+/* 81 */	"FETCH_DIM_R",
+/* 82 */	"FETCH_OBJ_R",
+/* 83 */	"FETCH_W",
+/* 84 */	"FETCH_DIM_W",
+/* 85 */	"FETCH_OBJ_W",
+/* 86 */	"FETCH_RW",
+/* 87 */	"FETCH_DIM_RW",
+/* 88 */	"FETCH_OBJ_RW",
+/* 89 */	"FETCH_IS",
+/* 90 */	"FETCH_DIM_IS",
+/* 91 */	"FETCH_OBJ_IS",
+/* 92 */	"FETCH_FUNC_ARG",
+/* 93 */	"FETCH_DIM_FUNC_ARG",
+/* 94 */	"FETCH_OBJ_FUNC_ARG",
+/* 95 */	"FETCH_UNSET",
+/* 96 */	"FETCH_DIM_UNSET",
+/* 97 */	"FETCH_OBJ_UNSET",
+/* 98 */	"FETCH_DIM_TMP_VAR",
+/* 99 */	"FETCH_CONSTANT",
+/* 100 */	"GOTO",
+/* 101 */	"EXT_STMT",
+/* 102 */	"EXT_FCALL_BEGIN",
+/* 103 */	"EXT_FCALL_END",
+/* 104 */	"EXT_NOP",
+/* 105 */	"TICKS",
+/* 106 */	"SEND_VAR_NO_REF",
+/* 107 */	"CATCH",
+/* 108 */	"THROW",
+/* 109 */	"FETCH_CLASS",
+/* 110 */	"CLONE",
+/* 111 */	"UNDEF",
+/* 112 */	"INIT_METHOD_CALL",
+/* 113 */	"INIT_STATIC_METHOD_CALL",
+/* 114 */	"ISSET_ISEMPTY_VAR",
+/* 115 */	"ISSET_ISEMPTY_DIM_OBJ",
+/* 116 */	"UNDEF",
+/* 117 */	"UNDEF",
+/* 118 */	"UNDEF",
+/* 119 */	"UNDEF",
+/* 120 */	"UNDEF",
+/* 121 */	"UNDEF",
+/* 122 */	"UNDEF",
+/* 123 */	"UNDEF",
+/* 124 */	"UNDEF",
+/* 125 */	"UNDEF",
+/* 126 */	"UNDEF",
+/* 127 */	"UNDEF",
+/* 128 */	"UNDEF",
+/* 129 */	"UNDEF",
+/* 130 */	"UNDEF",
+/* 131 */	"UNDEF",
+/* 132 */	"PRE_INC_OBJ",
+/* 133 */	"PRE_DEC_OBJ",
+/* 134 */	"POST_INC_OBJ",
+/* 135 */	"POST_DEC_OBJ",
+/* 136 */	"ASSIGN_OBJ",
+/* 137 */	"OP_DATA",
+/* 138 */	"INSTANCEOF",
+/* 139 */	"DECLARE_CLASS",
+/* 140 */	"DECLARE_INHERITED_CLASS",
+/* 141 */	"DECLARE_FUNCTION",
+/* 142 */	"RAISE_ABSTRACT_ERROR",
+/* 143 */	"DECLARE_CONST",
+/* 144 */	"ADD_INTERFACE",
+/* 145 */	"DECLARE_INHERITED_CLASS_DELAYED",
+/* 146 */	"VERIFY_ABSTRACT_CLASS",
+/* 147 */	"ASSIGN_DIM",
+/* 148 */	"ISSET_ISEMPTY_PROP_OBJ",
+/* 149 */	"HANDLE_EXCEPTION",
+/* 150 */	"USER_OPCODE",
+/* 151 */	"UNDEF",
+/* 152 */	"JMP_SET",
+/* 153 */	"DECLARE_LAMBDA_FUNCTION"
+};
Index: /tags/1.3.0-rc1/xcache.ini
===================================================================
--- /tags/1.3.0-rc1/xcache.ini	(revision 623)
+++ /tags/1.3.0-rc1/xcache.ini	(revision 623)
@@ -0,0 +1,71 @@
+[xcache-common]
+;; install as zend extension (recommended), normally "$extension_dir/xcache.so"
+zend_extension = /usr/local/lib/php/extensions/non-debug-non-zts-xxx/xcache.so
+; zend_extension_ts = /usr/local/lib/php/extensions/non-debug-zts-xxx/xcache.so
+;; For windows users, replace xcache.so with php_xcache.dll
+zend_extension_ts = c:/php/extensions/php_xcache.dll
+;; or install as extension, make sure your extension_dir setting is correct
+; extension = xcache.so
+;; or win32:
+; extension = php_xcache.dll
+
+[xcache.admin]
+xcache.admin.enable_auth = On
+xcache.admin.user = "mOo"
+; xcache.admin.pass = md5($your_password)
+xcache.admin.pass = ""
+
+[xcache]
+; ini only settings, all the values here is default unless explained
+
+; select low level shm/allocator scheme implemenation
+xcache.shm_scheme =        "mmap"
+; to disable: xcache.size=0
+; to enable : xcache.size=64M etc (any size > 0) and your system mmap allows
+xcache.size  =               60M
+; set to cpu count (cat /proc/cpuinfo |grep -c processor)
+xcache.count =                 1
+; just a hash hints, you can always store count(items) > slots
+xcache.slots =                8K
+; ttl of the cache item, 0=forever
+xcache.ttl   =                 0
+; interval of gc scanning expired items, 0=no scan, other values is in seconds
+xcache.gc_interval =           0
+
+; same as aboves but for variable cache
+xcache.var_size  =            4M
+xcache.var_count =             1
+xcache.var_slots =            8K
+; default ttl
+xcache.var_ttl   =             0
+xcache.var_maxttl   =          0
+xcache.var_gc_interval =     300
+
+xcache.test =                Off
+; N/A for /dev/zero
+xcache.readonly_protection = Off
+; for *nix, xcache.mmap_path is a file path, not directory.
+; Use something like "/tmp/xcache" if you want to turn on ReadonlyProtection
+; 2 group of php won't share the same /tmp/xcache
+; for win32, xcache.mmap_path=anonymous map name, not file path
+xcache.mmap_path =    "/dev/zero"
+
+
+; leave it blank(disabled) or "/tmp/phpcore/"
+; make sure it's writable by php (without checking open_basedir)
+xcache.coredump_directory =   ""
+
+; per request settings
+xcache.cacher =               On
+xcache.stat   =               On
+xcache.optimizer =           Off
+
+[xcache.coverager]
+; per request settings
+; enable coverage data collecting for xcache.coveragedump_directory and xcache_coverager_start/stop/get/clean() functions (will hurt executing performance)
+xcache.coverager =          Off
+
+; ini only settings
+; make sure it's readable (care open_basedir) by coverage viewer script
+; requires xcache.coverager=On
+xcache.coveragedump_directory = ""
Index: /tags/1.3.0-rc1/coverager/coverager.php
===================================================================
--- /tags/1.3.0-rc1/coverager/coverager.php	(revision 623)
+++ /tags/1.3.0-rc1/coverager/coverager.php	(revision 623)
@@ -0,0 +1,360 @@
+<?php
+
+include("./common.php");
+
+class Cycle
+{
+	var $values;
+	var $i;
+	var $count;
+
+	function Cycle($v)
+	{
+		$this->values = func_get_args();
+		$this->i = -1;
+		$this->count = count($this->values);
+	}
+
+	function next()
+	{
+		$this->i = ($this->i + 1) % $this->count;
+		return $this->values[$this->i];
+	}
+
+	function cur()
+	{
+		return $this->values[$this->i];
+	}
+
+	function reset()
+	{
+		$this->i = -1;
+	}
+}
+
+class XcacheCoverageViewer
+{
+	var $syntaxhiglight = true;
+	var $usecache = false;
+	var $include_paths = array();
+	var $exclude_paths = array();
+	var $charset = 'UTF-8';
+	var $lang = 'en-us';
+	var $datadir = null;
+	var $datadir_len = null;
+	var $path = null;
+	var $outpath = null;
+
+	function XcacheCoverageViewer()
+	{
+		$this->datadir = ini_get('xcache.coveragedump_directory');
+
+		// copy config
+		foreach (array('charset', 'include_paths', 'exclude_paths', 'syntaxhiglight', 'usecache', 'datadir', 'lang') as $k) {
+			if (isset($GLOBALS[$k])) {
+				$this->{$k} = $GLOBALS[$k];
+			}
+		}
+
+		$this->datadir = preg_replace('!/$!', '', $this->datadir);
+		$this->datadir_len = strlen($this->datadir);
+
+		$this->path = isset($_GET['path']) ? $_GET['path'] : '';
+		$this->path = preg_replace('!\.{2,}!', '.', $this->path);
+		$qsep = preg_quote(DIRECTORY_SEPARATOR, '!');
+		$this->path = preg_replace("![\\\\$qsep]{2,}!", DIRECTORY_SEPARATOR, $this->path);
+		$this->path = preg_replace("!$qsep$!", '', $this->path);
+		if ($this->path == '/') {
+			$this->path = '';
+		}
+		$this->outpath = $this->datadir . $this->path;
+	}
+
+	function main()
+	{
+		$path = $this->path;
+
+		if (is_dir($this->outpath)) {
+			$action = 'dir';
+			$prefix_len = strlen($path) + 1;
+			$dirinfo = $this->loadDir($this->outpath);
+			if (!$this->usecache) {
+				ksort($dirinfo['subdirs']);
+				ksort($dirinfo['files']);
+			}
+		}
+		else if (is_file($this->outpath . ".pcov")) {
+			$action = 'file';
+
+			$dir = dirname($path);
+			$filename = basename($path);
+
+			$fileinfo = $this->loadCov($this->outpath . ".pcov");
+
+			$lines = file($path);
+			// fix the tabs not in the middle
+			foreach ($lines as $l => $line) {
+				if (preg_match('!^(\\t*)([^\\t]+\\t.*)$!s', $line, $m)) {
+					$lines[$l] = $m[1];
+					$chunks = explode("\t", $m[2]);
+					for ($i = 0, $c = count($chunks) - 1; $i < $c; $i ++) {
+						$lines[$l] .= $chunks[$i] . str_repeat(" ", 4 - (strlen($chunks[$i]) % 4));
+					}
+					$lines[$l] .= $chunks[$c];
+				}
+			}
+			if ($this->syntaxhiglight) {
+				$source = implode('', $lines);
+				ob_start();
+				highlight_string($source);
+				$lines = str_replace("\n", "", ob_get_clean());
+				$lines = str_replace('<code>', '', $lines);
+				$lines = str_replace('</code>', '', $lines);
+				$lines = preg_replace('(^<span[^>]*>|</span>$)', '', $lines);
+				$lines = explode('<br />', $lines);
+				$last = array_pop($lines);
+				$lines[count($lines) - 1] .= $last;
+				$filecov = sprint_cov($fileinfo['cov'], $lines, false);
+				unset($source);
+			}
+			else {
+				$filecov = sprint_cov($fileinfo['cov'], $lines);
+			}
+
+			list($tplfile, $tpllines, $tplcov) = $this->loadTplCov($fileinfo['cov'], substr($this->outpath, $this->datadir_len));
+			if ($tplfile) {
+				$tplcov = sprint_cov($tplcov, $tpllines);
+				unset($tpllines);
+			}
+		}
+		else if (!$this->datadir) {
+			$action = 'error';
+			$error  = 'require `ini:xcache.coveragedump_directory` or `config:$datadir` to be set';
+		}
+		else {
+			$action = 'error';
+			$error  = "no data";
+		}
+
+		$xcache_version = defined('XCACHE_VERSION') ? XCACHE_VERSION : '';
+		include("coverager.tpl.php");
+	}
+
+	function loadDir($outdir, $addtodo = null)
+	{
+		if ($this->usecache) {
+			$cachefile = $outdir . "/.pcovcache";
+			if (file_exists($cachefile)) {
+				return unserialize(file_get_contents($cachefile));
+			}
+		}
+		$srcdir = substr($outdir, $this->datadir_len);
+
+		$total = $hits = $todos = 0;
+		$files = array();
+		$subdirs = array();
+		if (!isset($addtodo)) {
+			if ($this->include_paths) {
+				foreach ($this->include_paths as $p) {
+					if (strncmp($p, $srcdir, strlen($p)) == 0) {
+						$addtodo = true;
+						break;
+					}
+				}
+			}
+		}
+		if ($addtodo) {
+			if ($this->exclude_paths) {
+				foreach ($this->exclude_paths as $p) {
+					if (strncmp($p, $srcdir, strlen($p)) == 0) {
+						$addtodo = false;
+						break;
+					}
+				}
+			}
+		}
+		foreach (glob($outdir . "/*") as $outfile) {
+			if (is_dir($outfile)) {
+				$info = $this->loadDir($outfile, $addtodo);
+				$srcfile = substr($outfile, $this->datadir_len);
+				$subdirs += $info['subdirs'];
+				$total   += $info['total'];
+				$hits    += $info['hits'];
+				$todos   += $info['todos'];
+				unset($info['subdirs']);
+				$subdirs[$srcfile] = $info;
+			}
+			else if (substr($outfile, -5) == ".pcov") {
+				// pass
+				$info = $this->loadFile($outfile);
+				$total += $info['total'];
+				$hits  += $info['hits'];
+				$srcfile = substr($outfile, $this->datadir_len, -5);
+				$files[$srcfile] = $info;
+			}
+			else {
+				continue;
+			}
+		}
+		if ($addtodo === true) {
+			foreach (glob($srcdir . "/*") as $srcfile) {
+				if (!isset($files[$srcfile]) && is_file($srcfile)) {
+					$files[$srcfile] = array('total' => 0, 'hits' => 0);
+					$todos ++;
+				}
+				else if (!isset($subdirs[$srcfile]) && is_dir($srcfile)) {
+					$subdirs[$srcfile] = array('total' => 0, 'hits' => 0, 'todos' => 1, 'files' => 0, 'subdirs' => array());
+					$todos ++;
+				}
+			}
+		}
+
+		if ($this->usecache) {
+			ksort($subdirs);
+			ksort($files);
+		}
+
+		$info = array(
+				'total'   => $total,
+				'hits'    => $hits,
+				'todos'   => $todos,
+				'files'   => $files,
+				'subdirs' => $subdirs,
+				);
+
+		if ($this->usecache) {
+			$fp = fopen($cachefile, "wb");
+			fwrite($fp, serialize($info));
+			fclose($fp);
+		}
+		return $info;
+	}
+
+	function loadFile($file)
+	{
+		if ($this->usecache) {
+			$cachefile = $file . "cache";
+			if (file_exists($cachefile)) {
+				return unserialize(file_get_contents($cachefile));
+			}
+		}
+
+		$info = $this->loadCov($file); //, $lines);
+		unset($info['cov']);
+
+		if ($this->usecache) {
+			$fp = fopen($cachefile, "wb");
+			fwrite($fp, serialize($info));
+			fclose($fp);
+		}
+		return $info;
+	}
+
+	function loadCov($file)//, $lines)
+	{
+		$total = $hits = 0;
+
+		$cov = xcache_coverager_decode(file_get_contents($file));
+
+		return array('total' => count($cov) - 1, 'hits' => $cov[0], 'cov' => $cov);
+	}
+
+	function loadTplCov($cov, $ctpl)
+	{
+		$tplinfofile = $ctpl . '.phpinfo';
+
+		if (!file_exists($tplinfofile)) {
+			return;
+		}
+
+		$tplinfo = unserialize(file_get_contents($tplinfofile));
+
+		if (!isset($tplinfo['sourceFile'])) {
+			return;
+		}
+		$tplfile = $tplinfo['sourceFile'];
+		if (!isset($tplinfo['lineMap']) || !count($tplinfo['lineMap'])) {
+			return;
+		}
+
+		$tpllines = file($tplfile);
+
+		$dline = 0;
+		$sline = 0;
+		$tplcov = array();
+		foreach ($cov as $line => $times) {
+			// find nearest line
+			while ($dline < $line) {
+				if ((list($dline, $sline) = each($tplinfo['lineMap'])) === false) {
+					break 2;
+				}
+			}
+
+			$tplcov[$sline] = $times;
+		}
+		return array($tplfile, $tpllines, $tplcov);
+	}
+}
+
+function sprint_cov($cov, $lines, $encode = true)
+{
+	$lastattr = null;
+	foreach ($lines as $l => $line) {
+		$offs = $l + 1;
+		if ($encode) {
+			$line = str_replace("\n", "", htmlspecialchars($line));
+		}
+		else if ($line !== "") {
+			if (substr($line, 0, 7) == '</span>') {
+				$lastattr = null;
+				$line = substr($line, 7);
+			}
+			else if (isset($lastattr)) {
+				$line = $lastattr . $line;
+			}
+
+			if (preg_match('!(<span[^>]+>|</span>)[^<>]*$!', $line, $m)) {
+				if ($m[1] == '</span>') {
+					$lastattr = null;
+				}
+				else {
+					$line .= '</span>';
+					$lastattr = $m[1];
+				}
+			}
+		}
+		if (isset($cov[$offs])) {
+			$lines[$l] = sprintf("<li class=\"line%sCov\"><pre class=\"code\"> %s\t%s\n</pre></li>"
+					, $cov[$offs] ? '' : 'No'
+					, $cov[$offs]
+					, $line);
+		}
+		else {
+			$lines[$l] = "<li><pre class=\"code\">\t$line\n</pre></li>";
+		}
+	}
+	return implode('', $lines);
+}
+
+if (!function_exists('xcache_coverager_decode')) {
+	function xcache_coverager_decode($bytes)
+	{
+		$bytes = unpack('l*', $bytes);
+		$i = 1;
+		if ($bytes[$i ++] != 0x564f4350) {
+			return null;
+		}
+		$end = count($bytes);
+		$cov = array();
+		for (/* empty*/; $i <= $end; $i += 2) {
+			$hits = $bytes[$i + 1];
+			$cov[$bytes[$i]] = $hits <= 0 ? 0 : $hits;
+		}
+		return $cov;
+	}
+}
+
+$app = new XcacheCoverageViewer();
+$app->main();
+
+?>
Index: /tags/1.3.0-rc1/coverager/coverager.css
===================================================================
--- /tags/1.3.0-rc1/coverager/coverager.css	(revision 623)
+++ /tags/1.3.0-rc1/coverager/coverager.css	(revision 623)
@@ -0,0 +1,71 @@
+h1 { text-align: center; display: block; }
+input, table { font-family: sans-serif; font-size: 11px; }
+th { font-size: 12px; }
+table { border-collapse: collapse; }
+table.center { margin-left: auto; margin-right: auto; }
+table\-center { text-align: center; }
+table.cycles { border: 1px solid black; margin-top: 5px; margin-bottom: 5px; }
+table.cycles .col1 { background-color: #f5f5f5; }
+table.cycles .col2 { background-color: #e0e0e0; }
+table.cycles th, table.cycles td { border: 1px solid black; font-family: monospace; }
+table.cycles th { background-color: #9999cc; color: black; font-weight: bold; height: 20px; line-height: 20px; font-family: serif; }
+th a { color: black; font-weight: bold; display: block; width: 100%; height: 100%; }
+
+.coverFile {
+	text-align:       left;
+	color:            gray;
+	padding-left:     10px;
+	padding-right:    10px;
+}
+
+.coverBar {
+	padding-left:     10px;
+	padding-right:    10px;
+}
+
+.coverBarOutline {
+	border: 1px solid black;
+	background-color: #ffffff;
+	width: 100px;
+	font-size: 11px; line-height: 11px;
+	font-family: tahoma;
+	position: relative;
+}
+
+.coverPerHi, .coverPerMed, .coverPerLo {
+	text-align:       center;
+	font-weight:      bold;
+	left: 0px; top: 2px;
+	position: absolute;
+	width: 100%;
+}
+.coverBarHi, .coverBarMed, .coverBarLo { left: 1px; top: 1px; height: 14px; }
+.coverBarHi  { background-color: #A7FC9D; }
+.coverBarMed { background-color: #FFEA20; }
+.coverBarLo  { background-color: #FF0000; }
+
+
+.coverNumHi, .coverNumMed, .coverNumLo {
+	text-align:       right;
+	padding-left:     10px;
+	padding-right:    10px;
+}
+.coverNumHi  { /*background-color: #A7FC9D;*/ }
+.coverNumMed { /*background-color: #FFEA20;*/ }
+.coverNumLo  { background-color: #FF0000; }
+
+.lineCov   { background-color: #F0F0F0; }
+.lineNoCov { background-color: #ffe0e0; }
+div.code {
+	border: 1px solid gray;
+	font-size: 12px;
+}
+pre.code {
+	font-family: monospace;
+	font-size: 12px;
+	white-space: pre;
+	padding: 0; margin: 0;
+}
+
+.footnote { text-align: right; font-size: 12px; }
+.error { color: red; }
Index: /tags/1.3.0-rc1/coverager/config.php.example
===================================================================
--- /tags/1.3.0-rc1/coverager/config.php.example	(revision 623)
+++ /tags/1.3.0-rc1/coverager/config.php.example	(revision 623)
@@ -0,0 +1,59 @@
+<?php
+
+// this is an example only
+// write your own config and name it as config.php
+
+// detected by browser
+// $lang = 'en-us';
+
+$charset = "UTF-8";
+
+// developers only
+$show_todo_strings = false;
+
+// $include_paths = array("/www/my-php-project/");
+// $exclude_paths = array("/www/my-php-project/tmp/");
+$syntaxhiglight = true;
+$usecache = false;
+//// $datadir is default to ini_get("xcache.coveragedump_directory")
+// $datadir = '';
+
+function ob_filter_path_nicer($o)
+{
+	$sep = DIRECTORY_SEPARATOR;
+	$o = str_replace($_SERVER['DOCUMENT_ROOT'],  "{DOCROOT}" . (substr($d, -1) == $sep ? $sep : ""), $o);
+	$xcachedir = realpath(dirname(__FILE__) . "$sep..$sep");
+	$o = str_replace($xcachedir . $sep, "{XCache}$sep", $o);
+	if ($sep == '/') {
+		$o = str_replace("/home/", "{H}/", $o);
+	}
+	return $o;
+}
+
+// implement your auth here if needed
+// {{{ home made login example
+// this is an example only, it's won't work for you without your implemention.
+function check_admin_auth()
+{
+	require("/path/to/user-login-and-permission-lib.php");
+	session_start();
+
+	if (!user_logined()) {
+		if (!ask_the_user_to_login()) {
+			exit;
+		}
+	}
+
+	user_load_permissions();
+	if (!user_is_admin()) {
+		die("Permission denied");
+	}
+
+	return true;
+}
+
+// uncomment:
+// check_admin_auth()
+// }}}
+
+?>
Index: /tags/1.3.0-rc1/coverager/index.php
===================================================================
--- /tags/1.3.0-rc1/coverager/index.php	(revision 394)
+++ /tags/1.3.0-rc1/coverager/index.php	(revision 394)
@@ -0,0 +1,3 @@
+<?php
+
+include("coverager.php");
Index: /tags/1.3.0-rc1/coverager/common-en.lang.php
===================================================================
--- /tags/1.3.0-rc1/coverager/common-en.lang.php	(revision 394)
+++ /tags/1.3.0-rc1/coverager/common-en.lang.php	(revision 394)
@@ -0,0 +1,5 @@
+<?php
+
+$GLOBALS['show_todo_strings'] = false;
+
+?>
Index: /tags/1.3.0-rc1/coverager/common-zh-simplified-gb2312.lang.php
===================================================================
--- /tags/1.3.0-rc1/coverager/common-zh-simplified-gb2312.lang.php	(revision 394)
+++ /tags/1.3.0-rc1/coverager/common-zh-simplified-gb2312.lang.php	(revision 394)
@@ -0,0 +1,25 @@
+<?php
+
+$strings = array(
+		'root'
+		=> '��ʼ',
+		'Directory'
+		=> 'Ŀ¼',
+		'File'
+		=> '�ļ�',
+		'Percent'
+		=> '������',
+		'Hits'
+		=> '����',
+		'Lines'
+		=> '����',
+		'TODO'
+		=> '�����ļ�',
+		'XCache PHP Code Coverage Viewer'
+		=> 'XCache PHP ���븲�ǲ鿴��',
+		'module'
+		=> 'ģ��',
+		''
+		=> '',
+		);
+
Index: /tags/1.3.0-rc1/coverager/common.php
===================================================================
--- /tags/1.3.0-rc1/coverager/common.php	(revision 607)
+++ /tags/1.3.0-rc1/coverager/common.php	(revision 607)
@@ -0,0 +1,112 @@
+<?php
+
+function get_language_file_ex($name, $l, $s)
+{
+	static $lmap = array(
+			'zh'    => 'zh-simplified',
+			'zh-hk' => 'zh-traditional',
+			'zh-tw' => 'zh-traditional',
+			);
+	static $smap = array(
+			'gbk'     => 'gb2312',
+			'gb18030' => 'gb2312',
+			);
+
+	if (isset($lmap[$l])) {
+		$l = $lmap[$l];
+	}
+	if (file_exists($file = "$name-$l-$s.lang.php")) {
+		return $file;
+	}
+	if (isset($smap[$s])) {
+		$s = $smap[$s];
+		if (file_exists($file = "$name-$l-$s.lang.php")) {
+			return $file;
+		}
+	}
+	if (file_exists($file = "$name-$l.lang.php")) {
+		return $file;
+	}
+	return null;
+}
+
+function get_language_file($name)
+{
+	global $charset, $lang;
+	$s = strtolower($charset);
+	if (isset($lang)) {
+		$l = strtolower($lang);
+		$file = get_language_file_ex($name, $l, $s);
+		if (!isset($file)) {
+			$l = strtok($l, '-');
+			$file = get_language_file_ex($name, $l, $s);
+		}
+	}
+	else if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+		foreach (explode(',', str_replace(' ', '', $_SERVER['HTTP_ACCEPT_LANGUAGE'])) as $l) {
+			$l = strtok($l, ';');
+			$file = get_language_file_ex($name, $l, $s);
+			if (isset($file)) {
+				$lang = $l;
+				break;
+			}
+			if (strpos($l, '-') !== false) {
+				$ll = strtok($l, '-');
+				$file = get_language_file_ex($name, $ll, $s);
+				if (isset($file)) {
+					$lang = $l;
+					break;
+				}
+			}
+		}
+	}
+	return isset($file) ? $file : "$name-en.lang.php";
+}
+
+function _T($str)
+{
+	if (isset($GLOBALS['strings'][$str])) {
+		return $GLOBALS['strings'][$str];
+	}
+	if (!empty($GLOBALS['show_todo_strings'])) {
+		return '<span style="color:red">' . htmlspecialchars($str) . '</span>';
+	}
+	return $str;
+}
+
+function stripaddslashes_array($value, $mqs = false)
+{
+	if (is_array($value)) {
+		foreach($value as $k => $v) {
+			$value[$k] = stripaddslashes_array($v, $mqs);
+		}
+	}
+	else if(is_string($value)) {
+		$value = $mqs ? str_replace('\'\'', '\'', $value) : stripslashes($value);
+	}
+	return $value;
+}
+
+error_reporting(E_ALL);
+ini_set('display_errors', 'On');
+define('REQUEST_TIME', time());
+
+if (get_magic_quotes_gpc()) {
+	$mqs = (bool) ini_get('magic_quotes_sybase');
+	$_GET = stripaddslashes_array($_GET, $mqs);
+	$_POST = stripaddslashes_array($_POST, $mqs);
+	$_REQUEST = stripaddslashes_array($_REQUEST, $mqs);
+}
+ini_set('magic_quotes_runtime', '0');
+
+$charset = "UTF-8";
+if (file_exists("./config.php")) {
+	include("./config.php");
+}
+
+include(get_language_file("common"));
+if (!isset($lang)) {
+	$lang = 'en-us';
+}
+
+?>
Index: /tags/1.3.0-rc1/coverager/common-zh-simplified-utf-8.lang.php
===================================================================
--- /tags/1.3.0-rc1/coverager/common-zh-simplified-utf-8.lang.php	(revision 394)
+++ /tags/1.3.0-rc1/coverager/common-zh-simplified-utf-8.lang.php	(revision 394)
@@ -0,0 +1,25 @@
+<?php
+
+$strings = array(
+		'root'
+		=> '开始',
+		'Directory'
+		=> '目录',
+		'File'
+		=> '文件',
+		'Percent'
+		=> '覆盖率',
+		'Hits'
+		=> '命中',
+		'Lines'
+		=> '行数',
+		'TODO'
+		=> '闲置文件',
+		'XCache PHP Code Coverage Viewer'
+		=> 'XCache PHP 代码覆盖查看器',
+		'module'
+		=> '模块',
+		''
+		=> '',
+		);
+
Index: /tags/1.3.0-rc1/coverager/coverager.tpl.php
===================================================================
--- /tags/1.3.0-rc1/coverager/coverager.tpl.php	(revision 623)
+++ /tags/1.3.0-rc1/coverager/coverager.tpl.php	(revision 623)
@@ -0,0 +1,253 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<?php
+echo <<<HEAD
+	<meta http-equiv="Content-Type" content="text/html; charset=$this->charset" />
+	<meta http-equiv="Content-Language" content="{$this->lang}" />
+	<script type="text/javascript" src="tablesort.js" charset="$this->charset"></script>
+HEAD;
+?>
+
+	<link rel="stylesheet" type="text/css" href="coverager.css" />
+	<title><?php echo _T("XCache PHP Code Coverage Viewer"); ?></title>
+</head>
+<body>
+<h1><?php echo _T("XCache PHP Code Coverage Viewer"); ?></h1>
+
+<?php
+function calc_percent($info, &$percent, &$class)
+{
+	if (!$info['total']) {
+		$percent = 0;
+	}
+	else {
+		$percent = (int) ($info['hits'] / $info['total'] * 100);
+	}
+	if ($percent < 15) {
+		$class = "Lo";
+	}
+	else if ($percent < 50) {
+		$class = "Med";
+	}
+	else {
+		$class = "Hi";
+	}
+}
+
+function bar($percent, $class)
+{
+	return <<<EOS
+	<div class="coverBarOutline">
+		<div class="coverBar{$class}" style="width:{$percent}%"></div>
+		<div class="coverPer{$class}">{$percent}</div>
+	</div>
+EOS;
+}
+
+function dir_head()
+{
+	global $cycle;
+	$cycle = new Cycle('class="col1"', 'class="col2"');
+	$l_dir = _T("Directory");
+	$l_per = _T("Percent");
+	$l_hit = _T("Hits");
+	$l_lns = _T("Lines");
+	$l_tds = _T("TODO");
+	return <<<EOS
+<div class="table-center">
+	<table cellpadding="2" cellspacing="0" border="0" class="cycles center">
+	<tr>
+		<th>{$l_dir}</th><th>{$l_per}</th><th>{$l_hit}</th><th>{$l_lns}</th><th>{$l_tds}</th>
+	</tr>
+EOS;
+}
+
+function dir_row($info, $srcdir)
+{
+	global $cycle;
+	if ($info['files'] || $info['todos']) {
+		$srcdir .= DIRECTORY_SEPARATOR;
+		$c = $cycle->next();
+		$srcdir_html = htmlspecialchars($srcdir);
+		$todos = number_format($info['todos']);
+		if ($info['total']) {
+			$srcdir_url = urlencode($srcdir);
+			$hits  = number_format($info['hits']);
+			$total = number_format($info['total']);
+			calc_percent($info, $percent, $class);
+			$bar = bar($percent, $class);
+			return <<<EOS
+			<tr $c>
+				<td class="coverFile"><a href="?path={$srcdir_url}">{$srcdir_html}</a></td>
+				<td class="coverBar">$bar</td>
+				<td class="coverNum{$class}">{$hits}</td>
+				<td class="coverNum{$class}">{$total}</td>
+				<td class="coverNum{$class}">{$todos}</td>
+			</tr>
+EOS;
+		}
+		else {
+			return <<<EOS
+			<tr $c>
+				<td class="coverFile">{$srcdir_html}</td>
+				<td class="coverBar"></td>
+				<td class="coverNumLo"></td>
+				<td class="coverNumLo"></td>
+				<td class="coverNumLo">{$todos}</td>
+			</tr>
+EOS;
+		}
+	}
+}
+
+function dir_foot()
+{
+	return <<<EOS
+	</table>
+</div>
+EOS;
+}
+
+function file_head()
+{
+	global $cycle;
+	$cycle = new Cycle('class="col1"', 'class="col2"');
+	$l_fil = _T("File");
+	$l_per = _T("Percent");
+	$l_hit = _T("Hits");
+	$l_lns = _T("Lines");
+	return <<<EOS
+<div class="center-table">
+	<table cellpadding="2" cellspacing="0" border="0" class="cycles center">
+	<tr>
+		<th>{$l_fil}</th><th>{$l_per}</th><th>{$l_hit}</th><th>{$l_lns}</th>
+	</tr>
+EOS;
+}
+
+function file_row($info, $srcfile)
+{
+	global $cycle;
+
+	$c = $cycle->next();
+	$srcfile_html = htmlspecialchars($srcfile);
+	$total = number_format($info['total']);
+	if ($info['total']) {
+		$hits = number_format($info['hits']);
+		$srcfile_url = urlencode($srcfile);
+		calc_percent($info, $percent, $class);
+		$bar = bar($percent, $class);
+		return <<<EOS
+			<tr $c>
+					<td class="coverFile"><a href="?path={$srcfile_url}">{$srcfile_html}</a></td>
+					<td class="coverBar">$bar</td>
+					<td class="coverNum{$class}">{$hits}</td>
+					<td class="coverNum{$class}">{$total}</td>
+			</tr>
+EOS;
+	}
+	else {
+		return <<<EOS
+			<tr $c>
+					<td class="coverFile">{$srcfile_html}</a></td>
+					<td class="coverBar"></td>
+					<td class="coverNumLo"></td>
+					<td class="coverNumLo">{$total}</td>
+			</tr>
+EOS;
+	}
+}
+
+function file_foot()
+{
+	return <<<EOS
+    </table>
+</div>
+EOS;
+}
+
+$l_root = _T("root");
+if ($action == 'dir') {
+	if (function_exists('ob_filter_path_nicer')) {
+		ob_start('ob_filter_path_nicer');
+	}
+	$path_html = htmlspecialchars($path);
+	echo <<<EOS
+	<div>
+		<a href="?">$l_root</a> $path<br />
+	</div>
+EOS;
+	echo dir_head($dirinfo);
+	echo dir_row($dirinfo, $path);
+	echo dir_foot($dirinfo);
+	if ($dirinfo['subdirs']) {
+		echo dir_head();
+		foreach ($dirinfo['subdirs'] as $srcdir => $info) {
+			echo dir_row($info, $srcdir);
+		}
+		echo dir_foot();
+	}
+	if ($dirinfo['files']) {
+		echo file_head();
+		foreach ($dirinfo['files'] as $srcfile => $info) {
+			echo file_row($info, $srcfile);
+		}
+		echo file_foot();
+	}
+}
+else if ($action == 'file') {
+	if (function_exists('ob_filter_path_nicer')) {
+		ob_start('ob_filter_path_nicer');
+	}
+	$dir_url = urlencode($dir);
+	$dir_html = htmlspecialchars($dir);
+	echo <<<EOS
+	<div>
+		<a href="?">$l_root</a> <a href="?path={$dir_url}">{$dir_html}</a>/<strong>{$filename}</strong><br />
+	</div>
+EOS;
+
+	echo file_head();
+	echo file_row($fileinfo, $path);
+	echo file_foot();
+
+	if ($tplfile) {
+		$tplfile_html = htmlspecialchars($tplfile);
+		echo <<<EOS
+		<div>
+			<a href="#tpl">{$tplfile_html}</a><br />
+		</div>
+EOS;
+	}
+	if (function_exists('ob_filter_path_nicer')) {
+		ob_end_flush();
+	}
+	echo <<<EOS
+	<div class="code">
+		<ol>{$filecov}</ol>
+	</div>
+EOS;
+	if ($tplfile) {
+		echo <<<EOS
+	<a name="tpl">{$tplfile}</a>
+	<div class="code">
+		<ol>{$tplcov}</ol>
+	</div>
+EOS;
+	}
+}
+else {
+	$error_html = htmlspecialchars($error);
+	echo <<<EOS
+	<span class="error">{$error_html}</span>
+EOS;
+}
+?>
+
+<div class="footnote">
+Powered By: XCache <?php echo $xcache_version; ?> coverager <?php echo _T("module"); ?>
+</div>
+
+</body>
+</html>
Index: /tags/1.3.0-rc1/const_string_opcodes_php4.x.h
===================================================================
--- /tags/1.3.0-rc1/const_string_opcodes_php4.x.h	(revision 626)
+++ /tags/1.3.0-rc1/const_string_opcodes_php4.x.h	(revision 626)
@@ -0,0 +1,116 @@
+/* size = 113 */
+static const char *const xc_opcode_names[] = {
+/* 0 */	"NOP",
+/* 1 */	"ADD",
+/* 2 */	"SUB",
+/* 3 */	"MUL",
+/* 4 */	"DIV",
+/* 5 */	"MOD",
+/* 6 */	"SL",
+/* 7 */	"SR",
+/* 8 */	"CONCAT",
+/* 9 */	"BW_OR",
+/* 10 */	"BW_AND",
+/* 11 */	"BW_XOR",
+/* 12 */	"BW_NOT",
+/* 13 */	"BOOL_NOT",
+/* 14 */	"BOOL_XOR",
+/* 15 */	"IS_IDENTICAL",
+/* 16 */	"IS_NOT_IDENTICAL",
+/* 17 */	"IS_EQUAL",
+/* 18 */	"IS_NOT_EQUAL",
+/* 19 */	"IS_SMALLER",
+/* 20 */	"IS_SMALLER_OR_EQUAL",
+/* 21 */	"CAST",
+/* 22 */	"QM_ASSIGN",
+/* 23 */	"ASSIGN_ADD",
+/* 24 */	"ASSIGN_SUB",
+/* 25 */	"ASSIGN_MUL",
+/* 26 */	"ASSIGN_DIV",
+/* 27 */	"ASSIGN_MOD",
+/* 28 */	"ASSIGN_SL",
+/* 29 */	"ASSIGN_SR",
+/* 30 */	"ASSIGN_CONCAT",
+/* 31 */	"ASSIGN_BW_OR",
+/* 32 */	"ASSIGN_BW_AND",
+/* 33 */	"ASSIGN_BW_XOR",
+/* 34 */	"PRE_INC",
+/* 35 */	"PRE_DEC",
+/* 36 */	"POST_INC",
+/* 37 */	"POST_DEC",
+/* 38 */	"ASSIGN",
+/* 39 */	"ASSIGN_REF",
+/* 40 */	"ECHO",
+/* 41 */	"PRINT",
+/* 42 */	"JMP",
+/* 43 */	"JMPZ",
+/* 44 */	"JMPNZ",
+/* 45 */	"JMPZNZ",
+/* 46 */	"JMPZ_EX",
+/* 47 */	"JMPNZ_EX",
+/* 48 */	"CASE",
+/* 49 */	"SWITCH_FREE",
+/* 50 */	"BRK",
+/* 51 */	"CONT",
+/* 52 */	"BOOL",
+/* 53 */	"INIT_STRING",
+/* 54 */	"ADD_CHAR",
+/* 55 */	"ADD_STRING",
+/* 56 */	"ADD_VAR",
+/* 57 */	"BEGIN_SILENCE",
+/* 58 */	"END_SILENCE",
+/* 59 */	"INIT_FCALL_BY_NAME",
+/* 60 */	"DO_FCALL",
+/* 61 */	"DO_FCALL_BY_NAME",
+/* 62 */	"RETURN",
+/* 63 */	"RECV",
+/* 64 */	"RECV_INIT",
+/* 65 */	"SEND_VAL",
+/* 66 */	"SEND_VAR",
+/* 67 */	"SEND_REF",
+/* 68 */	"NEW",
+/* 69 */	"JMP_NO_CTOR",
+/* 70 */	"FREE",
+/* 71 */	"INIT_ARRAY",
+/* 72 */	"ADD_ARRAY_ELEMENT",
+/* 73 */	"INCLUDE_OR_EVAL",
+/* 74 */	"UNSET_VAR",
+/* 75 */	"UNSET_DIM_OBJ",
+/* 76 */	"ISSET_ISEMPTY",
+/* 77 */	"FE_RESET",
+/* 78 */	"FE_FETCH",
+/* 79 */	"EXIT",
+/* 80 */	"FETCH_R",
+/* 81 */	"FETCH_DIM_R",
+/* 82 */	"FETCH_OBJ_R",
+/* 83 */	"FETCH_W",
+/* 84 */	"FETCH_DIM_W",
+/* 85 */	"FETCH_OBJ_W",
+/* 86 */	"FETCH_RW",
+/* 87 */	"FETCH_DIM_RW",
+/* 88 */	"FETCH_OBJ_RW",
+/* 89 */	"FETCH_IS",
+/* 90 */	"FETCH_DIM_IS",
+/* 91 */	"FETCH_OBJ_IS",
+/* 92 */	"FETCH_FUNC_ARG",
+/* 93 */	"FETCH_DIM_FUNC_ARG",
+/* 94 */	"FETCH_OBJ_FUNC_ARG",
+/* 95 */	"FETCH_UNSET",
+/* 96 */	"FETCH_DIM_UNSET",
+/* 97 */	"FETCH_OBJ_UNSET",
+/* 98 */	"FETCH_DIM_TMP_VAR",
+/* 99 */	"FETCH_CONSTANT",
+/* 100 */	"DECLARE_FUNCTION_OR_CLASS",
+/* 101 */	"EXT_STMT",
+/* 102 */	"EXT_FCALL_BEGIN",
+/* 103 */	"EXT_FCALL_END",
+/* 104 */	"EXT_NOP",
+/* 105 */	"TICKS",
+/* 106 */	"SEND_VAR_NO_REF",
+/* 107 */	"UNDEF",
+/* 108 */	"UNDEF",
+/* 109 */	"UNDEF",
+/* 110 */	"DO_FCALL_BY_FUNC",
+/* 111 */	"INIT_FCALL_BY_FUNC",
+/* 112 */	"UNDEF"
+};
Index: /tags/1.3.0-rc1/align.h
===================================================================
--- /tags/1.3.0-rc1/align.h	(revision 394)
+++ /tags/1.3.0-rc1/align.h	(revision 394)
@@ -0,0 +1,19 @@
+#ifndef __ALIGN_H
+#define __ALIGN_H
+#ifndef ALIGN
+typedef union align_union {
+	double d;
+	void *v;
+	int (*func)(int);
+	long l;
+} align_union;
+
+#if (defined (__GNUC__) && __GNUC__ >= 2)
+#define XCACHE_PLATFORM_ALIGNMENT (__alignof__ (align_union))
+#else
+#define XCACHE_PLATFORM_ALIGNMENT (sizeof(align_union))
+#endif
+
+#define ALIGN(n) ((((size_t)(n)-1) & ~(XCACHE_PLATFORM_ALIGNMENT-1)) + XCACHE_PLATFORM_ALIGNMENT)
+#endif
+#endif /* __ALIGN_H */
Index: /tags/1.3.0-rc1/const_string_opcodes_php6.x.h
===================================================================
--- /tags/1.3.0-rc1/const_string_opcodes_php6.x.h	(revision 626)
+++ /tags/1.3.0-rc1/const_string_opcodes_php6.x.h	(revision 626)
@@ -0,0 +1,157 @@
+/* size = 154 */
+static const char *const xc_opcode_names[] = {
+/* 0 */	"NOP",
+/* 1 */	"ADD",
+/* 2 */	"SUB",
+/* 3 */	"MUL",
+/* 4 */	"DIV",
+/* 5 */	"MOD",
+/* 6 */	"SL",
+/* 7 */	"SR",
+/* 8 */	"CONCAT",
+/* 9 */	"BW_OR",
+/* 10 */	"BW_AND",
+/* 11 */	"BW_XOR",
+/* 12 */	"BW_NOT",
+/* 13 */	"BOOL_NOT",
+/* 14 */	"BOOL_XOR",
+/* 15 */	"IS_IDENTICAL",
+/* 16 */	"IS_NOT_IDENTICAL",
+/* 17 */	"IS_EQUAL",
+/* 18 */	"IS_NOT_EQUAL",
+/* 19 */	"IS_SMALLER",
+/* 20 */	"IS_SMALLER_OR_EQUAL",
+/* 21 */	"CAST",
+/* 22 */	"QM_ASSIGN",
+/* 23 */	"ASSIGN_ADD",
+/* 24 */	"ASSIGN_SUB",
+/* 25 */	"ASSIGN_MUL",
+/* 26 */	"ASSIGN_DIV",
+/* 27 */	"ASSIGN_MOD",
+/* 28 */	"ASSIGN_SL",
+/* 29 */	"ASSIGN_SR",
+/* 30 */	"ASSIGN_CONCAT",
+/* 31 */	"ASSIGN_BW_OR",
+/* 32 */	"ASSIGN_BW_AND",
+/* 33 */	"ASSIGN_BW_XOR",
+/* 34 */	"PRE_INC",
+/* 35 */	"PRE_DEC",
+/* 36 */	"POST_INC",
+/* 37 */	"POST_DEC",
+/* 38 */	"ASSIGN",
+/* 39 */	"ASSIGN_REF",
+/* 40 */	"ECHO",
+/* 41 */	"PRINT",
+/* 42 */	"JMP",
+/* 43 */	"JMPZ",
+/* 44 */	"JMPNZ",
+/* 45 */	"JMPZNZ",
+/* 46 */	"JMPZ_EX",
+/* 47 */	"JMPNZ_EX",
+/* 48 */	"CASE",
+/* 49 */	"SWITCH_FREE",
+/* 50 */	"BRK",
+/* 51 */	"CONT",
+/* 52 */	"BOOL",
+/* 53 */	"INIT_STRING",
+/* 54 */	"ADD_CHAR",
+/* 55 */	"ADD_STRING",
+/* 56 */	"ADD_VAR",
+/* 57 */	"BEGIN_SILENCE",
+/* 58 */	"END_SILENCE",
+/* 59 */	"INIT_FCALL_BY_NAME",
+/* 60 */	"DO_FCALL",
+/* 61 */	"DO_FCALL_BY_NAME",
+/* 62 */	"RETURN",
+/* 63 */	"RECV",
+/* 64 */	"RECV_INIT",
+/* 65 */	"SEND_VAL",
+/* 66 */	"SEND_VAR",
+/* 67 */	"SEND_REF",
+/* 68 */	"NEW",
+/* 69 */	"INIT_NS_FCALL_BY_NAME",
+/* 70 */	"FREE",
+/* 71 */	"INIT_ARRAY",
+/* 72 */	"ADD_ARRAY_ELEMENT",
+/* 73 */	"INCLUDE_OR_EVAL",
+/* 74 */	"UNSET_VAR",
+/* 75 */	"UNSET_DIM",
+/* 76 */	"UNSET_OBJ",
+/* 77 */	"FE_RESET",
+/* 78 */	"FE_FETCH",
+/* 79 */	"EXIT",
+/* 80 */	"FETCH_R",
+/* 81 */	"FETCH_DIM_R",
+/* 82 */	"FETCH_OBJ_R",
+/* 83 */	"FETCH_W",
+/* 84 */	"FETCH_DIM_W",
+/* 85 */	"FETCH_OBJ_W",
+/* 86 */	"FETCH_RW",
+/* 87 */	"FETCH_DIM_RW",
+/* 88 */	"FETCH_OBJ_RW",
+/* 89 */	"FETCH_IS",
+/* 90 */	"FETCH_DIM_IS",
+/* 91 */	"FETCH_OBJ_IS",
+/* 92 */	"FETCH_FUNC_ARG",
+/* 93 */	"FETCH_DIM_FUNC_ARG",
+/* 94 */	"FETCH_OBJ_FUNC_ARG",
+/* 95 */	"FETCH_UNSET",
+/* 96 */	"FETCH_DIM_UNSET",
+/* 97 */	"FETCH_OBJ_UNSET",
+/* 98 */	"FETCH_DIM_TMP_VAR",
+/* 99 */	"FETCH_CONSTANT",
+/* 100 */	"GOTO",
+/* 101 */	"EXT_STMT",
+/* 102 */	"EXT_FCALL_BEGIN",
+/* 103 */	"EXT_FCALL_END",
+/* 104 */	"EXT_NOP",
+/* 105 */	"TICKS",
+/* 106 */	"SEND_VAR_NO_REF",
+/* 107 */	"CATCH",
+/* 108 */	"THROW",
+/* 109 */	"FETCH_CLASS",
+/* 110 */	"CLONE",
+/* 111 */	"UNDEF",
+/* 112 */	"INIT_METHOD_CALL",
+/* 113 */	"INIT_STATIC_METHOD_CALL",
+/* 114 */	"ISSET_ISEMPTY_VAR",
+/* 115 */	"ISSET_ISEMPTY_DIM_OBJ",
+/* 116 */	"UNDEF",
+/* 117 */	"UNDEF",
+/* 118 */	"UNDEF",
+/* 119 */	"UNDEF",
+/* 120 */	"UNDEF",
+/* 121 */	"UNDEF",
+/* 122 */	"UNDEF",
+/* 123 */	"UNDEF",
+/* 124 */	"UNDEF",
+/* 125 */	"UNDEF",
+/* 126 */	"UNDEF",
+/* 127 */	"UNDEF",
+/* 128 */	"UNDEF",
+/* 129 */	"UNDEF",
+/* 130 */	"UNDEF",
+/* 131 */	"UNDEF",
+/* 132 */	"PRE_INC_OBJ",
+/* 133 */	"PRE_DEC_OBJ",
+/* 134 */	"POST_INC_OBJ",
+/* 135 */	"POST_DEC_OBJ",
+/* 136 */	"ASSIGN_OBJ",
+/* 137 */	"OP_DATA",
+/* 138 */	"INSTANCEOF",
+/* 139 */	"DECLARE_CLASS",
+/* 140 */	"DECLARE_INHERITED_CLASS",
+/* 141 */	"DECLARE_FUNCTION",
+/* 142 */	"RAISE_ABSTRACT_ERROR",
+/* 143 */	"DECLARE_CONST",
+/* 144 */	"ADD_INTERFACE",
+/* 145 */	"DECLARE_INHERITED_CLASS_DELAYED",
+/* 146 */	"VERIFY_ABSTRACT_CLASS",
+/* 147 */	"ASSIGN_DIM",
+/* 148 */	"ISSET_ISEMPTY_PROP_OBJ",
+/* 149 */	"HANDLE_EXCEPTION",
+/* 150 */	"USER_OPCODE",
+/* 151 */	"U_NORMALIZE",
+/* 152 */	"JMP_SET",
+/* 153 */	"DECLARE_LAMBDA_FUNCTION"
+};
