diff --git a/parsekit.c b/parsekit.c index 3973daa..ce0f81e 100644 --- a/parsekit.c +++ b/parsekit.c @@ -12,7 +12,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: | + | Author: Sara Golemon | +----------------------------------------------------------------------+ */ @@ -77,8 +77,11 @@ static void php_parsekit_parse_node(zval *return_value, znode *node TSRMLS_DC) snprintf(sop, (sizeof(void *) * 2) + 1, "%X", (unsigned int)node->u.op_array); add_assoc_string(return_value, "op_array", sop, 1); +#if PHP_MAJOR_VERSION >= 5 +/* ZE2 Only */ snprintf(sop, (sizeof(void *) * 2) + 1, "%X", (unsigned int)node->u.jmp_addr); add_assoc_string(return_value, "jmp_addr", sop, 1); +#endif add_assoc_long(return_value, "EA.type", node->u.EA.type); } @@ -114,6 +117,7 @@ static void php_parsekit_parse_op(zval *return_value, zend_op *op TSRMLS_DC) } /* }}} */ +#if PHP_MAJOR_VERSION >= 5 /* {{{ php_parsekit_parse_arginfo */ static void php_parsekit_parse_arginfo(zval *return_value, zend_uint num_args, zend_arg_info *arginfo TSRMLS_DC) { @@ -139,6 +143,7 @@ static void php_parsekit_parse_arginfo(zval *return_value, zend_uint num_args, z } } /* }}} */ +#endif /* {{{ php_parsekit_parse_op_array */ static void php_parsekit_parse_op_array(zval *return_value, zend_op_array *ops TSRMLS_DC) @@ -147,9 +152,10 @@ static void php_parsekit_parse_op_array(zval *return_value, zend_op_array *ops T zval *tmpzval; int i = 0; + /* TODO: Reorder / Organize */ + 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) { @@ -158,12 +164,13 @@ static void php_parsekit_parse_op_array(zval *return_value, zend_op_array *ops T add_assoc_null(return_value, "function_name"); } +#if PHP_MAJOR_VERSION >= 5 +/* 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 { add_assoc_null(return_value, "scope"); } - add_assoc_long(return_value, "fn_flags", ops->fn_flags); if (ops->prototype) { MAKE_STD_ZVAL(tmpzval); @@ -187,7 +194,7 @@ static void php_parsekit_parse_op_array(zval *return_value, zend_op_array *ops T 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); @@ -195,26 +202,63 @@ static void php_parsekit_parse_op_array(zval *return_value, zend_op_array *ops T } else { add_assoc_null(return_value, "arg_info"); } - /* End "Common" */ + 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"); + } + + add_assoc_bool(return_value, "uses_this", ops->uses_this); + 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"); + } + +#else +/* ZE1 op_array members */ + + if (ops->arg_types) { + zend_uchar *arg_types = ops->arg_types; + + MAKE_STD_ZVAL(tmpzval); + array_init(tmpzval); + while (*arg_types) { + add_next_index_long(tmpzval, (long)(*arg_types)); + arg_types++; + } + add_assoc_zval(return_value, "arg_types", tmpzval); + } else { + add_assoc_null(return_value, "arg_types"); + } + 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)); - 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); + 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); @@ -233,25 +277,6 @@ static void php_parsekit_parse_op_array(zval *return_value, zend_op_array *ops T } 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; @@ -273,24 +298,28 @@ static void php_parsekit_parse_op_array(zval *return_value, zend_op_array *ops T 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); + /* Leave this last, it simplifies readability */ + MAKE_STD_ZVAL(tmpzval); + array_init(tmpzval); + for(op = ops->opcodes, i = 0; op && i < ops->size; op++, i++) { + zval *zop; + 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); - 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"); - } } /* }}} */ @@ -341,7 +370,9 @@ static int php_parsekit_pop_functions(zval *return_value, HashTable *function_ta static int php_parsekit_parse_class_entry(zval *return_value, zend_class_entry *ce TSRMLS_DC) { zval *tmpzval; +#if PHP_MAJOR_VERSION >= 5 int i; +#endif array_init(return_value); @@ -353,8 +384,9 @@ static int php_parsekit_parse_class_entry(zval *return_value, zend_class_entry * } 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); +#if PHP_MAJOR_VERSION >= 5 +/* ZE2 class_entry members */ add_assoc_long(return_value, "ce_flags", ce->ce_flags); /* function table pop destorys entries! */ @@ -388,28 +420,6 @@ static int php_parsekit_parse_class_entry(zval *return_value, zend_class_entry * 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; @@ -474,6 +484,42 @@ static int php_parsekit_parse_class_entry(zval *return_value, zend_class_entry * add_assoc_null(return_value, "doc_comment"); } + add_assoc_long(return_value, "refcount", ce->refcount); + +#else +/* ZE1 class_entry members */ + if (ce->refcount) { + add_assoc_long(return_value, "refcount", *(ce->refcount)); + } else { + 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 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"); + } + return SUCCESS; } /* }}} */ @@ -587,7 +633,11 @@ PHP_FUNCTION(parsekit_compile_string) if (ops) { php_parsekit_common(return_value, original_num_functions, original_num_classes, ops TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 5 destroy_op_array(ops TSRMLS_CC); +#else + destroy_op_array(ops); +#endif efree(ops); } else { RETURN_FALSE; @@ -626,7 +676,11 @@ PHP_FUNCTION(parsekit_compile_file) if (ops) { php_parsekit_common(return_value, original_num_functions, original_num_classes, ops TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 5 destroy_op_array(ops TSRMLS_CC); +#else + destroy_op_array(ops); +#endif efree(ops); } else { RETURN_FALSE; @@ -634,12 +688,15 @@ PHP_FUNCTION(parsekit_compile_file) } /* }}} */ +#if PHP_MAJOR_VERSION >= 5 static ZEND_BEGIN_ARG_INFO(second_arg_force_ref, 0) ZEND_ARG_PASS_INFO(0) ZEND_ARG_PASS_INFO(1) ZEND_END_ARG_INFO() - +#else +static unsigned char second_arg_force_ref[] = { 3, BYREF_NONE, BYREF_FORCE }; +#endif /* {{{ function_entry */ function_entry parsekit_functions[] = { diff --git a/php_parsekit.h b/php_parsekit.h index a3f9f74..82d6c6f 100644 --- a/php_parsekit.h +++ b/php_parsekit.h @@ -12,7 +12,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: | + | Author: Sara Golemon | +----------------------------------------------------------------------+ */ @@ -68,7 +68,10 @@ static php_parsekit_define_list php_parsekit_function_types[] = { { ZEND_USER_FUNCTION, "ZEND_USER_FUNCTION" }, { ZEND_OVERLOADED_FUNCTION, "ZEND_OVERLOADED_FUNCTION" }, { ZEND_EVAL_CODE, "ZEND_EVAL_CODE" }, +#ifdef ZEND_OVERLOADED_FUNCTION_TEMPORARY +/* ZE2 Only */ { ZEND_OVERLOADED_FUNCTION_TEMPORARY, "ZEND_OVERLOADED_FUNCTION_TEMPORARY" }, +#endif { 0, NULL } }; @@ -157,6 +160,10 @@ static php_parsekit_define_list php_parsekit_opcode_names[] = { { ZEND_INCLUDE_OR_EVAL, "ZEND_INCLUDE_OR_EVAL" }, { ZEND_UNSET_VAR, "ZEND_UNSET_VAR" }, { ZEND_UNSET_DIM_OBJ, "ZEND_UNSET_DIM_OBJ" }, +#ifdef ZEND_ISSET_ISEMPTY +/* ZE1 Only */ + { ZEND_ISSET_ISEMPTY, "ZEND_ISSET_ISEMPTY" }, +#endif { ZEND_FE_RESET, "ZEND_FE_RESET" }, { ZEND_FE_FETCH, "ZEND_FE_FETCH" }, { ZEND_EXIT, "ZEND_EXIT" }, @@ -186,6 +193,7 @@ static php_parsekit_define_list php_parsekit_opcode_names[] = { { ZEND_EXT_NOP, "ZEND_EXT_NOP" }, { ZEND_TICKS, "ZEND_TICKS" }, { ZEND_SEND_VAR_NO_REF, "ZEND_SEND_VAR_NO_REF" }, +#if PHP_MAJOR_VERSION >= 5 { ZEND_CATCH, "ZEND_CATCH" }, { ZEND_THROW, "ZEND_THROW" }, { ZEND_FETCH_CLASS, "ZEND_FETCH_CLASS" }, @@ -214,6 +222,7 @@ static php_parsekit_define_list php_parsekit_opcode_names[] = { { ZEND_ASSIGN_DIM, "ZEND_ASSIGN_DIM" }, { ZEND_ISSET_ISEMPTY_PROP_OBJ, "ZEND_ISSET_ISEMPTY_PROP_OBJ" }, { ZEND_HANDLE_EXCEPTION, "ZEND_HANDLE_EXCEPTION" }, +#endif { 0, NULL } };