首页 > 代码库 > php 5.5 parsekit 扩展问题

php 5.5 parsekit 扩展问题

背景:

    几天前 在项目框架中 实现一个 类和方法的扫描器,配合 语言包 来实现一个动态的 后台菜单。发现php 的一个扩展parsekit 搭配目录的迭代器可以实现此功能。

    环境:php 5.3  apache 2.2 ubunut 12.04

悲剧的是在早上来上班的时候,开机发现系统更新 ubunut 14.,手贱点了更新

结果 更新后 首先旧的显卡驱动不支持,导致无法正常启动桌面。然后apache 更新到 2.4, 旧的 配置文件 中 默认 Allow from all  语法需要改为  Require all granted,否则 报错 403。最纠结的事情是 php 由5.3 变为 5.5 扩展不能正常使用。

更悲剧的事情是 这个扩展就是不支持 》 5.3 的版本的php

所以无论是编译安装还是 pecl 都装不上,编译会报错

下面说正题

解决办法如下:

    1.下载 扩展源码包

用下面的代码 替换 parsekit.c

/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2006 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.0 of the PHP license,       |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_0.txt.                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author: Sara Golemon <pollita@php.net>                               |
  +----------------------------------------------------------------------+
*/

/* $Id: parsekit.c 274237 2009-01-22 16:21:11Z sebastian $ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_parsekit.h"
#include "php3_compat.h"
#ifndef Z_REFCOUNT_P
#define Z_REFCOUNT_P(pz)              (pz)->refcount
#endif

#ifndef Z_SET_REFCOUNT_P
#define Z_SET_REFCOUNT_P(pz, rc)      (pz)->refcount = rc
#endif

ZEND_DECLARE_MODULE_GLOBALS(parsekit)
/* Potentially thread-unsafe, see MINIT_FUNCTION */
void (*php_parsekit_original_error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);

/* Parsekit Workhorse */

/* {{{ php_parsekit_define_name */
static char* php_parsekit_define_name_ex(long val, php_parsekit_define_list *lookup_list, long *pflags, char *unknown_default)
{
	php_parsekit_define_list *names;

	for(names = lookup_list; names->str; names++) {
		if (names->val == val) {
			if (pflags) {
				*pflags = names->flags;
			}
			return names->str;
		}
	}

	return unknown_default ? unknown_default : PHP_PARSEKIT_UNKNOWN;
}

#define php_parsekit_define_name(val, lookup_list, unknown_default)			php_parsekit_define_name_ex((val), (lookup_list), NULL, (unknown_default))
/* }}} */

/* {{{ php_parsekit_parse_node */
static void php_parsekit_parse_node(zval *return_value, zend_op_array *op_array, znode *node, long flags, long options TSRMLS_DC)
{
	array_init(return_value);
	add_assoc_long(return_value, "type", node->op_type);
	add_assoc_string(return_value, "type_name", php_parsekit_define_name(node->op_type, php_parsekit_nodetype_names, PHP_PARSEKIT_NODETYPE_UNKNOWN), 1);
	if (node->op_type == IS_CONST) {
		zval *tmpzval;
		MAKE_STD_ZVAL(tmpzval);
		*tmpzval = node->u.constant;
		zval_copy_ctor(tmpzval);
		Z_SET_REFCOUNT_P(tmpzval, 1);
		add_assoc_zval(return_value, "constant", tmpzval);
#ifdef IS_CV
/* PHP >= 5.1 */
	} else if (node->op_type == IS_CV) {
		add_assoc_long(return_value, "var", node->u.op.var);
		add_assoc_stringl(return_value, "varname", op_array->vars[node->u.op.var].name, op_array->vars[node->u.op.var].name_len, 1);
#endif
	} else {
		/* IS_VAR || IS_TMP_VAR || IS_UNUSED */
		char sop[(sizeof(void *) * 2) + 1];

		snprintf(sop, (sizeof(void *) * 2) + 1, "%X", (unsigned int)node->u.op.var); 

		if ((flags & PHP_PARSEKIT_VAR) ||
			(options & PHP_PARSEKIT_ALL_ELEMENTS)) {
			add_assoc_long(return_value, "var", node->u.op.var / sizeof(temp_variable));
		} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
			add_assoc_null(return_value, "var");
		}

		if ((flags & PHP_PARSEKIT_OPLINE) ||
			(options & PHP_PARSEKIT_ALL_ELEMENTS)) {
			add_assoc_string(return_value, "opline_num", sop, 1);
		} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
			add_assoc_null(return_value, "opline_num");
		}

		if ((flags & PHP_PARSEKIT_OPARRAY) ||
			(options & PHP_PARSEKIT_ALL_ELEMENTS)) {
			add_assoc_string(return_value, "op_array", sop, 1);
		} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
			add_assoc_null(return_value, "op_array");
		}

#ifdef ZEND_ENGINE_2
/* ZE2 Only */
		if ((flags & PHP_PARSEKIT_JMP_ADDR) ||
			(options & PHP_PARSEKIT_ALL_ELEMENTS)) {
			add_assoc_string(return_value, "jmp_addr", sop, 1);
			snprintf(sop, sizeof(sop)-1, "%u",
					((unsigned int)((char*)node->u.op.var - (char*)op_array->opcodes))/sizeof(zend_op));
			add_assoc_string(return_value, "jmp_offset", sop, 1); 
		} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
			add_assoc_null(return_value, "jmp_addr");
		}
#endif

		if ((flags & PHP_PARSEKIT_EA_TYPE) ||
			(options & PHP_PARSEKIT_ALL_ELEMENTS)) {
			add_assoc_long(return_value, "EA.type", 1);
		} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
			add_assoc_null(return_value, "EA.type");
		}
	}
}
/* }}} */

