mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
- MFZE1
This commit is contained in:
parent
e50dc16b21
commit
b6ecd6704c
64
Zend/zend.c
64
Zend/zend.c
@ -134,6 +134,34 @@ static void print_hash(HashTable *ht, int indent)
|
||||
ZEND_PUTS(")\n");
|
||||
}
|
||||
|
||||
static void print_flat_hash(HashTable *ht)
|
||||
{
|
||||
zval **tmp;
|
||||
char *string_key;
|
||||
HashPosition iterator;
|
||||
ulong num_key;
|
||||
uint str_len;
|
||||
int i = 0;
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(ht, &iterator);
|
||||
while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) {
|
||||
if (i++ > 0) {
|
||||
ZEND_PUTS(",");
|
||||
}
|
||||
ZEND_PUTS("[");
|
||||
switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
|
||||
case HASH_KEY_IS_STRING:
|
||||
ZEND_PUTS(string_key);
|
||||
break;
|
||||
case HASH_KEY_IS_LONG:
|
||||
zend_printf("%ld", num_key);
|
||||
break;
|
||||
}
|
||||
ZEND_PUTS("] => ");
|
||||
zend_print_flat_zval_r(*tmp);
|
||||
zend_hash_move_forward_ex(ht, &iterator);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy)
|
||||
{
|
||||
@ -216,6 +244,42 @@ ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int in
|
||||
return expr->value.str.len;
|
||||
}
|
||||
|
||||
ZEND_API void zend_print_flat_zval_r(zval *expr)
|
||||
{
|
||||
zend_write_func_t write_func = zend_write;
|
||||
|
||||
switch (expr->type) {
|
||||
case IS_ARRAY:
|
||||
ZEND_PUTS("Array (");
|
||||
if (++expr->value.ht->nApplyCount>1) {
|
||||
ZEND_PUTS(" *RECURSION*");
|
||||
expr->value.ht->nApplyCount--;
|
||||
return;
|
||||
}
|
||||
print_flat_hash(expr->value.ht);
|
||||
ZEND_PUTS(")");
|
||||
expr->value.ht->nApplyCount--;
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
{
|
||||
zend_object *object = Z_OBJ_P(expr);
|
||||
|
||||
if (++object->properties->nApplyCount>1) {
|
||||
ZEND_PUTS(" *RECURSION*");
|
||||
object->properties->nApplyCount--;
|
||||
return;
|
||||
}
|
||||
zend_printf("%s Object (", object->ce->name);
|
||||
print_flat_hash(object->properties);
|
||||
ZEND_PUTS(")");
|
||||
object->properties->nApplyCount--;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
zend_print_variable(expr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_print_zval_r(zval *expr, int indent)
|
||||
{
|
||||
|
@ -431,6 +431,7 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
|
||||
ZEND_API int zend_print_zval(zval *expr, int indent);
|
||||
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent);
|
||||
ZEND_API void zend_print_zval_r(zval *expr, int indent);
|
||||
ZEND_API void zend_print_flat_zval_r(zval *expr);
|
||||
ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent);
|
||||
ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ...);
|
||||
|
||||
|
@ -70,6 +70,7 @@ static ZEND_FUNCTION(extension_loaded);
|
||||
static ZEND_FUNCTION(get_extension_funcs);
|
||||
static ZEND_FUNCTION(get_defined_constants);
|
||||
static ZEND_FUNCTION(debug_backtrace);
|
||||
static ZEND_FUNCTION(debug_print_backtrace);
|
||||
#if ZEND_DEBUG
|
||||
static ZEND_FUNCTION(zend_test_func);
|
||||
#ifdef ZTS
|
||||
@ -129,6 +130,7 @@ static zend_function_entry builtin_functions[] = {
|
||||
ZEND_FE(get_extension_funcs, NULL)
|
||||
ZEND_FE(get_defined_constants, NULL)
|
||||
ZEND_FE(debug_backtrace, NULL)
|
||||
ZEND_FE(debug_print_backtrace, NULL)
|
||||
#if ZEND_DEBUG
|
||||
ZEND_FE(zend_test_func, NULL)
|
||||
#ifdef ZTS
|
||||
@ -1296,6 +1298,143 @@ static zval *debug_backtrace_get_args(void ***curpos TSRMLS_DC) {
|
||||
return arg_array;
|
||||
}
|
||||
|
||||
void debug_print_backtrace_args(zval *arg_array)
|
||||
{
|
||||
zval **tmp;
|
||||
HashPosition iterator;
|
||||
int i = 0;
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(arg_array->value.ht, &iterator);
|
||||
while (zend_hash_get_current_data_ex(arg_array->value.ht, (void **) &tmp, &iterator) == SUCCESS) {
|
||||
if (i++) {
|
||||
ZEND_PUTS(", ");
|
||||
}
|
||||
zend_print_flat_zval_r(*tmp);
|
||||
zend_hash_move_forward_ex(arg_array->value.ht, &iterator);
|
||||
}
|
||||
}
|
||||
|
||||
/* {{{ proto void debug_print_backtrace(void)
|
||||
ZEND_FUNCTION(debug_print_backtrace)
|
||||
{
|
||||
zend_execute_data *ptr;
|
||||
int lineno;
|
||||
char *function_name;
|
||||
char *filename;
|
||||
char *class_name;
|
||||
char *call_type;
|
||||
char *include_filename = NULL;
|
||||
zval *arg_array;
|
||||
void **cur_arg_pos = EG(argument_stack).top_element;
|
||||
void **args = cur_arg_pos;
|
||||
int arg_stack_consistent = 0;
|
||||
int frames_on_stack = 0;
|
||||
int indent;
|
||||
|
||||
if (ZEND_NUM_ARGS()) {
|
||||
ZEND_WRONG_PARAM_COUNT();
|
||||
}
|
||||
|
||||
while (--args >= EG(argument_stack).elements) {
|
||||
if (*args--) {
|
||||
break;
|
||||
}
|
||||
args -= *(ulong*)args;
|
||||
frames_on_stack++;
|
||||
|
||||
if (args == EG(argument_stack).elements) {
|
||||
arg_stack_consistent = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = EG(current_execute_data);
|
||||
|
||||
/* skip debug_backtrace() */
|
||||
ptr = ptr->prev_execute_data;
|
||||
cur_arg_pos -= 2;
|
||||
frames_on_stack--;
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
while (ptr) {
|
||||
if (ptr->op_array) {
|
||||
filename = ptr->op_array->filename;
|
||||
lineno = ptr->opline->lineno;
|
||||
} else {
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
function_name = ptr->function_state.function->common.function_name;
|
||||
|
||||
if (function_name) {
|
||||
if (ptr->object) {
|
||||
class_name = Z_OBJCE(*ptr->object)->name;
|
||||
call_type = "->";
|
||||
} else if (ptr->function_state.function->common.scope) {
|
||||
class_name = ptr->function_state.function->common.scope->name;
|
||||
call_type = "::";
|
||||
} else {
|
||||
class_name = NULL;
|
||||
call_type = NULL;
|
||||
}
|
||||
if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) {
|
||||
if (arg_stack_consistent && (frames_on_stack > 0)) {
|
||||
arg_array = debug_backtrace_get_args(&cur_arg_pos TSRMLS_CC);
|
||||
frames_on_stack--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
|
||||
zend_bool build_filename_arg = 1;
|
||||
|
||||
switch (ptr->opline->op2.u.constant.value.lval) {
|
||||
case ZEND_EVAL:
|
||||
function_name = "eval";
|
||||
build_filename_arg = 0;
|
||||
break;
|
||||
case ZEND_INCLUDE:
|
||||
function_name = "include";
|
||||
break;
|
||||
case ZEND_REQUIRE:
|
||||
function_name = "require";
|
||||
break;
|
||||
case ZEND_INCLUDE_ONCE:
|
||||
function_name = "include_once";
|
||||
break;
|
||||
case ZEND_REQUIRE_ONCE:
|
||||
function_name = "require_once";
|
||||
break;
|
||||
default:
|
||||
/* this can actually happen if you use debug_backtrace() in your error_handler and
|
||||
* you're in the top-scope */
|
||||
function_name = "unknown";
|
||||
build_filename_arg = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (build_filename_arg && include_filename) {
|
||||
MAKE_STD_ZVAL(arg_array);
|
||||
array_init(arg_array);
|
||||
add_next_index_string(arg_array, include_filename, 1);
|
||||
}
|
||||
}
|
||||
zend_printf("#%-2d ", indent);
|
||||
if (class_name) {
|
||||
ZEND_PUTS(class_name);
|
||||
ZEND_PUTS(call_type);
|
||||
}
|
||||
zend_printf("%s(", function_name?function_name:"main");
|
||||
debug_print_backtrace_args(arg_array);
|
||||
ZVAL_DELREF(arg_array);
|
||||
zend_printf(") called at [%s:%d]\n", filename, lineno);
|
||||
include_filename = filename;
|
||||
ptr = ptr->prev_execute_data;
|
||||
++indent;
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ proto void debug_backtrace(void)
|
||||
Prints out a backtrace */
|
||||
ZEND_FUNCTION(debug_backtrace)
|
||||
|
Loading…
Reference in New Issue
Block a user