diff --git a/README b/README
new file mode 100644
index 0000000..0591538
--- /dev/null
+++ b/README
@@ -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.
diff --git a/config.m4 b/config.m4
new file mode 100644
index 0000000..b12d6d8
--- /dev/null
+++ b/config.m4
@@ -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
diff --git a/examples/compile_file.php b/examples/compile_file.php
new file mode 100644
index 0000000..e20b53c
--- /dev/null
+++ b/examples/compile_file.php
@@ -0,0 +1,6 @@
+
+ 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.
+
+ PHP
+
+
+ pollita
+ Sara Golemon
+ pollita@php.net
+ lead
+
+
+
+
+ 0.1
+ alpha
+ 2004-05-06
+ Initial Release
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/parsekit.c b/parsekit.c
new file mode 100644
index 0000000..3973daa
--- /dev/null
+++ b/parsekit.c
@@ -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
+ */
diff --git a/php_parsekit.h b/php_parsekit.h
new file mode 100644
index 0000000..a3f9f74
--- /dev/null
+++ b/php_parsekit.h
@@ -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
+ */
+