/* {{{ php_parsekit_parse_op */
static void php_parsekit_parse_op(zval *return_value, zend_op_array *op_array, zend_op *op, long options TSRMLS_DC)
{
	zval *result, *op1, *op2;
	long flags = 0;

	array_init(return_value);

	/* op->handler */
	add_assoc_long(return_value, "address", (unsigned int)(&(op->opcode)));
	add_assoc_long(return_value, "opcode", op->opcode);
	add_assoc_string(return_value, "opcode_name", php_parsekit_define_name_ex(op->opcode, php_parsekit_opcode_names, &flags, PHP_PARSEKIT_OPCODE_UNKNOWN) , 1);
	add_assoc_long(return_value, "flags", flags);

	/* args: result, op1, op2 */
	if ((options & PHP_PARSEKIT_ALL_ELEMENTS) ||
		(flags & PHP_PARSEKIT_RESULT_USED)) {
		MAKE_STD_ZVAL(result);
		php_parsekit_parse_node(result, op_array, &(op->result), flags & PHP_PARSEKIT_RESULT_USED, options TSRMLS_CC);
		add_assoc_zval(return_value, "result", result);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "result");
	}

	if ((options & PHP_PARSEKIT_ALL_ELEMENTS) ||
		(flags & PHP_PARSEKIT_OP1_USED)) {
		MAKE_STD_ZVAL(op1);
		php_parsekit_parse_node(op1, op_array, &(op->op1), flags & PHP_PARSEKIT_OP1_USED, options TSRMLS_CC);
		add_assoc_zval(return_value, "op1", op1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "op1");
	}

	if ((options & PHP_PARSEKIT_ALL_ELEMENTS) ||
		(flags & PHP_PARSEKIT_OP2_USED)) {
		MAKE_STD_ZVAL(op2);
		php_parsekit_parse_node(op2, op_array, &(op->op2), flags & PHP_PARSEKIT_OP2_USED, options TSRMLS_CC);
		add_assoc_zval(return_value, "op2", op2);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "op2");
	}

	if ((options & PHP_PARSEKIT_ALL_ELEMENTS) ||
		(flags & PHP_PARSEKIT_EXTENDED_VALUE)) {
		add_assoc_long(return_value, "extended_value", op->extended_value);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "extended_value");
	}

	add_assoc_long(return_value, "lineno", op->lineno);
}
/* }}} */

#ifdef ZEND_ENGINE_2
/* {{{ php_parsekit_parse_arginfo */
static void php_parsekit_parse_arginfo(zval *return_value, zend_uint num_args, zend_arg_info *arginfo, long options TSRMLS_DC)
{
	zend_uint i;

	array_init(return_value);

	for(i = 0; i < num_args; i++) {
		zval *tmpzval;

		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		add_assoc_stringl(tmpzval, "name", arginfo[i].name, arginfo[i].name_len, 1);
		if (arginfo[i].class_name_len) {
			add_assoc_stringl(tmpzval, "class_name", arginfo[i].class_name, arginfo[i].class_name_len, 1);
		} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
			add_assoc_null(tmpzval, "class_name");
		}
		add_assoc_bool(tmpzval, "allow_null", arginfo[i].allow_null);
		add_assoc_bool(tmpzval, "pass_by_reference", arginfo[i].pass_by_reference);

		add_next_index_zval(return_value, tmpzval);
	}	
}
/* }}} */
#else
/* {{{ php_parsekit_derive_arginfo 
	ZE1 Func Arg loading is done via opcodes "RECV"ing from the caller */
static void php_parsekit_derive_arginfo(zval *return_value, zend_op_array *op_array, long options TSRMLS_DC)
{
	int i;
	zend_op *opcodes = op_array->opcodes;

	array_init(return_value);

	/* Received vars come in pairs:
		A ZEND_FETCH_W, and a ZEND_RECV */
	for(i = 0; i < op_array->arg_types[0]; i++) {
		if (opcodes[i*2].opcode   == ZEND_FETCH_W &&
			opcodes[i*2].op1.op_type == IS_CONST &&
			opcodes[i*2].op1.u.constant.type == IS_STRING &&
			(opcodes[(i*2)+1].opcode == ZEND_RECV || opcodes[(i*2)+1].opcode == ZEND_RECV_INIT)) {
			zval *tmpzval;

			MAKE_STD_ZVAL(tmpzval);
			array_init(tmpzval);

			add_assoc_stringl(tmpzval, "name", opcodes[i*2].op1.u.constant.value.str.val, opcodes[i*2].op1.u.constant.value.str.len, 1);
			add_assoc_bool(tmpzval, "pass_by_reference", op_array->arg_types[i+1]);
			if (opcodes[(i*2)+1].opcode == ZEND_RECV_INIT &&
				opcodes[(i*2)+1].op2.op_type == IS_CONST) {
				zval *def;
	
				MAKE_STD_ZVAL(def);
				*def = opcodes[(i*2)+1].op2.u.constant;
				zval_copy_ctor(def);
				add_assoc_zval(tmpzval, "default", def);
				Z_SET_REFCOUNT_P(tmpzval, 1);
			}

			add_next_index_zval(return_value, tmpzval);
		}
	}
}
/* }}} */
#endif

