背景:
几天前 在项目框架中 实现一个 类和方法的扫描器,配合 语言包 来实现一个动态的 后台菜单。发现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 |
+----------------------------------------------------------------------+
*/
/* $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
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 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 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
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 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 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
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
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 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
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
/* 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
/* 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 就能通过了