mirror of
https://github.com/php/pecl-php-parsekit.git
synced 2026-03-24 01:02:10 +01:00
Initial Release
This commit is contained in:
53
README
Normal file
53
README
Normal file
@@ -0,0 +1,53 @@
|
||||
parsekit: PHP Opcode Analyser
|
||||
|
||||
Provides a userspace interpretation of the opcodes
|
||||
generated by the Zend engine compiler built into PHP.
|
||||
|
||||
This extension is meant for development and debug
|
||||
purposes only and contains some code which is
|
||||
potentially non-threadsafe.
|
||||
|
||||
This extension exports two functions
|
||||
(parsekit_compile_string(string phpcode[, array &errors])
|
||||
and parsekit_compile_file(string filename[, array &errors]))
|
||||
which will attempt to compile one or more blocks of PHP
|
||||
code into Zend opcodes.
|
||||
|
||||
The output of these functions is an n-depth hash containing
|
||||
the main block of code's oparray at its root, with
|
||||
function_table and class_table elements to hold any functions
|
||||
or classes declared within the compiled code.
|
||||
|
||||
In order to accomplish these compilation steps within
|
||||
the context of an active execution, some potentially unsafe
|
||||
methods are used.
|
||||
|
||||
1) Compilation modifies EG(function_table) and EG(class_table),
|
||||
after compilation completes, parsekit pops these functions
|
||||
and classes off the end of these stacks.
|
||||
|
||||
2) To avoid parse errors in supplied code causing a zend_bailout(),
|
||||
parsekit replaces zend_error_cb with a wrapper which passes E_CORE_ERROR
|
||||
or any error which occurs outside of parsekit_compile_*() onto
|
||||
the original zend_error_cb. If another module which replaced
|
||||
zend_error_cb were to be loaded prior to parsekit, then unloaded
|
||||
after parsekit's startup, but prior to parsekit's shutdown, then
|
||||
the global value zend_error_cb could become populated with an
|
||||
invalid function pointer.
|
||||
|
||||
The moral of the story: Use this at your own risk.
|
||||
|
||||
This extension also exports constant entries for all class types,
|
||||
function types, node types, and opcodes. While a name collision
|
||||
would be unexpected, all constants are prefixed with PARSEKIT_
|
||||
just to be safe.
|
||||
|
||||
Example:
|
||||
|
||||
#define ZEND_NOP 0
|
||||
|
||||
Exported as:
|
||||
|
||||
REGISTER_LONG_CONSTANT("PARSEKIT_ZEND_NOP", 0, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
For examples on usage, refer to the examples subdirectory in this package.
|
||||
10
config.m4
Normal file
10
config.m4
Normal file
@@ -0,0 +1,10 @@
|
||||
dnl $Id$
|
||||
dnl config.m4 for extension parsekit
|
||||
|
||||
PHP_ARG_ENABLE(parsekit, whether to enable parsekit support,
|
||||
[ --enable-parsekit Enable parsekit support])
|
||||
|
||||
if test "$PHP_PARSEKIT" != "no"; then
|
||||
AC_DEFINE(HAVE_PARSEKITLIB, 1, [ Parser Toolkit ])
|
||||
PHP_NEW_EXTENSION(parsekit, parsekit.c, $ext_shared)
|
||||
fi
|
||||
6
examples/compile_file.php
Normal file
6
examples/compile_file.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
/* Compile ourself */
|
||||
|
||||
$oparray = parsekit_compile_file($_SERVER['PHP_SELF']);
|
||||
|
||||
var_dump($oparray);
|
||||
14
examples/compile_string.php
Normal file
14
examples/compile_string.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/* Compile a simple Hello World type program */
|
||||
|
||||
$oparray = parsekit_compile_string('
|
||||
|
||||
function foo($bar = "Hello World") {
|
||||
return $bar;
|
||||
}
|
||||
|
||||
echo foo();
|
||||
|
||||
');
|
||||
|
||||
var_dump($oparray);
|
||||
14
examples/compile_string_show_errors.php
Normal file
14
examples/compile_string_show_errors.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/* Compile a buggy Hello World program */
|
||||
|
||||
$oparray = parsekit_compile_string('
|
||||
|
||||
function foo($bar = "Hello World) {
|
||||
return $bar;
|
||||
}
|
||||
|
||||
echo foo();
|
||||
|
||||
', $errors);
|
||||
|
||||
var_dump($errors);
|
||||
40
package.xml
Normal file
40
package.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<package version="1.0">
|
||||
<name>parsekit</name>
|
||||
<summary>PHP Opcode Analyser</summary>
|
||||
<description>
|
||||
Provides a userspace interpretation of the opcodes generated by the Zend engine compiler built into PHP.
|
||||
|
||||
This extension is meant for development and debug purposes only and contains some code which is potentially non-threadsafe.
|
||||
</description>
|
||||
<license>PHP</license>
|
||||
<maintainers>
|
||||
<maintainer>
|
||||
<user>pollita</user>
|
||||
<name>Sara Golemon</name>
|
||||
<email>pollita@php.net</email>
|
||||
<role>lead</role>
|
||||
</maintainer>
|
||||
</maintainers>
|
||||
|
||||
<release>
|
||||
<version>0.1</version>
|
||||
<state>alpha</state>
|
||||
<date>2004-05-06</date>
|
||||
<notes>Initial Release</notes>
|
||||
<filelist>
|
||||
<file role="src" name="config.m4"/>
|
||||
<file role="src" name="parsekit.c"/>
|
||||
<file role="src" name="php_parsekit.h"/>
|
||||
<file role="doc" name="README"/>
|
||||
<dir name="examples">
|
||||
<file role="script" name="compile_string.php"/>
|
||||
<file role="script" name="compile_file.php"/>
|
||||
<file role="script" name="compile_string_show_errors.php"/>
|
||||
</dir>
|
||||
</filelist>
|
||||
<deps>
|
||||
<dep type="php" rel="ge" version="5.0.0" />
|
||||
</deps>
|
||||
</release>
|
||||
|
||||
</package>
|
||||
791
parsekit.c
Normal file
791
parsekit.c
Normal file
@@ -0,0 +1,791 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2004 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: |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_parsekit.h"
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS(parsekit)
|
||||
/* Potentially thread-unsafe, see MINIT_FUNCTION */
|
||||
void (*original_error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
|
||||
|
||||
/* Parsekit Workhorse */
|
||||
|
||||
/* {{{ php_parsekit_define_name */
|
||||
static char* php_parsekit_define_name(long val, php_parsekit_define_list *lookup_list, char *unknown_default)
|
||||
{
|
||||
php_parsekit_define_list *names;
|
||||
|
||||
for(names = lookup_list; names->str; names++) {
|
||||
if (names->val == val) {
|
||||
return names->str;
|
||||
}
|
||||
}
|
||||
|
||||
return unknown_default ? unknown_default : PHP_PARSEKIT_UNKNOWN;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_parsekit_parse_node */
|
||||
static void php_parsekit_parse_node(zval *return_value, znode *node 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);
|
||||
add_assoc_zval(return_value, "constant", tmpzval);
|
||||
} else {
|
||||
/* IS_VAR || IS_TMP_VAR || IS_UNUSED */
|
||||
char sop[(sizeof(void *) * 2) + 1];
|
||||
|
||||
/* Which of these is relevant depends on the opcode
|
||||
Just offer them all up and let the user decide */
|
||||
/* Probably best to only do the snprintf once,
|
||||
but leave in the extra calls for readability.
|
||||
This is just a debug extension for pete's sake. */
|
||||
add_assoc_long(return_value, "var", node->u.var);
|
||||
|
||||
snprintf(sop, (sizeof(void *) * 2) + 1, "%X", (unsigned int)node->u.opline_num);
|
||||
add_assoc_string(return_value, "opline_num", sop, 1);
|
||||
|
||||
snprintf(sop, (sizeof(void *) * 2) + 1, "%X", (unsigned int)node->u.op_array);
|
||||
add_assoc_string(return_value, "op_array", sop, 1);
|
||||
|
||||
snprintf(sop, (sizeof(void *) * 2) + 1, "%X", (unsigned int)node->u.jmp_addr);
|
||||
add_assoc_string(return_value, "jmp_addr", sop, 1);
|
||||
|
||||
add_assoc_long(return_value, "EA.type", node->u.EA.type);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_parsekit_parse_op */
|
||||
static void php_parsekit_parse_op(zval *return_value, zend_op *op TSRMLS_DC)
|
||||
{
|
||||
zval *result, *op1, *op2;
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
/* op->handler */
|
||||
add_assoc_long(return_value, "opcode", op->opcode);
|
||||
add_assoc_string(return_value, "opcode_name", php_parsekit_define_name(op->opcode, php_parsekit_opcode_names, PHP_PARSEKIT_OPCODE_UNKNOWN) , 1);
|
||||
|
||||
/* args: result, op1, op2 */
|
||||
MAKE_STD_ZVAL(result);
|
||||
MAKE_STD_ZVAL(op1);
|
||||
MAKE_STD_ZVAL(op2);
|
||||
|
||||
php_parsekit_parse_node(result, &(op->result) TSRMLS_CC);
|
||||
php_parsekit_parse_node(op1, &(op->op1) TSRMLS_CC);
|
||||
php_parsekit_parse_node(op2, &(op->op2) TSRMLS_CC);
|
||||
|
||||
add_assoc_zval(return_value, "result", result);
|
||||
add_assoc_zval(return_value, "op1", op1);
|
||||
add_assoc_zval(return_value, "op2", op2);
|
||||
|
||||
add_assoc_long(return_value, "extended_value", op->extended_value);
|
||||
add_assoc_long(return_value, "lineno", op->lineno);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_parsekit_parse_arginfo */
|
||||
static void php_parsekit_parse_arginfo(zval *return_value, zend_uint num_args, zend_arg_info *arginfo 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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_parsekit_parse_op_array */
|
||||
static void php_parsekit_parse_op_array(zval *return_value, zend_op_array *ops TSRMLS_DC)
|
||||
{
|
||||
zend_op *op;
|
||||
zval *tmpzval;
|
||||
int i = 0;
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
/* "Common" members */
|
||||
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 {
|
||||
add_assoc_null(return_value, "function_name");
|
||||
}
|
||||
|
||||
if (ops->scope && ops->scope->name) {
|
||||
add_assoc_stringl(return_value, "scope", ops->scope->name, ops->scope->name_length, 1);
|
||||
} else {
|
||||
add_assoc_null(return_value, "scope");
|
||||
}
|
||||
|
||||
add_assoc_long(return_value, "fn_flags", ops->fn_flags);
|
||||
if (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 {
|
||||
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 {
|
||||
add_assoc_null(tmpzval, "scope");
|
||||
}
|
||||
add_assoc_zval(return_value, "prototype", tmpzval);
|
||||
} else {
|
||||
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);
|
||||
add_assoc_bool(return_value, "return_reference", ops->return_reference);
|
||||
if (ops->num_args && ops->arg_info) {
|
||||
MAKE_STD_ZVAL(tmpzval);
|
||||
php_parsekit_parse_arginfo(tmpzval, ops->num_args, ops->arg_info TSRMLS_CC);
|
||||
add_assoc_zval(return_value, "arg_info", tmpzval);
|
||||
} else {
|
||||
add_assoc_null(return_value, "arg_info");
|
||||
}
|
||||
/* End "Common" */
|
||||
|
||||
add_assoc_long(return_value, "refcount", *(ops->refcount));
|
||||
MAKE_STD_ZVAL(tmpzval);
|
||||
array_init(tmpzval);
|
||||
for(op = ops->opcodes, i = 0; op && i < ops->size; op++, i++) {
|
||||
zval *zop;
|
||||
char sop[(sizeof(void *) * 2) + 1];
|
||||
|
||||
/* Use the memory address as a convenient reference point
|
||||
This lets us find target ops when we JMP */
|
||||
snprintf(sop, (sizeof(void *) * 2) + 1, "%X", (unsigned int)op);
|
||||
MAKE_STD_ZVAL(zop);
|
||||
php_parsekit_parse_op(zop, op TSRMLS_CC);
|
||||
add_assoc_zval(tmpzval, sop, zop);
|
||||
}
|
||||
add_assoc_zval(return_value, "opcodes", tmpzval);
|
||||
add_assoc_long(return_value, "last", ops->last);
|
||||
add_assoc_long(return_value, "size", ops->size);
|
||||
add_assoc_long(return_value, "T", ops->T);
|
||||
|
||||
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 {
|
||||
add_assoc_null(return_value, "brk_cont_array");
|
||||
}
|
||||
add_assoc_long(return_value, "last_brk_cont", ops->last_brk_cont);
|
||||
add_assoc_long(return_value, "current_brk_cont", ops->current_brk_cont);
|
||||
|
||||
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 {
|
||||
add_assoc_null(return_value, "try_catch_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 {
|
||||
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 {
|
||||
add_assoc_null(return_value, "start_op");
|
||||
}
|
||||
|
||||
add_assoc_long(return_value, "backpatch_count", ops->backpatch_count);
|
||||
add_assoc_bool(return_value, "done_pass_two", ops->done_pass_two);
|
||||
add_assoc_bool(return_value, "uses_this", ops->uses_this);
|
||||
|
||||
if (ops->filename) {
|
||||
add_assoc_string(return_value, "filename", ops->filename, 1);
|
||||
} else {
|
||||
add_assoc_null(return_value, "filename");
|
||||
}
|
||||
|
||||
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 {
|
||||
add_assoc_null(return_value, "doc_comment");
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_parsekit_pop_functions */
|
||||
static int php_parsekit_pop_functions(zval *return_value, HashTable *function_table, int target_count TSRMLS_DC)
|
||||
{
|
||||
array_init(return_value);
|
||||
|
||||
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;
|
||||
|
||||
zend_hash_internal_pointer_end(function_table);
|
||||
if (zend_hash_get_current_data(function_table, (void **)&function) == 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_USER_FUNCTION) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from function table: "
|
||||
"Found %s where ZEND_USER_FUNCTION was expected.",
|
||||
php_parsekit_define_name(function->type, php_parsekit_function_types, PHP_PARSEKIT_FUNCTYPE_UNKNOWN));
|
||||
return FAILURE;
|
||||
}
|
||||
MAKE_STD_ZVAL(function_ops);
|
||||
php_parsekit_parse_op_array(function_ops, &(function->op_array) 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, NULL) == HASH_KEY_IS_STRING) {
|
||||
/* 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_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 TSRMLS_DC)
|
||||
{
|
||||
zval *tmpzval;
|
||||
int i;
|
||||
|
||||
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 {
|
||||
add_assoc_null(return_value, "parent");
|
||||
}
|
||||
add_assoc_long(return_value, "refcount", ce->refcount);
|
||||
add_assoc_bool(return_value, "constnats_updated", ce->constants_updated);
|
||||
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 {
|
||||
add_assoc_null(return_value, "constructor");
|
||||
}
|
||||
|
||||
if (ce->clone) {
|
||||
add_assoc_string(return_value, "clone", ce->clone->common.function_name, 1);
|
||||
} else {
|
||||
add_assoc_null(return_value, "clone");
|
||||
}
|
||||
|
||||
if (ce->__get) {
|
||||
add_assoc_string(return_value, "__get", ce->__get->common.function_name, 1);
|
||||
} else {
|
||||
add_assoc_null(return_value, "__get");
|
||||
}
|
||||
|
||||
if (ce->__set) {
|
||||
add_assoc_string(return_value, "__set", ce->__set->common.function_name, 1);
|
||||
} else {
|
||||
add_assoc_null(return_value, "__set");
|
||||
}
|
||||
|
||||
if (ce->__call) {
|
||||
add_assoc_string(return_value, "__call", ce->__call->common.function_name, 1);
|
||||
} else {
|
||||
add_assoc_null(return_value, "__call");
|
||||
}
|
||||
|
||||
if (zend_hash_num_elements(&(ce->function_table)) > 0) {
|
||||
MAKE_STD_ZVAL(tmpzval);
|
||||
if (php_parsekit_pop_functions(tmpzval, &(ce->function_table), 0 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 {
|
||||
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 {
|
||||
add_assoc_null(return_value, "default_properties");
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
add_assoc_null(return_value, "doc_comment");
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_parsekit_pop_classes */
|
||||
static int php_parsekit_pop_classes(zval *return_value, HashTable *class_table, int target_count 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;
|
||||
}
|
||||
class_entry = *pce;
|
||||
if (class_entry->type != ZEND_USER_CLASS) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to remove pollution from class table: "
|
||||
"Found %s where ZEND_USER_CLASS was expected.",
|
||||
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 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 TSRMLS_DC)
|
||||
{
|
||||
zval *declared_functions, *declared_classes;
|
||||
|
||||
/* main() */
|
||||
php_parsekit_parse_op_array(return_value, ops TSRMLS_CC);
|
||||
|
||||
MAKE_STD_ZVAL(declared_functions);
|
||||
ZVAL_NULL(declared_functions);
|
||||
|
||||
MAKE_STD_ZVAL(declared_classes);
|
||||
ZVAL_NULL(declared_classes);
|
||||
|
||||
if (original_num_functions < zend_hash_num_elements(EG(function_table))) {
|
||||
/* The compiled code introduced new functions, get them out of there! */
|
||||
php_parsekit_pop_functions(declared_functions, EG(function_table), original_num_functions TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (original_num_classes < zend_hash_num_elements(EG(class_table))) {
|
||||
/* The compiled code introduced new classes, get them out of here */
|
||||
php_parsekit_pop_classes(declared_classes, EG(class_table), original_num_classes TSRMLS_CC);
|
||||
}
|
||||
add_assoc_zval(return_value, "function_table", declared_functions);
|
||||
add_assoc_zval(return_value, "class_table", declared_classes);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* ****************************************** */
|
||||
/* Module Housekeeping and Userland Functions */
|
||||
/* ****************************************** */
|
||||
|
||||
/* {{{ proto array parsekit_compile_string(string phpcode)
|
||||
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_handle_op_arrays;
|
||||
zend_op_array *ops;
|
||||
zval *zcode, *zerrors = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &zcode, &zerrors) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (zerrors) {
|
||||
zval_dtor(zerrors);
|
||||
ZVAL_NULL(zerrors);
|
||||
PARSEKIT_G(compile_errors) = zerrors;
|
||||
}
|
||||
|
||||
convert_to_string(zcode);
|
||||
original_handle_op_arrays = CG(handle_op_arrays);
|
||||
CG(handle_op_arrays) = 0;
|
||||
PARSEKIT_G(in_parsekit_compile) = 1;
|
||||
ops = compile_string(zcode, "Parsekit Compiler" TSRMLS_CC);
|
||||
PARSEKIT_G(in_parsekit_compile) = 0;
|
||||
PARSEKIT_G(compile_errors) = NULL;
|
||||
CG(handle_op_arrays) = original_handle_op_arrays;
|
||||
|
||||
|
||||
if (ops) {
|
||||
php_parsekit_common(return_value, original_num_functions, original_num_classes, ops TSRMLS_CC);
|
||||
destroy_op_array(ops TSRMLS_CC);
|
||||
efree(ops);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array parsekit_compile_file(string filename)
|
||||
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_handle_op_arrays;
|
||||
zend_op_array *ops;
|
||||
zval *zfilename, *zerrors = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &zfilename, &zerrors) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (zerrors) {
|
||||
zval_dtor(zerrors);
|
||||
ZVAL_NULL(zerrors);
|
||||
PARSEKIT_G(compile_errors) = zerrors;
|
||||
}
|
||||
|
||||
convert_to_string(zfilename);
|
||||
original_handle_op_arrays = CG(handle_op_arrays);
|
||||
CG(handle_op_arrays) = 0;
|
||||
PARSEKIT_G(in_parsekit_compile) = 1;
|
||||
ops = compile_filename(ZEND_INCLUDE, zfilename TSRMLS_CC);
|
||||
PARSEKIT_G(in_parsekit_compile) = 0;
|
||||
PARSEKIT_G(compile_errors) = NULL;
|
||||
CG(handle_op_arrays) = original_handle_op_arrays;
|
||||
|
||||
if (ops) {
|
||||
php_parsekit_common(return_value, original_num_functions, original_num_classes, ops TSRMLS_CC);
|
||||
destroy_op_array(ops TSRMLS_CC);
|
||||
efree(ops);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(second_arg_force_ref, 0)
|
||||
ZEND_ARG_PASS_INFO(0)
|
||||
ZEND_ARG_PASS_INFO(1)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
|
||||
/* {{{ function_entry */
|
||||
function_entry parsekit_functions[] = {
|
||||
PHP_FE(parsekit_compile_string, second_arg_force_ref)
|
||||
PHP_FE(parsekit_compile_file, second_arg_force_ref)
|
||||
{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
|
||||
"0.1", /* Replace with version number for your extension */
|
||||
#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. */
|
||||
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);
|
||||
|
||||
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. */
|
||||
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 = 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_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
|
||||
*/
|
||||
235
php_parsekit.h
Normal file
235
php_parsekit.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2004 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: |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef PHP_PARSEKIT_H
|
||||
#define PHP_PARSEKIT_H
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
extern zend_module_entry parsekit_module_entry;
|
||||
#define phpext_parsekit_ptr &parsekit_module_entry
|
||||
|
||||
PHP_MINIT_FUNCTION(parsekit);
|
||||
PHP_MSHUTDOWN_FUNCTION(parsekit);
|
||||
PHP_MINFO_FUNCTION(parsekit);
|
||||
|
||||
PHP_FUNCTION(parsekit_compile_string);
|
||||
PHP_FUNCTION(parsekit_compile_file);
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(parsekit)
|
||||
int in_parsekit_compile;
|
||||
zval *compile_errors;
|
||||
ZEND_END_MODULE_GLOBALS(parsekit)
|
||||
|
||||
#ifdef ZTS
|
||||
#define PARSEKIT_G(v) TSRMG(parsekit_globals_id, zend_parsekit_globals *, v)
|
||||
#else
|
||||
#define PARSEKIT_G(v) (parsekit_globals.v)
|
||||
#endif
|
||||
|
||||
typedef struct _php_parsekit_define_list {
|
||||
long val;
|
||||
char *str;
|
||||
} php_parsekit_define_list;
|
||||
|
||||
#define PHP_PARSEKIT_UNKNOWN "UNKNOWN"
|
||||
#define PHP_PARSEKIT_OPCODE_UNKNOWN "Unknown Opcode"
|
||||
#define PHP_PARSEKIT_NODETYPE_UNKNOWN "Unknown Nodetype"
|
||||
#define PHP_PARSEKIT_FUNCTYPE_UNKNOWN "Unknown Functiontype"
|
||||
#define PHP_PARSEKIT_CLASSTYPE_UNKNOWN "Unknown Classtype"
|
||||
|
||||
static php_parsekit_define_list php_parsekit_class_types[] = {
|
||||
{ ZEND_INTERNAL_CLASS, "ZEND_INTERNAL_CLASS" },
|
||||
{ ZEND_USER_CLASS, "ZEND_USER_CLASS" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static php_parsekit_define_list php_parsekit_function_types[] = {
|
||||
{ ZEND_INTERNAL_FUNCTION, "ZEND_INTERNAL_FUNCTION" },
|
||||
{ ZEND_USER_FUNCTION, "ZEND_USER_FUNCTION" },
|
||||
{ ZEND_OVERLOADED_FUNCTION, "ZEND_OVERLOADED_FUNCTION" },
|
||||
{ ZEND_EVAL_CODE, "ZEND_EVAL_CODE" },
|
||||
{ ZEND_OVERLOADED_FUNCTION_TEMPORARY, "ZEND_OVERLOADED_FUNCTION_TEMPORARY" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static php_parsekit_define_list php_parsekit_nodetype_names[] = {
|
||||
{ IS_CONST, "IS_CONST" },
|
||||
{ IS_TMP_VAR, "IS_TMP_VAR" },
|
||||
{ IS_VAR, "IS_VAR" },
|
||||
{ IS_UNUSED, "IS_UNUSED" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static php_parsekit_define_list php_parsekit_opcode_names[] = {
|
||||
{ ZEND_NOP, "ZEND_NOP" },
|
||||
{ ZEND_ADD, "ZEND_ADD" },
|
||||
{ ZEND_SUB, "ZEND_SUB" },
|
||||
{ ZEND_MUL, "ZEND_MUL" },
|
||||
{ ZEND_DIV, "ZEND_DIV" },
|
||||
{ ZEND_MOD, "ZEND_MOD" },
|
||||
{ ZEND_SL, "ZEND_SL" },
|
||||
{ ZEND_SR, "ZEND_SR" },
|
||||
{ ZEND_CONCAT, "ZEND_CONCAT" },
|
||||
{ ZEND_BW_OR, "ZEND_BW_OR" },
|
||||
{ ZEND_BW_AND, "ZEND_BW_AND" },
|
||||
{ ZEND_BW_XOR, "ZEND_BW_XOR" },
|
||||
{ ZEND_BW_NOT, "ZEND_BW_NOT" },
|
||||
{ ZEND_BOOL_NOT, "ZEND_BOOL_NOT" },
|
||||
{ ZEND_BOOL_XOR, "ZEND_BOOL_XOR" },
|
||||
{ ZEND_IS_IDENTICAL, "ZEND_IS_IDENTICAL" },
|
||||
{ ZEND_IS_NOT_IDENTICAL, "ZEND_IS_NOT_IDENTICAL" },
|
||||
{ ZEND_IS_EQUAL, "ZEND_IS_EQUAL" },
|
||||
{ ZEND_IS_NOT_EQUAL, "ZEND_IS_NOT_EQUAL" },
|
||||
{ ZEND_IS_SMALLER, "ZEND_IS_SMALLER" },
|
||||
{ ZEND_IS_SMALLER_OR_EQUAL, "ZEND_IS_SMALLER_OR_EQUAL" },
|
||||
{ ZEND_CAST, "ZEND_CAST" },
|
||||
{ ZEND_QM_ASSIGN, "ZEND_QM_ASSIGN" },
|
||||
{ ZEND_ASSIGN_ADD, "ZEND_ASSIGN_ADD" },
|
||||
{ ZEND_ASSIGN_SUB, "ZEND_ASSIGN_SUB" },
|
||||
{ ZEND_ASSIGN_MUL, "ZEND_ASSIGN_MUL" },
|
||||
{ ZEND_ASSIGN_DIV, "ZEND_ASSIGN_DIV" },
|
||||
{ ZEND_ASSIGN_MOD, "ZEND_ASSIGN_MOD" },
|
||||
{ ZEND_ASSIGN_SL, "ZEND_ASSIGN_SL" },
|
||||
{ ZEND_ASSIGN_SR, "ZEND_ASSIGN_SR" },
|
||||
{ ZEND_ASSIGN_CONCAT, "ZEND_ASSIGN_CONCAT" },
|
||||
{ ZEND_ASSIGN_BW_OR, "ZEND_ASSIGN_BW_OR" },
|
||||
{ ZEND_ASSIGN_BW_AND, "ZEND_ASSIGN_BW_AND" },
|
||||
{ ZEND_ASSIGN_BW_XOR, "ZEND_ASSIGN_BW_XOR" },
|
||||
{ ZEND_PRE_INC, "ZEND_PRE_INC" },
|
||||
{ ZEND_PRE_DEC, "ZEND_PRE_DEC" },
|
||||
{ ZEND_POST_INC, "ZEND_POST_INC" },
|
||||
{ ZEND_POST_DEC, "ZEND_POST_DEC" },
|
||||
{ ZEND_ASSIGN, "ZEND_ASSIGN" },
|
||||
{ ZEND_ASSIGN_REF, "ZEND_ASSIGN_REF" },
|
||||
{ ZEND_ECHO, "ZEND_ECHO" },
|
||||
{ ZEND_PRINT, "ZEND_PRINT" },
|
||||
{ ZEND_JMP, "ZEND_JMP" },
|
||||
{ ZEND_JMPZ, "ZEND_JMPZ" },
|
||||
{ ZEND_JMPNZ, "ZEND_JMPNZ" },
|
||||
{ ZEND_JMPZNZ, "ZEND_JMPZNZ" },
|
||||
{ ZEND_JMPZ_EX, "ZEND_JMPZ_EX" },
|
||||
{ ZEND_JMPNZ_EX, "ZEND_JMPNZ_EX" },
|
||||
{ ZEND_CASE, "ZEND_CASE" },
|
||||
{ ZEND_SWITCH_FREE, "ZEND_SWITCH_FREE" },
|
||||
{ ZEND_BRK, "ZEND_BRK" },
|
||||
{ ZEND_CONT, "ZEND_CONT" },
|
||||
{ ZEND_BOOL, "ZEND_BOOL" },
|
||||
{ ZEND_INIT_STRING, "ZEND_INIT_STRING" },
|
||||
{ ZEND_ADD_CHAR, "ZEND_ADD_CHAR" },
|
||||
{ ZEND_ADD_STRING, "ZEND_ADD_STRING" },
|
||||
{ ZEND_ADD_VAR, "ZEND_ADD_VAR" },
|
||||
{ ZEND_BEGIN_SILENCE, "ZEND_BEGIN_SILENCE" },
|
||||
{ ZEND_END_SILENCE, "ZEND_END_SILENCE" },
|
||||
{ ZEND_INIT_FCALL_BY_NAME, "ZEND_INIT_FCALL_BY_NAME" },
|
||||
{ ZEND_DO_FCALL, "ZEND_DO_FCALL" },
|
||||
{ ZEND_DO_FCALL_BY_NAME, "ZEND_DO_FCALL_BY_NAME" },
|
||||
{ ZEND_RETURN, "ZEND_RETURN" },
|
||||
{ ZEND_RECV, "ZEND_RECV" },
|
||||
{ ZEND_RECV_INIT, "ZEND_RECV_INIT" },
|
||||
{ ZEND_SEND_VAL, "ZEND_SEND_VAL" },
|
||||
{ ZEND_SEND_VAR, "ZEND_SEND_VAR" },
|
||||
{ ZEND_SEND_REF, "ZEND_SEND_REF" },
|
||||
{ ZEND_NEW, "ZEND_NEW" },
|
||||
{ ZEND_JMP_NO_CTOR, "ZEND_JMP_NO_CTOR" },
|
||||
{ ZEND_FREE, "ZEND_FREE" },
|
||||
{ ZEND_INIT_ARRAY, "ZEND_INIT_ARRAY" },
|
||||
{ ZEND_ADD_ARRAY_ELEMENT, "ZEND_ADD_ARRAY_ELEMENT" },
|
||||
{ ZEND_INCLUDE_OR_EVAL, "ZEND_INCLUDE_OR_EVAL" },
|
||||
{ ZEND_UNSET_VAR, "ZEND_UNSET_VAR" },
|
||||
{ ZEND_UNSET_DIM_OBJ, "ZEND_UNSET_DIM_OBJ" },
|
||||
{ ZEND_FE_RESET, "ZEND_FE_RESET" },
|
||||
{ ZEND_FE_FETCH, "ZEND_FE_FETCH" },
|
||||
{ ZEND_EXIT, "ZEND_EXIT" },
|
||||
{ ZEND_FETCH_R, "ZEND_FETCH_R" },
|
||||
{ ZEND_FETCH_DIM_R, "ZEND_FETCH_DIM_R" },
|
||||
{ ZEND_FETCH_OBJ_R, "ZEND_FETCH_OBJ_R" },
|
||||
{ ZEND_FETCH_W, "ZEND_FETCH_W" },
|
||||
{ ZEND_FETCH_DIM_W, "ZEND_FETCH_DIM_W" },
|
||||
{ ZEND_FETCH_OBJ_W, "ZEND_FETCH_OBJ_W" },
|
||||
{ ZEND_FETCH_RW, "ZEND_FETCH_RW" },
|
||||
{ ZEND_FETCH_DIM_RW, "ZEND_FETCH_DIM_RW" },
|
||||
{ ZEND_FETCH_OBJ_RW, "ZEND_FETCH_OBJ_RW" },
|
||||
{ ZEND_FETCH_IS, "ZEND_FETCH_IS" },
|
||||
{ ZEND_FETCH_DIM_IS, "ZEND_FETCH_DIM_IS" },
|
||||
{ ZEND_FETCH_OBJ_IS, "ZEND_FETCH_OBJ_IS" },
|
||||
{ ZEND_FETCH_FUNC_ARG, "ZEND_FETCH_FUNC_ARG" },
|
||||
{ ZEND_FETCH_DIM_FUNC_ARG, "ZEND_FETCH_DIM_FUNC_ARG" },
|
||||
{ ZEND_FETCH_OBJ_FUNC_ARG, "ZEND_FETCH_OBJ_FUNC_ARG" },
|
||||
{ ZEND_FETCH_UNSET, "ZEND_FETCH_UNSET" },
|
||||
{ ZEND_FETCH_DIM_UNSET, "ZEND_FETCH_DIM_UNSET" },
|
||||
{ ZEND_FETCH_OBJ_UNSET, "ZEND_FETCH_OBJ_UNSET" },
|
||||
{ ZEND_FETCH_DIM_TMP_VAR, "ZEND_FETCH_DIM_TMP_VAR" },
|
||||
{ ZEND_FETCH_CONSTANT, "ZEND_FETCH_CONSTANT" },
|
||||
{ ZEND_EXT_STMT, "ZEND_EXT_STMT" },
|
||||
{ ZEND_EXT_FCALL_BEGIN, "ZEND_EXT_FCALL_BEGIN" },
|
||||
{ ZEND_EXT_FCALL_END, "ZEND_EXT_FCALL_END" },
|
||||
{ ZEND_EXT_NOP, "ZEND_EXT_NOP" },
|
||||
{ ZEND_TICKS, "ZEND_TICKS" },
|
||||
{ ZEND_SEND_VAR_NO_REF, "ZEND_SEND_VAR_NO_REF" },
|
||||
{ ZEND_CATCH, "ZEND_CATCH" },
|
||||
{ ZEND_THROW, "ZEND_THROW" },
|
||||
{ ZEND_FETCH_CLASS, "ZEND_FETCH_CLASS" },
|
||||
{ ZEND_CLONE, "ZEND_CLONE" },
|
||||
{ ZEND_INIT_CTOR_CALL, "ZEND_INIT_CTOR_CALL" },
|
||||
{ ZEND_INIT_METHOD_CALL, "ZEND_INIT_METHOD_CALL" },
|
||||
{ ZEND_INIT_STATIC_METHOD_CALL, "ZEND_INIT_STATIC_METHOD_CALL" },
|
||||
{ ZEND_ISSET_ISEMPTY_VAR, "ZEND_ISSET_ISEMPTY_VAR" },
|
||||
{ ZEND_ISSET_ISEMPTY_DIM_OBJ, "ZEND_ISSET_ISEMPTY_DIM_OBJ" },
|
||||
{ ZEND_IMPORT_FUNCTION, "ZEND_IMPORT_FUNCTION" },
|
||||
{ ZEND_IMPORT_CLASS, "ZEND_IMPORT_CLASS" },
|
||||
{ ZEND_IMPORT_CONST, "ZEND_IMPORT_CONST" },
|
||||
{ ZEND_PRE_INC_OBJ, "ZEND_PRE_INC_OBJ" },
|
||||
{ ZEND_PRE_DEC_OBJ, "ZEND_PRE_DEC_OBJ" },
|
||||
{ ZEND_POST_INC_OBJ, "ZEND_POST_INC_OBJ" },
|
||||
{ ZEND_POST_DEC_OBJ, "ZEND_POST_DEC_OBJ" },
|
||||
{ ZEND_ASSIGN_OBJ, "ZEND_ASSIGN_OBJ" },
|
||||
{ ZEND_OP_DATA, "ZEND_OP_DATA" },
|
||||
{ ZEND_INSTANCEOF, "ZEND_INSTANCEOF" },
|
||||
{ ZEND_DECLARE_CLASS, "ZEND_DECLARE_CLASS" },
|
||||
{ ZEND_DECLARE_INHERITED_CLASS, "ZEND_DECLARE_INHERITED_CLASS" },
|
||||
{ ZEND_DECLARE_FUNCTION, "ZEND_DECLARE_FUNCTION" },
|
||||
{ ZEND_RAISE_ABSTRACT_ERROR, "ZEND_RAISE_ABSTRACT_ERROR" },
|
||||
{ ZEND_ADD_INTERFACE, "ZEND_ADD_INTERFACE" },
|
||||
{ ZEND_VERIFY_ABSTRACT_CLASS, "ZEND_VERIFY_ABSTRACT_CLASS" },
|
||||
{ ZEND_ASSIGN_DIM, "ZEND_ASSIGN_DIM" },
|
||||
{ ZEND_ISSET_ISEMPTY_PROP_OBJ, "ZEND_ISSET_ISEMPTY_PROP_OBJ" },
|
||||
{ ZEND_HANDLE_EXCEPTION, "ZEND_HANDLE_EXCEPTION" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define phpext_parsekit_ptr &parsekit_module_entry
|
||||
|
||||
#endif /* PHP_PARSEKIT_H */
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user