/* {{{ php_parsekit_parse_op_array */
static void php_parsekit_parse_op_array(zval *return_value, zend_op_array *ops, long options TSRMLS_DC)
{
	zend_op *op;
	zval *tmpzval;
	int i = 0;

	/* TODO: Reorder / Organize */

	array_init(return_value);

	add_assoc_long(return_value, "type", (long)(ops->type));
	add_assoc_string(return_value, "type_name", php_parsekit_define_name(ops->type, php_parsekit_function_types, PHP_PARSEKIT_FUNCTYPE_UNKNOWN), 1);
	if (ops->function_name) {
		add_assoc_string(return_value, "function_name", ops->function_name, 1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "function_name");
	}

#ifdef ZEND_ENGINE_2
/* ZE2 op_array members */
	if (ops->scope && ops->scope->name) {
		add_assoc_stringl(return_value, "scope", ops->scope->name, ops->scope->name_length, 1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "scope");
	}
	add_assoc_long(return_value, "fn_flags", ops->fn_flags);
	if (ops->function_name && ops->prototype) {
		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		add_assoc_long(tmpzval, "type", ops->prototype->type);
		add_assoc_string(return_value, "type_name", php_parsekit_define_name(ops->prototype->type, php_parsekit_function_types, PHP_PARSEKIT_FUNCTYPE_UNKNOWN), 1);
		if (ops->prototype->common.function_name) {
			add_assoc_string(tmpzval, "function_name", ops->prototype->common.function_name, 1);
		} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
			add_assoc_null(tmpzval, "function_name");
		}
		if (ops->prototype->common.scope && ops->prototype->common.scope->name) {
			add_assoc_stringl(tmpzval, "scope", ops->prototype->common.scope->name, ops->prototype->common.scope->name_length, 1);
		} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
			add_assoc_null(tmpzval, "scope");
		}
		add_assoc_zval(return_value, "prototype", tmpzval);		
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "prototype");
	}
	add_assoc_long(return_value, "num_args", ops->num_args);
	add_assoc_long(return_value, "required_num_args", ops->required_num_args);
	//add_assoc_bool(return_value, "pass_rest_by_reference", ops->pass_rest_by_reference);

	if (ops->num_args && ops->arg_info) {
		MAKE_STD_ZVAL(tmpzval);
		php_parsekit_parse_arginfo(tmpzval, ops->num_args, ops->arg_info, options TSRMLS_CC);
		add_assoc_zval(return_value, "arg_info", tmpzval);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "arg_info");
	}

	if (ops->last_try_catch > 0) {
		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		for(i = 0; i < ops->last_try_catch; i++) {
			zval *tmp_zval;

			MAKE_STD_ZVAL(tmp_zval);
			array_init(tmp_zval);
			add_assoc_long(tmp_zval, "try_op", ops->try_catch_array[i].try_op);
			add_assoc_long(tmp_zval, "catch_op", ops->try_catch_array[i].catch_op);
			add_index_zval(tmpzval, i, tmp_zval);
		}
		add_assoc_zval(return_value, "try_catch_array", tmpzval);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "try_catch_array");
	}

#ifndef ZEND_ACC_CLOSURE
/* PHP<5.3 */
	add_assoc_bool(return_value, "uses_this", ops->uses_this);
#endif
	add_assoc_long(return_value, "line_start", ops->line_start);
	add_assoc_long(return_value, "line_end", ops->line_end);

	if (ops->doc_comment && ops->doc_comment_len) {
		add_assoc_stringl(return_value, "doc_comment", ops->doc_comment, ops->doc_comment_len, 1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "doc_comment");
	}

#else
/* ZE1 op_array members */

	if (ops->arg_types) {
		zend_uchar *arg_types = ops->arg_types;
		int numargs = *(ops->arg_types);

		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		add_assoc_long(tmpzval, "arg_count", numargs);

		for(i = 0; i < numargs; i++) {
			add_next_index_long(tmpzval, arg_types[i+1]);
		}

		add_assoc_zval(return_value, "arg_types", tmpzval);

		/* Emulated arg_info */
		MAKE_STD_ZVAL(tmpzval);
		php_parsekit_derive_arginfo(tmpzval, ops, options TSRMLS_CC);
		add_assoc_zval(return_value, "arg_info", tmpzval);
	} else {
		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		add_assoc_long(tmpzval, "arg_count", 0);

		add_assoc_zval(return_value, "arg_types", tmpzval);
		add_assoc_null(return_value, "arg_info");
	}

	add_assoc_bool(return_value, "uses_global", ops->uses_globals);
#endif
/* ZE1 and ZE2 */

	//add_assoc_bool(return_value, "return_reference", ops->return_reference);
	add_assoc_long(return_value, "refcount", *(ops->refcount));
	add_assoc_long(return_value, "last", ops->last);
	//add_assoc_long(return_value, "size", ops->size);
	add_assoc_long(return_value, "T", ops->T);
	add_assoc_long(return_value, "last_brk_cont", ops->last_brk_cont);
	//add_assoc_long(return_value, "current_brk_cont", ops->current_brk_cont);
	//add_assoc_long(return_value, "backpatch_count", ops->backpatch_count);
	//add_assoc_bool(return_value, "done_pass_two", ops->done_pass_two);

	if (ops->last_brk_cont > 0) {
		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		for(i = 0; i < ops->last_brk_cont; i++) {
			zval *tmp_zval;

			MAKE_STD_ZVAL(tmp_zval);
			array_init(tmp_zval);
			add_assoc_long(tmp_zval, "cont", ops->brk_cont_array[i].cont);
			add_assoc_long(tmp_zval, "brk", ops->brk_cont_array[i].brk);
			add_assoc_long(tmp_zval, "parent", ops->brk_cont_array[i].parent);
			add_index_zval(tmpzval, i, tmp_zval);
		}
		add_assoc_zval(return_value, "brk_cont_array", tmpzval);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "brk_cont_array");
	}

	if (ops->static_variables) {
		zval *tmp_zval;

		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		zend_hash_copy(HASH_OF(tmpzval), ops->static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
		add_assoc_zval(return_value, "static_variables", tmpzval);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "static_variables");
	}

	/*if (ops->start_op) {
		char sop[(sizeof(void *) * 2) + 1];

		snprintf(sop, sizeof(sop), "%X", (unsigned int)ops->start_op); 
		add_assoc_string(return_value, "start_op", sop, 1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "start_op");
	}*/

	if (ops->filename) {
		add_assoc_string(return_value, "filename", ops->filename, 1);
	} else {
		add_assoc_null(return_value, "filename");
	}

	/* Leave this last, it simplifies readability */
	MAKE_STD_ZVAL(tmpzval);
	array_init(tmpzval);
	/*for(op = ops->opcodes, i = 0; op && i < ops->size; op++, i++) {
		zval *zop;

		MAKE_STD_ZVAL(zop);
		php_parsekit_parse_op(zop, ops, op, options TSRMLS_CC);
		add_next_index_zval(tmpzval, zop);
	}	
	add_assoc_zval(return_value, "opcodes", tmpzval);
*/

}
/* }}} */

