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

Reply via email to