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