/* {{{ php_parsekit_parse_node_simple */
static int php_parsekit_parse_node_simple(char **pret, zend_op_array *op_array, znode *node, zend_op_array *oparray TSRMLS_DC)
{
	if (node->op_type == IS_UNUSED) {
		if (node->u.op.var) {
#ifdef ZEND_ENGINE_2
			/*if (node->u.op.jmp_addr >= oparray->opcodes &&
				node->u.op.jmp_addr <= (oparray->opcodes + (sizeof(zend_op) * oparray->size))) 
			{
				spprintf(pret, 0, "#%d", node->u.jmp_addr - oparray->opcodes);
			} 
			else*/
#endif
			{
				spprintf(pret, 0, "0x%X", node->u.op.var);
			}
			return 1;
		} else {
			*pret =  "UNUSED";
			return 0;
		}
	}
	if (node->op_type == IS_CONST) {
		switch (node->u.constant.type) {
			case IS_NULL:
				*pret = "NULL";
				return 0;
				break;
			case IS_BOOL:
				if (node->u.constant.value.lval) {
					*pret = "TRUE";
				} else {
					*pret = "FALSE";
				}
				return 0;
				break;
			case IS_LONG:
				spprintf(pret, 0, "%ld", node->u.constant.value.lval);
				return 1;
				break;
			case IS_DOUBLE:
				spprintf(pret, 0, "%f", node->u.constant.value.dval);
				return 1;
				break;
			case IS_STRING:
				if (node->u.constant.value.str.len > 15) {
					spprintf(pret, 0, "‘%12s...‘", node->u.constant.value.str.val);
				} else {
					spprintf(pret, 0, "‘%s‘", node->u.constant.value.str.val);
				}
				return 1;
				break;
			/* Should these ever occur? */
			case IS_RESOURCE:
				spprintf(pret, 0, "Resource ID#%ld", node->u.constant.value.lval);
				return 1;
				break;
			case IS_ARRAY:
				*pret = "Array";
				return 0;
				break;
			case IS_OBJECT:
				*pret = "Object";
				return 0;
				break;
			default:
				*pret = "Unknown";
				return 0;
		}
	}

	spprintf(pret, 0, "T(%d)", node->u.op.var / sizeof(temp_variable));
	return 1;
}
/* }}} */

/* {{{ php_parsekit_parse_op_array_simple */
static void php_parsekit_parse_op_array_simple(zval *return_value, zend_op_array *ops, long options TSRMLS_DC)
{
	zend_op *op;
	int i;
	long flags;

	array_init(return_value);

	for (op = ops->opcodes, i = 0; op && i < 32; op++, i++) {
		char *opline, *result, *op1, *op2;
		int opline_len, freeit = 0;

		if (php_parsekit_parse_node_simple(&result, ops, &(op->result), ops TSRMLS_CC)) {
			freeit |= 1;
		}
		if (php_parsekit_parse_node_simple(&op1, ops, &(op->op1), ops TSRMLS_CC)) {
			freeit |= 2;
		}
		if (php_parsekit_parse_node_simple(&op2, ops, &(op->op2), ops TSRMLS_CC)) {
			freeit |= 4;
		}

		opline_len = spprintf(&opline, 0, "%s %s %s %s", 
			php_parsekit_define_name_ex(op->opcode, php_parsekit_opcode_names, &flags, PHP_PARSEKIT_OPCODE_UNKNOWN),
			result, op1, op2);

		if (freeit & 1) efree(result);
		if (freeit & 2) efree(op1);
		if (freeit & 4) efree(op2);

		add_next_index_stringl(return_value, opline, opline_len, 0);
	}
}
/* }}} */

/* {{{ php_parsekit_pop_functions */
static int php_parsekit_pop_functions(zval *return_value, HashTable *function_table, int target_count, long options TSRMLS_DC)
{
	HashPosition pos;

	array_init(return_value);

	zend_hash_internal_pointer_end_ex(function_table, &pos);
	while (target_count < zend_hash_num_elements(function_table)) {
		long func_index;
		unsigned int func_name_len;
		char *func_name;
		zend_function *function;
		zval *function_ops;

		if (zend_hash_get_current_data_ex(function_table, (void **)&function, &pos) == FAILURE) {
			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from function table: Illegal function entry found.");
			return FAILURE;
		}
		if (function->type == ZEND_INTERNAL_FUNCTION) {
			/* Inherited internal method */
			zend_hash_move_backwards_ex(function_table, &pos);
			target_count++;
			continue;
		} else if (function->type != ZEND_USER_FUNCTION) {
			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from function table: %s%s%s - "
							"Found %s where ZEND_USER_FUNCTION was expected.",
							function->common.scope ? function->common.scope->name : "",
							function->common.scope ? "::" : "",
							function->common.function_name,
							php_parsekit_define_name(function->type, php_parsekit_function_types, PHP_PARSEKIT_FUNCTYPE_UNKNOWN));
			return FAILURE;
		}
		MAKE_STD_ZVAL(function_ops);
		if (options == PHP_PARSEKIT_SIMPLE) {
			php_parsekit_parse_op_array_simple(function_ops, &(function->op_array), options TSRMLS_CC);
		} else {
			php_parsekit_parse_op_array(function_ops, &(function->op_array), options TSRMLS_CC);
		}
		add_assoc_zval(return_value, function->common.function_name, function_ops);

		if (zend_hash_get_current_key_ex(function_table, &func_name, &func_name_len, &func_index, 0, &pos) == HASH_KEY_IS_STRING) {
			zend_hash_move_backwards_ex(function_table, &pos);

			/* TODO: dispose of the function properly */
			if (zend_hash_del(function_table, func_name, func_name_len) == FAILURE) {
				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from function table: Unknown hash_del failure.");
				return FAILURE;
			}
		} else {
			/* Absolutely no reason this should ever occur */
			zend_hash_move_backwards_ex(function_table, &pos);
			zend_hash_index_del(function_table, func_index);
		}
	}

	return SUCCESS;
}
/* }}} */

