Skip to content

Commit

Permalink
Added support for generators.
Browse files Browse the repository at this point in the history
  • Loading branch information
derickr committed Nov 24, 2012
1 parent 8576032 commit e773605
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 10 deletions.
59 changes: 59 additions & 0 deletions tests/bug00905.phpt
@@ -0,0 +1,59 @@
--TEST--
Test for bug #905: Tracing for generators.
--SKIPIF--
<?php if (!version_compare(phpversion(), "5.5", '>=')) echo "skip >= PHP 5.5 needed\n"; ?>
--INI--
xdebug.enable=1
xdebug.auto_trace=0
xdebug.collect_params=3
xdebug.collect_return=1
xdebug.collect_assignments=0
xdebug.auto_profile=0
xdebug.profiler_enable=0
xdebug.show_mem_delta=0
xdebug.trace_format=0
--FILE--
<?php
$tf = xdebug_start_trace('/tmp/'. uniqid('xdt', TRUE));

function gen() {
yield 'a';
yield 'b';
yield 'key' => 'c';
yield 'd';
yield 10 => 'e';
yield 'f';
}

foreach (gen() as $key => $value) {
echo $key, ' => ', $value, "\n";
}

xdebug_stop_trace();
echo file_get_contents($tf);
unlink($tf);
?>
--EXPECTF--
0 => a
1 => b
key => c
2 => d
10 => e
11 => f
TRACE START [%d-%d-%d %d:%d:%d]
%w%f %w%d -> gen() %sbug00905.php:13
>=> (0 => 'a')
%w%f %w%d -> gen() %sbug00905.php:13
>=> (1 => 'b')
%w%f %w%d -> gen() %sbug00905.php:13
>=> ('key' => 'c')
%w%f %w%d -> gen() %sbug00905.php:13
>=> (2 => 'd')
%w%f %w%d -> gen() %sbug00905.php:13
>=> (10 => 'e')
%w%f %w%d -> gen() %sbug00905.php:13
>=> (11 => 'f')
%w%f %w%d -> gen() %sbug00905.php:13
%w%f %w%d -> xdebug_stop_trace() %sbug00905.php:17
%w%f %w%d
TRACE END [%d-%d-%d %d:%d:%d]
11 changes: 10 additions & 1 deletion xdebug.c
Expand Up @@ -1444,7 +1444,16 @@ void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
/* Store return value in the trace file */ /* Store return value in the trace file */
if (XG(collect_return) && do_return && XG(do_trace) && XG(trace_file)) { if (XG(collect_return) && do_return && XG(do_trace) && XG(trace_file)) {
if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
char* t = xdebug_return_trace_stack_retval(fse, *EG(return_value_ptr_ptr) TSRMLS_CC); char *t;
#if PHP_VERSION_ID >= 50500
if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
t = xdebug_return_trace_stack_generator_retval(fse, (zend_generator *) EG(return_value_ptr_ptr) TSRMLS_CC);
} else {
t = xdebug_return_trace_stack_retval(fse, *EG(return_value_ptr_ptr) TSRMLS_CC);
}
#else
t = xdebug_return_trace_stack_retval(fse, *EG(return_value_ptr_ptr) TSRMLS_CC);
#endif
fprintf(XG(trace_file), "%s", t); fprintf(XG(trace_file), "%s", t);
fflush(XG(trace_file)); fflush(XG(trace_file));
xdfree(t); xdfree(t);
Expand Down
4 changes: 4 additions & 0 deletions xdebug_private.h
Expand Up @@ -27,6 +27,10 @@
#include "zend_constants.h" #include "zend_constants.h"
#include "zend_extensions.h" #include "zend_extensions.h"
#include "zend_exceptions.h" #include "zend_exceptions.h"
#if PHP_VERSION_ID >= 50500
#include "zend_generators.h"
#endif
#include "zend_exceptions.h"
#include "zend_vm.h" #include "zend_vm.h"
#include "zend_hash.h" #include "zend_hash.h"
#include "xdebug_hash.h" #include "xdebug_hash.h"
Expand Down
56 changes: 47 additions & 9 deletions xdebug_tracing.c
Expand Up @@ -93,24 +93,30 @@ char* xdebug_return_trace_assignment(function_stack_entry *i, char *varname, zva
return str.d; return str.d;
} }


