cvs: Zend / zend.c zend.h zend_builtin_functions.c

From: Date: Sat, 30 Nov 2002 10:51:56 +0000
Subject: cvs: Zend / zend.c zend.h zend_builtin_functions.c
Groups: php.zend-engine.cvs 
Request: Send a blank email to php-zend-engine-cvs+get-673@lists.php.net to get a copy of this message
andi Sat Nov 30 05:51:56 2002 EDT Modified files: /Zend zend.c zend.h zend_builtin_functions.c Log: - debug_print_backtrace (by George Schlossnagle <george@omniti.com>) Index: Zend/zend.c diff -u Zend/zend.c:1.163 Zend/zend.c:1.164 --- Zend/zend.c:1.163 Sun Nov 17 08:26:36 2002 +++ Zend/zend.c Sat Nov 30 05:51:56 2002 @@ -138,6 +138,35 @@ } +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) { if (expr->type==IS_STRING) { @@ -215,6 +244,43 @@ } +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) { zend_print_zval_r_ex(zend_write, expr, indent); @@ -253,6 +319,7 @@ break; } } + static FILE *zend_fopen_wrapper(const char *filename, char **opened_path) Index: Zend/zend.h diff -u Zend/zend.h:1.166 Zend/zend.h:1.167 --- Zend/zend.h:1.166 Sun Nov 17 08:26:36 2002 +++ Zend/zend.h Sat Nov 30 05:51:56 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend.h,v 1.166 2002/11/17 13:26:36 zeev Exp $ */ +/* $Id: zend.h,v 1.167 2002/11/30 10:51:56 andi Exp $ */ #ifndef ZEND_H #define ZEND_H @@ -383,6 +383,7 @@ 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, ...); Index: Zend/zend_builtin_functions.c diff -u Zend/zend_builtin_functions.c:1.127 Zend/zend_builtin_functions.c:1.128 --- Zend/zend_builtin_functions.c:1.127 Wed Nov 27 15:11:39 2002 +++ Zend/zend_builtin_functions.c Sat Nov 30 05:51:56 2002 @@ -68,6 +68,7 @@ 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); #endif @@ -122,6 +123,7 @@ 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) #endif @@ -1171,6 +1173,151 @@ add_next_index_zval(arg_array, *arg); } 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_backtrace(void) + Prints out a backtrace */ +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 *stack_frame; + 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 = 0; + int i; + + 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->ce) { + class_name = ptr->ce->name; + call_type = "::"; + } else if (ptr->object.ptr) { + class_name = ptr->object.ptr->value.obj.ce->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); + /* include_filename always points to the last filename of the last last called-fuction. + if we have called include in the frame above - this is the file we have included. + */ + + 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)

« previous php.zend-engine.cvs (#673) next »