/* {{{ php_parsekit_parse_class_entry */
static int php_parsekit_parse_class_entry(zval *return_value, zend_class_entry *ce, long options TSRMLS_DC)
{
	zval *tmpzval;
#ifdef ZEND_ENGINE_2
	int i;
#endif

	array_init(return_value);

	add_assoc_long(return_value, "type", ce->type);
	add_assoc_string(return_value, "type_name", php_parsekit_define_name(ce->type, php_parsekit_class_types, PHP_PARSEKIT_CLASSTYPE_UNKNOWN), 1);
	add_assoc_stringl(return_value, "name", ce->name, ce->name_length, 1);
	if (ce->parent) {
		add_assoc_stringl(return_value, "parent", ce->parent->name, ce->parent->name_length, 1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "parent");
	}
	//add_assoc_bool(return_value, "constants_updated", ce->constants_updated);
#ifdef ZEND_ENGINE_2
/* ZE2 class_entry members */
	add_assoc_long(return_value, "ce_flags", ce->ce_flags);

	/* function table pop destorys entries! */
	if (ce->constructor) {
		add_assoc_string(return_value, "constructor", ce->constructor->common.function_name, 1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "constructor");
	}

	if (ce->clone) {
		add_assoc_string(return_value, "clone", ce->clone->common.function_name, 1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "clone");
	}

	if (ce->__get) {
		add_assoc_string(return_value, "__get", ce->__get->common.function_name, 1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "__get");
	}

	if (ce->__set) {
		add_assoc_string(return_value, "__set", ce->__set->common.function_name, 1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "__set");
	}

	if (ce->__call) {
		add_assoc_string(return_value, "__call", ce->__call->common.function_name, 1);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "__call");
	}

	if (zend_hash_num_elements(&(ce->properties_info)) > 0) {
		zend_property_info *property_info;

		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		for(zend_hash_internal_pointer_reset(&(ce->properties_info));
			zend_hash_get_current_data(&(ce->properties_info), (void **)&property_info) == SUCCESS;
			zend_hash_move_forward(&(ce->properties_info))) {
			zval *tmp_zval;

			MAKE_STD_ZVAL(tmp_zval);
			array_init(tmp_zval);
			add_assoc_long(tmp_zval, "flags", property_info->flags);
			add_assoc_stringl(tmp_zval, "name", property_info->name, property_info->name_length, 1);
			add_assoc_long(tmp_zval, "h", property_info->h);
			add_next_index_zval(tmpzval, tmp_zval);
		}
		add_assoc_zval(return_value, "properties_info", tmpzval);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "properties_info");
	}
	
	/*if (ce->static_members && zend_hash_num_elements(ce->static_members) > 0) {
		zval *tmp_zval;

		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		zend_hash_copy(HASH_OF(tmpzval), ce->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));	
		add_assoc_zval(return_value, "static_members", tmpzval);
	} else*/ if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "static_members");
	}

	if (zend_hash_num_elements(&(ce->constants_table)) > 0) {
		zval *tmp_zval;

		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		zend_hash_copy(HASH_OF(tmpzval), &(ce->constants_table), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));	
		add_assoc_zval(return_value, "constants_table", tmpzval);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "constants_table");
	}

	if (ce->num_interfaces > 0) {
		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		for(i = 0; i < ce->num_interfaces; i++) {
			add_next_index_stringl(tmpzval, ce->interfaces[i]->name, ce->interfaces[i]->name_length, 1);
		}
		add_assoc_zval(return_value, "interfaces", tmpzval);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "interfaces");
	}

	//add_assoc_string(return_value, "filename", ce->filename, 1);
	//add_assoc_long(return_value, "line_start", ce->line_start);
	//add_assoc_long(return_value, "line_end", ce->line_end);
	/*if (ce->doc_comment) {
		add_assoc_stringl(return_value, "doc_comment", ce->doc_comment, ce->doc_comment_len, 1);
	} else*/ if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "doc_comment");
	}

	add_assoc_long(return_value, "refcount", Z_REFCOUNT_P(ce));

#else
/* ZE1 class_entry members */
	if (ce->refcount) {
		add_assoc_long(return_value, "refcount", *(ce->refcount));
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "refcount");
	}

#endif
/* ZE1 and ZE2 */

	if (zend_hash_num_elements(&(ce->function_table)) > 0) {
		MAKE_STD_ZVAL(tmpzval);
		if (php_parsekit_pop_functions(tmpzval, &(ce->function_table), 0, options TSRMLS_CC) == FAILURE) {
			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to cleanup class %s: Error scrubbing function_table", ce->name);
			return FAILURE;
		}
		add_assoc_zval(return_value, "function_table", tmpzval);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "function_table");
	}

	/*if (zend_hash_num_elements(&(ce->default_properties)) > 0) {
		zval *tmp_zval;

		MAKE_STD_ZVAL(tmpzval);
		array_init(tmpzval);
		zend_hash_copy(HASH_OF(tmpzval), &(ce->default_properties), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));	
		add_assoc_zval(return_value, "default_properties", tmpzval);
	} else*/ if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "default_properties");
	}

	return SUCCESS;
}
/* }}} */

