if noone objects i'm going to commit this to -HEAD (and we can start discussing it then;-)
re, tc On Fri, Aug 16, 2002 at 07:39:59PM +0200, Thies C. Arntzen wrote: > > hi, > > this patch adds the extremely useful debug_backtrace() > function to ZE1. as it's more-or-less the same > implementation as in ZE2 so it should be "fast and efficient" > enough for inclusion in 4.3 IMHO. > > it has one extra feature over the ZE2 implementation by > giving some extra information if a method was called > using :: or -> (see the 'type' attribute in the array > returned by debug_backtrace). > > zeev, andi one question: i had to comment line 1628 (just > apply the patch and see for yourself) to make the following > code work correctly (= show the class in the backtrace): > > <?php > class a { > function dump() { > var_dump(debug_backtrace()); > } > } > > $a = new a; > $a->dump(); > ?> > > (just uncomment line 1628 in the patched sources and see how > the output of debug_backtrace doesn't show the class-name for > this script any more) > > i don't think that commenting this line will have any > side-effect as EG(object).ptr will be re-initialized in 1665 > and i don't see any references to it in between. > > i'd love to have this included in 4.3.0 and i think a lot of > people would be happy as well. > > implementation: > to make this whole thing work i simply added the class_entry > to the execute_data and am pushing and popping it together > with (object).ptr. > > if this patch gets accepted i'll add an php.ini seting so > that errors and warnings will optionally have the full > call-stack. > > > comments are welcome - especially from andi & zeev. > tc > > PS: patch is against -HEAD > > -- > Thies C. Arnzten - Looking for all sorts of freelance work - just ask.. > Whishlist: http://www.amazon.de/exec/obidos/wishlist/AB9DY62QWDSZ/ref=wl_em_to > ? ext/tca_prof > Index: Zend/zend_builtin_functions.c > =================================================================== > RCS file: /repository/Zend/zend_builtin_functions.c,v > retrieving revision 1.118 > diff -u -r1.118 zend_builtin_functions.c > --- Zend/zend_builtin_functions.c 12 Jun 2002 17:02:22 -0000 1.118 > +++ Zend/zend_builtin_functions.c 16 Aug 2002 17:22:01 -0000 > @@ -65,6 +65,7 @@ > static ZEND_FUNCTION(extension_loaded); > static ZEND_FUNCTION(get_extension_funcs); > static ZEND_FUNCTION(get_defined_constants); > +static ZEND_FUNCTION(debug_backtrace); > #if ZEND_DEBUG > static ZEND_FUNCTION(zend_test_func); > #endif > @@ -116,6 +117,7 @@ > ZEND_FE(extension_loaded, NULL) > ZEND_FE(get_extension_funcs, NULL) > ZEND_FE(get_defined_constants, NULL) > + ZEND_FE(debug_backtrace, NULL) > #if ZEND_DEBUG > ZEND_FE(zend_test_func, NULL) > #endif > @@ -1133,6 +1135,69 @@ > array_init(return_value); > zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) >add_constant_info, return_value TSRMLS_CC); > } > + > +/* {{{ proto void debug_backtrace(void) > + Prints out a backtrace */ > +ZEND_FUNCTION(debug_backtrace) > +{ > + zend_execute_data *ptr; > + int lineno; > + char *function_name; > + char *filename; > + char *class_name; > + zend_uint class_name_length; > + zval *stack_frame; > + > + ptr = EG(execute_data_ptr); > + > + /* Skip debug_backtrace() itself */ > + ptr = ptr->prev_execute_data; > + > + array_init(return_value); > + > + while (ptr) { > + MAKE_STD_ZVAL(stack_frame); > + array_init(stack_frame); > + > + > +/* if (ptr->object) { > + class_name = Z_OBJCE(*ptr->object)->name; > + class_name_length = Z_OBJCE(*ptr->object)->name_length; > + } > + if (ptr->function_state.function->common.scope) { > + class_name = ptr->function_state.function->common.scope->name; > + } > +*/ > + if (ptr->ce) { > + add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", >1); > + class_name = ptr->ce->name; > + } else if (ptr->object.ptr) { > + add_assoc_string_ex(stack_frame, "type", sizeof("type"), "->", >1); > + class_name = ptr->object.ptr->value.obj.ce->name; > + > + } else { > + class_name = NULL; > + } > + > + function_name = ptr->function_state.function->common.function_name; > + > + filename = ptr->op_array->filename; > + lineno = ptr->opline->lineno; > + > + if (function_name) { > + add_assoc_string_ex(stack_frame, "function", >sizeof("function"), function_name, 1); > + } > + if (class_name) { > + add_assoc_string_ex(stack_frame, "class", sizeof("class"), >class_name, 1); > + } > + add_assoc_string_ex(stack_frame, "file", sizeof("file"), filename, 1); > + add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno); > + add_next_index_zval(return_value, stack_frame); > + > + ptr = ptr->prev_execute_data; > + } > +} > +/* }}} */ > > > /* {{{ proto bool extension_loaded(string extension_name) > Index: Zend/zend_execute.c > =================================================================== > RCS file: /repository/Zend/zend_execute.c,v > retrieving revision 1.300 > diff -u -r1.300 zend_execute.c > --- Zend/zend_execute.c 2 Aug 2002 20:21:38 -0000 1.300 > +++ Zend/zend_execute.c 16 Aug 2002 17:22:02 -0000 > @@ -1000,14 +1000,17 @@ > { > zend_execute_data execute_data; > > - EG(execute_data_ptr) = &execute_data; > - > /* Initialize execute_data */ > EX(fbc) = NULL; > + EX(ce) = NULL; > EX(object).ptr = NULL; > + EX(op_array) = op_array; > EX(Ts) = (temp_variable *) do_alloca(sizeof(temp_variable)*op_array->T); > + EX(prev_execute_data) = EG(execute_data_ptr); > EX(original_in_execution)=EG(in_execution); > > + EG(execute_data_ptr) = &execute_data; > + > EG(in_execution) = 1; > if (op_array->start_op) { > EX(opline) = op_array->start_op; > @@ -1479,7 +1482,7 @@ > HashTable *active_function_table; > zval tmp; > > - zend_ptr_stack_n_push(&EG(arg_types_stack), 2, >EX(fbc), EX(object).ptr); > + zend_ptr_stack_n_push(&EG(arg_types_stack), 3, >EX(fbc), EX(object).ptr, EX(ce)); > if (EX(opline)->extended_value & >ZEND_CTOR_CALL) { > /* constructor call */ > > @@ -1497,10 +1500,9 @@ > convert_to_string(&tmp); > function_name = &tmp; > zend_str_tolower(tmp.value.str.val, >tmp.value.str.len); > - > + EX(ce) = NULL; > > if (EX(opline)->op1.op_type != IS_UNUSED) { > if (EX(opline)->op1.op_type==IS_CONST) >{ /* used for class_name::function() */ > - zend_class_entry *ce; > zval **object_ptr_ptr; > > if >(zend_hash_find(EG(active_symbol_table), "this", sizeof("this"), (void **) >&object_ptr_ptr)==FAILURE) { > @@ -1511,10 +1513,10 @@ > EX(object).ptr = >*object_ptr_ptr; > >EX(object).ptr->refcount++; /* For this pointer */ > } > - if >(zend_hash_find(EG(class_table), EX(opline)->op1.u.constant.value.str.val, >EX(opline)->op1.u.constant.value.str.len+1, (void **) &ce)==FAILURE) { /* class >doesn't exist */ > + if >(zend_hash_find(EG(class_table), EX(opline)->op1.u.constant.value.str.val, >EX(opline)->op1.u.constant.value.str.len+1, (void **) &EX(ce))==FAILURE) { /* class >doesn't exist */ > zend_error(E_ERROR, >"Undefined class name '%s'", EX(opline)->op1.u.constant.value.str.val); > } > - active_function_table = >&ce->function_table; > + active_function_table = >&EX(ce)->function_table; > } else { /* used for member function >calls */ > EX(object).ptr = >_get_object_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1) TSRMLS_CC); > > @@ -1572,8 +1574,9 @@ > zend_error(E_ERROR, "Unknown function: > %s()\n", fname->value.str.val); > } > FREE_OP(EX(Ts), &EX(opline)->op1, >EG(free_op1)); > - zend_ptr_stack_push(&EG(arg_types_stack), >EX(object).ptr); > + zend_ptr_stack_n_push(&EG(arg_types_stack), 2, >EX(object).ptr, EX(ce)); > EX(object).ptr = NULL; > + EX(ce) = NULL; > goto do_fcall_common; > } > do_fcall_common: > @@ -1623,7 +1626,7 @@ > zend_error(E_WARNING, >"Problem with method call - please report this bug"); > } > *this_ptr = EX(object).ptr; > - EX(object).ptr = NULL; > + /* EX(object).ptr = NULL; */ > } > original_return_value = >EG(return_value_ptr_ptr); > EG(return_value_ptr_ptr) = >EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr; > @@ -1659,9 +1662,9 @@ > } > } > if (EX(opline)->opcode == >ZEND_DO_FCALL_BY_NAME) { > - >zend_ptr_stack_n_pop(&EG(arg_types_stack), 2, &EX(object).ptr, &EX(fbc)); > + >zend_ptr_stack_n_pop(&EG(arg_types_stack), 3, &EX(ce), &EX(object).ptr, &EX(fbc)); > } else { > - EX(object).ptr = >zend_ptr_stack_pop(&EG(arg_types_stack)); > + >zend_ptr_stack_n_pop(&EG(arg_types_stack), 2, &EX(ce), &EX(object).ptr); > } > EX(function_state).function = (zend_function >*) op_array; > EG(function_state_ptr) = &EX(function_state); > @@ -1709,6 +1712,7 @@ > } > free_alloca(EX(Ts)); > EG(in_execution) = EX(original_in_execution); > + EG(execute_data_ptr) = EX(prev_execute_data); > return; > } > break; > Index: Zend/zend_execute_globals.h > =================================================================== > RCS file: /repository/Zend/zend_execute_globals.h,v > retrieving revision 1.1 > diff -u -r1.1 zend_execute_globals.h > --- Zend/zend_execute_globals.h 16 May 2002 04:28:18 -0000 1.1 > +++ Zend/zend_execute_globals.h 16 Aug 2002 17:22:02 -0000 > @@ -55,9 +55,12 @@ > zend_op *opline; > zend_function_state function_state; > zend_function *fbc; /* Function Being Called */ > + zend_class_entry *ce; > object_info object; > temp_variable *Ts; > zend_bool original_in_execution; > + zend_op_array *op_array; > + struct _zend_execute_data *prev_execute_data; > } zend_execute_data; > > #endif > > -- > PHP Development Mailing List <http://www.php.net/> > To unsubscribe, visit: http://www.php.net/unsub.php -- Thies C. Arnzten - Looking for all sorts of freelance work - just ask.. Whishlist: http://www.amazon.de/exec/obidos/wishlist/AB9DY62QWDSZ -- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php