char* xdebug_return_trace_stack_retval(function_stack_entry* i, zval* retval TSRMLS_DC) static void xdebug_return_trace_stack_common(xdebug_str *str, function_stack_entry *i TSRMLS_DC)
{ {
int j = 0; /* Counter */ int j = 0; /* Counter */

xdebug_str_addl(str, " ", 20, 0);
if (XG(show_mem_delta)) {
xdebug_str_addl(str, " ", 8, 0);
}
for (j = 0; j < i->level; j++) {
xdebug_str_addl(str, " ", 2, 0);
}
xdebug_str_addl(str, " >=> ", 7, 0);
}

char* xdebug_return_trace_stack_retval(function_stack_entry* i, zval* retval TSRMLS_DC)
{
xdebug_str str = {0, 0, NULL}; xdebug_str str = {0, 0, NULL};
char *tmp_value; char *tmp_value;


if (XG(trace_format) != 0) { if (XG(trace_format) != 0) {
return xdstrdup(""); return xdstrdup("");
} }


xdebug_str_addl(&str, " ", 20, 0); xdebug_return_trace_stack_common(&str, i TSRMLS_CC);
if (XG(show_mem_delta)) {
xdebug_str_addl(&str, " ", 8, 0);
}
for (j = 0; j < i->level; j++) {
xdebug_str_addl(&str, " ", 2, 0);
}
xdebug_str_addl(&str, " >=> ", 7, 0);


tmp_value = xdebug_get_zval_value(retval, 0, NULL); tmp_value = xdebug_get_zval_value(retval, 0, NULL);
if (tmp_value) { if (tmp_value) {
Expand All @@ -121,6 +127,38 @@ char* xdebug_return_trace_stack_retval(function_stack_entry* i, zval* retval TSR
return str.d; return str.d;
} }


#if PHP_VERSION_ID >= 50500
char* xdebug_return_trace_stack_generator_retval(function_stack_entry* i, zend_generator* generator TSRMLS_DC)
{
xdebug_str str = {0, 0, NULL};
char *tmp_value = NULL;

if (XG(trace_format) != 0) {
return xdstrdup("");
}

/* Generator key */
tmp_value = xdebug_get_zval_value(generator->key, 0, NULL);
if (tmp_value) {
xdebug_return_trace_stack_common(&str, i TSRMLS_CC);

xdebug_str_addl(&str, "(", 1, 0);
xdebug_str_add(&str, tmp_value, 1);
xdebug_str_addl(&str, " => ", 4, 0);

tmp_value = xdebug_get_zval_value(generator->value, 0, NULL);
if (tmp_value) {
xdebug_str_add(&str, tmp_value, 1);
}
xdebug_str_addl(&str, ")", 1, 0);
xdebug_str_addl(&str, "\n", 2, 0);
return str.d;
} else {
return xdstrdup("");
}
}
#endif

static char* return_trace_stack_frame_begin_normal(function_stack_entry* i TSRMLS_DC) static char* return_trace_stack_frame_begin_normal(function_stack_entry* i TSRMLS_DC)
{ {
int c = 0; /* Comma flag */ int c = 0; /* Comma flag */
Expand Down
3 changes: 3 additions & 0 deletions xdebug_tracing.h
Expand Up @@ -20,6 +20,9 @@
#define XDEBUG_TRACING_H #define XDEBUG_TRACING_H


char* xdebug_return_trace_stack_retval(function_stack_entry* i, zval* retval TSRMLS_DC); char* xdebug_return_trace_stack_retval(function_stack_entry* i, zval* retval TSRMLS_DC);
#if PHP_VERSION_ID >= 50500
char* xdebug_return_trace_stack_generator_retval(function_stack_entry* i, zend_generator* generator TSRMLS_DC);
#endif
char* xdebug_return_trace_assignment(function_stack_entry *i, char *varname, zval *retval, char *op, char *file, int fileno TSRMLS_DC); char* xdebug_return_trace_assignment(function_stack_entry *i, char *varname, zval *retval, char *op, char *file, int fileno TSRMLS_DC);


void xdebug_trace_function_begin(function_stack_entry *fse, int function_nr TSRMLS_DC); void xdebug_trace_function_begin(function_stack_entry *fse, int function_nr TSRMLS_DC);
Expand Down

0 comments on commit e773605

Please sign in to comment.