/* {{{ php_parsekit_pop_classes */
static int php_parsekit_pop_classes(zval *return_value, HashTable *class_table, int target_count, long options TSRMLS_DC)
{
	array_init(return_value);

	while (target_count < zend_hash_num_elements(class_table)) {
		long class_index;
		unsigned int class_name_len;
		char *class_name;
		zend_class_entry *class_entry, **pce;
		zval *class_data;

		zend_hash_internal_pointer_end(class_table);
		if (zend_hash_get_current_data(class_table, (void **)&pce) == FAILURE || !pce || !(*pce)) {
			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from class table: Illegal class entry found.");
			return FAILURE;
		}
#ifdef ZEND_ENGINE_2
		class_entry = *pce;
#else
		class_entry = (zend_class_entry*)pce;
#endif
		if (class_entry->type != ZEND_USER_CLASS) {
			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from class table: %s - "
							"Found %s where ZEND_USER_CLASS was expected.", class_entry->name,
							php_parsekit_define_name(class_entry->type, php_parsekit_class_types, PHP_PARSEKIT_CLASSTYPE_UNKNOWN));
			return FAILURE;
		}
		MAKE_STD_ZVAL(class_data);
		if (php_parsekit_parse_class_entry(class_data, class_entry, options TSRMLS_CC) == FAILURE) {
			return FAILURE; /* Exit gracefully even though the E_ERROR condition will clean up after us */
		}
		add_assoc_zval(return_value, class_entry->name, class_data);

		if (zend_hash_get_current_key_ex(class_table, &class_name, &class_name_len, &class_index, 0, NULL) == HASH_KEY_IS_STRING) {
			/* TODO: dispose of the class properly */
			if (zend_hash_del(class_table, class_name, class_name_len) == FAILURE) {
				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from class table: Unknown hash_del failure.");
				return FAILURE;
			}
		} else {
			/* Absolutely no reason this should ever occur */
			zend_hash_index_del(class_table, class_index);
		}
	}
	return SUCCESS;
}
/* }}} */

/* {{{ php_parsekit_common */
static void php_parsekit_common(zval *return_value, int original_num_functions, int original_num_classes, zend_op_array *ops, long options TSRMLS_DC)
{
	zval *declared_functions, *declared_classes;

	/* main() */
	if (options == PHP_PARSEKIT_SIMPLE) {
		php_parsekit_parse_op_array_simple(return_value, ops, options TSRMLS_CC);
	} else {
		php_parsekit_parse_op_array(return_value, ops, options TSRMLS_CC);
	}

	if (original_num_functions < zend_hash_num_elements(EG(function_table))) {
		/* The compiled code introduced new functions, get them out of there! */
		MAKE_STD_ZVAL(declared_functions);
		php_parsekit_pop_functions(declared_functions, EG(function_table), original_num_functions, options TSRMLS_CC);
		add_assoc_zval(return_value, "function_table", declared_functions);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "function_table");
	}

	if (original_num_classes < zend_hash_num_elements(EG(class_table))) {
		/* The compiled code introduced new classes, get them out of here */
		MAKE_STD_ZVAL(declared_classes);
		php_parsekit_pop_classes(declared_classes, EG(class_table), original_num_classes, options TSRMLS_CC);
		add_assoc_zval(return_value, "class_table", declared_classes);
	} else if (options & PHP_PARSEKIT_ALWAYS_SET) {
		add_assoc_null(return_value, "class_table");
	}
}
/* }}} */

/* ****************************************** */
/* Module Housekeeping and Userland Functions */
/* ****************************************** */

/* {{{ proto array parsekit_compile_string(string phpcode[, array &errors[, int options]])
   Return array of opcodes compiled from phpcode */
PHP_FUNCTION(parsekit_compile_string)
{
	int original_num_functions = zend_hash_num_elements(EG(function_table));
	int original_num_classes = zend_hash_num_elements(EG(class_table));
	zend_uchar original_compiler_options;
	zend_op_array *ops;
	zval *zcode, *zerrors = NULL;
	long options = PHP_PARSEKIT_QUIET;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zl", &zcode, &zerrors, &options) == FAILURE) {
		RETURN_FALSE;
	}

	if (zerrors) {
		zval_dtor(zerrors);
		ZVAL_NULL(zerrors);
		PARSEKIT_G(compile_errors) = zerrors;
	}

	convert_to_string(zcode);
#ifdef ZEND_COMPILE_HANDLE_OP_ARRAY
	original_compiler_options = CG(compiler_options);
	CG(compiler_options) = CG(compiler_options) & ~ZEND_COMPILE_HANDLE_OP_ARRAY;
#else
	original_compiler_options = CG(handle_op_arrays);
	CG(handle_op_arrays) = 0;
#endif
	PARSEKIT_G(in_parsekit_compile) = 1;

	zend_try {
		ops = compile_string(zcode, "Parsekit Compiler" TSRMLS_CC);
	} zend_catch {
		ops = NULL;
	} zend_end_try();

	PARSEKIT_G(in_parsekit_compile) = 0;
	PARSEKIT_G(compile_errors) = NULL;

#ifdef ZEND_COMPILE_HANDLE_OP_ARRAY
	CG(compiler_options) = original_compiler_options;
#else
	CG(handle_op_arrays) = original_compiler_options;
#endif

	if (ops) {
		php_parsekit_common(return_value, original_num_functions, original_num_classes, ops, options TSRMLS_CC);
		destroy_op_array(ops PHP_PARSEKIT_TSRMLS_CC_ZE2ONLY);
		efree(ops);
	} else {
		RETURN_FALSE;
	}
}
/* }}} */

/* {{{ proto array parsekit_compile_file(string filename[, array &errors[, int options]])
   Return array of opcodes compiled from phpfile */
PHP_FUNCTION(parsekit_compile_file)
{
	int original_num_functions = zend_hash_num_elements(EG(function_table));
	int original_num_classes = zend_hash_num_elements(EG(class_table));
	zend_uchar original_compiler_options;
	zend_op_array *ops;
	zval *zfilename, *zerrors = NULL;
	long options = PHP_PARSEKIT_QUIET;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zl", &zfilename, &zerrors, &options) == FAILURE) {
		RETURN_FALSE;
	}

	if (zerrors) {
		zval_dtor(zerrors);
		ZVAL_NULL(zerrors);
		PARSEKIT_G(compile_errors) = zerrors;
	}

	convert_to_string(zfilename);
#ifdef ZEND_COMPILE_HANDLE_OP_ARRAY
	original_compiler_options = CG(compiler_options);
	CG(compiler_options) = CG(compiler_options) & ~ZEND_COMPILE_HANDLE_OP_ARRAY;
#else
	original_compiler_options = CG(handle_op_arrays);
	CG(handle_op_arrays) = 0;
#endif
	PARSEKIT_G(in_parsekit_compile) = 1;

	zend_try {
		ops = compile_filename(ZEND_INCLUDE, zfilename TSRMLS_CC);
	} zend_catch {
		ops = NULL;
	} zend_end_try();

	PARSEKIT_G(in_parsekit_compile) = 0;
	PARSEKIT_G(compile_errors) = NULL;

#ifdef ZEND_COMPILE_HANDLE_OP_ARRAY
	CG(compiler_options) = original_compiler_options;
#else
	CG(handle_op_arrays) = original_compiler_options;
#endif

	if (ops) {
		php_parsekit_common(return_value, original_num_functions, original_num_classes, ops, options TSRMLS_CC);

		destroy_op_array(ops PHP_PARSEKIT_TSRMLS_CC_ZE2ONLY);
		efree(ops);
	} else {
		RETURN_FALSE;
	}
}
/* }}} */

/* {{{ proto long parsekit_opcode_flags(long opcode)
	Return the flags associated with an opcode */
PHP_FUNCTION(parsekit_opcode_flags)
{
	long opcode;
	php_parsekit_define_list *opcodes = php_parsekit_opcode_names;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &opcode) == FAILURE) {
		RETURN_FALSE;
	}

	while (opcodes) {
		if (opcodes->val == opcode) {
			RETURN_LONG(opcodes->flags);
		}
	}

	RETURN_FALSE;
}
/* }}} */

/* {{{ proto string parsekit_opcode_name(long opcode)
	Return the name of a given opcode */
PHP_FUNCTION(parsekit_opcode_name)
{
	long opcode;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &opcode) == FAILURE) {
		RETURN_FALSE;
	}

	RETURN_STRING(php_parsekit_define_name(opcode, php_parsekit_opcode_names, PHP_PARSEKIT_OPCODE_UNKNOWN), 1);
}
/* }}} */

/* {{{ proto array parsekit_func_arginfo(mixed function)
	Return the arg_info data for a given user function/method */
PHP_FUNCTION(parsekit_func_arginfo)
{
	zval *function;
	char *class = NULL, *fname = NULL;
	int class_len = 0, fname_len = 0;
	HashTable *function_table = NULL;
	zend_function *fe = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &function) == FAILURE) {
		RETURN_FALSE;
	}

	switch (Z_TYPE_P(function)) {
		case IS_STRING:
			fname = Z_STRVAL_P(function);
			fname_len = Z_STRLEN_P(function);
			function_table = EG(function_table);
			break;
		case IS_ARRAY:
		{
			zval **classname;
			zval **funcname;

			zend_hash_internal_pointer_reset(HASH_OF(function));

			/* Name that class */
			if (zend_hash_get_current_data(HASH_OF(function), (void **)&classname) == FAILURE) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expecting string or array containing two elements.");
				RETURN_FALSE;
			}
			if (!classname || !*classname || (Z_TYPE_PP(classname) != IS_STRING && Z_TYPE_PP(classname) != IS_OBJECT)) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid class name given");
				RETURN_FALSE;
			}
			if (Z_TYPE_PP(classname) == IS_STRING) {
				class = Z_STRVAL_PP(classname);
				class_len = Z_STRLEN_PP(classname);
			} else {
				class = Z_OBJCE_PP(classname)->name;
				class_len = Z_OBJCE_PP(classname)->name_length;

				/* Save looking it up later! */
				function_table = &(Z_OBJCE_PP(classname)->function_table);
			}

			zend_hash_move_forward(HASH_OF(function));

			/* Name that function */
			if (zend_hash_get_current_data(HASH_OF(function), (void **)&funcname) == FAILURE) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expecting string or array containing two elements.");
				RETURN_FALSE;
			}
			if (!funcname || !*funcname || Z_TYPE_PP(funcname) != IS_STRING) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid method name given");
				RETURN_FALSE;
			}
			fname = Z_STRVAL_PP(funcname);
			fname_len = Z_STRLEN_PP(funcname);

			break;
		}
		default:
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expecting string or array containing two elements.");
			RETURN_FALSE;
	}

	if (class && !function_table) {
		zend_class_entry **pce;
#ifndef ZEND_ENGINE_2
		zend_class_entry *ce;
#endif

		/* Fetch class‘s method table */
#ifdef ZEND_ENGINE_2
		if (zend_lookup_class(class, class_len, &pce TSRMLS_CC) == FAILURE) {
#else
		pce = &ce;
		if (zend_hash_find(EG(class_table), class, class_len + 1, (void**)&ce) == FAILURE) {
#endif
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown class: %s", class);
			RETURN_FALSE;
		}
		if (!pce || !*pce) {
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fetch class entry.");
			RETURN_FALSE;
		}

		function_table = &((*pce)->function_table);
	}

	if (!function_table) {
		/* Should never happen */
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error locating function table");
		RETURN_FALSE;
	}

	if (zend_hash_find(function_table, fname, fname_len + 1, (void **)&fe) == FAILURE) {
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s%s() not found.", class ? class : "", class ? "::" : "", fname);
		RETURN_FALSE;
	}

	if (fe->type != ZEND_USER_FUNCTION) {
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only user defined functions support reflection");
		RETURN_FALSE;
	}

#ifdef ZEND_ENGINE_2
	php_parsekit_parse_arginfo(return_value, fe->common.num_args, fe->common.arg_info, 0 TSRMLS_CC);
#else
	php_parsekit_derive_arginfo(return_value, &fe->op_array, 0 TSRMLS_CC);
#endif
}
/* }}} */

#ifdef ZEND_ENGINE_2
	ZEND_BEGIN_ARG_INFO(php_parsekit_second_arg_force_ref, 0)
		ZEND_ARG_PASS_INFO(0)
		ZEND_ARG_PASS_INFO(1)
	ZEND_END_ARG_INFO()
#else
static unsigned char php_parsekit_second_arg_force_ref[] = { 3, BYREF_NONE, BYREF_FORCE };
#endif

/* {{{ function_entry */
function_entry parsekit_functions[] = {
	PHP_FE(parsekit_compile_string,			php_parsekit_second_arg_force_ref)
	PHP_FE(parsekit_compile_file,			php_parsekit_second_arg_force_ref)
	PHP_FE(parsekit_opcode_flags,			NULL)
	PHP_FE(parsekit_opcode_name,			NULL)
	PHP_FE(parsekit_func_arginfo,			NULL)
	{NULL, NULL, NULL}
};
/* }}} */

/* {{{ parsekit_module_entry
 */
zend_module_entry parsekit_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
	STANDARD_MODULE_HEADER,
#endif
	"parsekit",
	parsekit_functions,
	PHP_MINIT(parsekit),
	PHP_MSHUTDOWN(parsekit),
	NULL, /* RINIT */
	NULL, /* RSHUTDOWN */
	PHP_MINFO(parsekit),
#if ZEND_MODULE_API_NO >= 20010901
	PHP_PARSEKIT_VERSION,
#endif
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_PARSEKIT
ZEND_GET_MODULE(parsekit)
#endif

/* {{{ php_parsekit_error_cb 
	Capture error messages and locations while suppressing otherwise fatal (non-core) errors */
static void php_parsekit_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args)
{
	char *buffer;
	int buffer_len;
	zval *tmpzval;
	TSRMLS_FETCH();

	if (!PARSEKIT_G(in_parsekit_compile) || type == E_CORE_ERROR) {
		/* Some normal (or massively abnormal) event triggered this error. */
		php_parsekit_original_error_function(type, (char *)error_filename, error_lineno, format, args);
		return;
	}

	if (!PARSEKIT_G(compile_errors)) {
		/* All errors ignored */
		return;
	}

	/* If an error gets triggered in here, revert to normal handling to avoid potential loop */
	PARSEKIT_G(in_parsekit_compile) = 0;
	MAKE_STD_ZVAL(tmpzval);
	array_init(tmpzval);
	add_assoc_long(tmpzval, "errno", type);
	add_assoc_string(tmpzval, "filename", (char *)error_filename, 1);
	add_assoc_long(tmpzval, "lineno", error_lineno);
	buffer_len = vspprintf(&buffer, PG(log_errors_max_len), format, args);
	add_assoc_stringl(tmpzval, "errstr", buffer, buffer_len, 1);

	if (Z_TYPE_P(PARSEKIT_G(compile_errors)) == IS_NULL) {
		array_init(PARSEKIT_G(compile_errors));
	}
	add_next_index_zval(PARSEKIT_G(compile_errors), tmpzval);

	/* Restore compiler state */
	PARSEKIT_G(in_parsekit_compile) = 1;
}
/* }}} */

#define REGISTER_PARSEKIT_CONSTANTS(define_list)			{			char const_name[96];			int const_name_len;			php_parsekit_define_list *defines = (define_list);			while (defines->str) {				/* the macros don‘t like variable constant names */ 			const_name_len = snprintf(const_name, sizeof(const_name), "PARSEKIT_%s", defines->str);				zend_register_long_constant(const_name, const_name_len+1, defines->val, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC); 			defines++;			}		}

/* {{{ php_parsekit_init_globals
 */
static void php_parsekit_init_globals(zend_parsekit_globals *parsekit_globals)
{
	parsekit_globals->in_parsekit_compile = 0;
	parsekit_globals->compile_errors = NULL;
}
/* }}} */

/* {{{ PHP_MINIT_FUNCTION
 */
PHP_MINIT_FUNCTION(parsekit)
{
	REGISTER_PARSEKIT_CONSTANTS(php_parsekit_class_types);
	REGISTER_PARSEKIT_CONSTANTS(php_parsekit_function_types);
	REGISTER_PARSEKIT_CONSTANTS(php_parsekit_nodetype_names);
	REGISTER_PARSEKIT_CONSTANTS(php_parsekit_opcode_names);
	REGISTER_PARSEKIT_CONSTANTS(php_parsekit_opnode_flags);

	REGISTER_LONG_CONSTANT("PARSEKIT_QUIET",	PHP_PARSEKIT_QUIET,		CONST_CS | CONST_PERSISTENT );
	REGISTER_LONG_CONSTANT("PARSEKIT_SIMPLE",	PHP_PARSEKIT_SIMPLE,		CONST_CS | CONST_PERSISTENT );

	ZEND_INIT_MODULE_GLOBALS(parsekit, php_parsekit_init_globals, NULL);

	/* Changing zend_error_cb isn‘t threadsafe,
	   so we‘ll have to just change it for everybody
	   and track whether or not we‘re in parsekit_compile()
	   on a perthread basis and go from there.
	   DANGER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	   This could tank if another module does this same hack
	   before us then unloads. */
	php_parsekit_original_error_function = zend_error_cb;
	zend_error_cb = php_parsekit_error_cb;

	return SUCCESS;
}
/* }}} */

	/* {{{ PHP_MSHUTDOWN_FUNCTION
 */
PHP_MSHUTDOWN_FUNCTION(parsekit)
{
	zend_error_cb = php_parsekit_original_error_function;

	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(parsekit)
{
	php_info_print_table_start();
	php_info_print_table_header(2, "parsekit support", "enabled");
	php_info_print_table_row(2, "version", PHP_PARSEKIT_VERSION);
	php_info_print_table_end();
}
/* }}} */


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */


拷贝 php 5.3  源码包中的 php3_compat.h 文件 到 扩展的根目录

然后 顺利的话,make , make install 就能通过了