diff --git a/config.m4 b/config.m4
index 4d4d95159..7c7ec07a1 100644
--- a/config.m4
+++ b/config.m4
@@ -26,7 +26,7 @@ dnl Check for new current_execute_data field in zend_executor_globals
CPPFLAGS=$old_CPPFLAGS
- PHP_NEW_EXTENSION(xdebug, xdebug.c xdebug_branch_info.c xdebug_code_coverage.c xdebug_com.c xdebug_compat.c xdebug_handler_dbgp.c xdebug_handlers.c xdebug_llist.c xdebug_hash.c xdebug_private.c xdebug_profiler.c xdebug_set.c xdebug_stack.c xdebug_str.c xdebug_superglobals.c xdebug_tracing.c xdebug_var.c xdebug_xml.c usefulstuff.c, $ext_shared,,,,yes)
+ PHP_NEW_EXTENSION(xdebug, xdebug.c xdebug_branch_info.c xdebug_code_coverage.c xdebug_com.c xdebug_compat.c xdebug_handler_dbgp.c xdebug_handlers.c xdebug_llist.c xdebug_hash.c xdebug_private.c xdebug_profiler.c xdebug_set.c xdebug_stack.c xdebug_str.c xdebug_superglobals.c xdebug_tracing.c xdebug_trace_textual.c xdebug_trace_computerized.c xdebug_trace_html.c xdebug_var.c xdebug_xml.c usefulstuff.c, $ext_shared,,,,yes)
PHP_SUBST(XDEBUG_SHARED_LIBADD)
PHP_ADD_MAKEFILE_FRAGMENT
fi
diff --git a/config.w32 b/config.w32
index 4b8f8eea2..4dfe1b680 100644
--- a/config.w32
+++ b/config.w32
@@ -4,6 +4,6 @@
ARG_WITH("xdebug", "Xdebug support", "no");
if (PHP_XDEBUG == "yes") {
- EXTENSION("xdebug", "xdebug.c xdebug_branch_info.c xdebug_code_coverage.c xdebug_com.c xdebug_compat.c xdebug_handler_dbgp.c xdebug_handlers.c xdebug_llist.c xdebug_hash.c xdebug_private.c xdebug_profiler.c xdebug_set.c xdebug_stack.c xdebug_str.c xdebug_superglobals.c xdebug_tracing.c xdebug_var.c xdebug_xml.c usefulstuff.c");
+ EXTENSION("xdebug", "xdebug.c xdebug_branch_info.c xdebug_code_coverage.c xdebug_com.c xdebug_compat.c xdebug_handler_dbgp.c xdebug_handlers.c xdebug_llist.c xdebug_hash.c xdebug_private.c xdebug_profiler.c xdebug_set.c xdebug_stack.c xdebug_str.c xdebug_superglobals.c xdebug_tracing.c xdebug_trace_textual.c xdebug_trace_computerized.c xdebug_trace_html.c xdebug_var.c xdebug_xml.c usefulstuff.c");
AC_DEFINE("HAVE_XDEBUG", 1, "Xdebug support");
}
diff --git a/package.xml b/package.xml
index 3a52f87b1..19fce00eb 100644
--- a/package.xml
+++ b/package.xml
@@ -177,6 +177,12 @@ Tue, May 08, 2012 - xdebug 2.2.0
+
+
+
+
+
+
diff --git a/php_xdebug.h b/php_xdebug.h
index ba5c2d96a..efe8770ca 100644
--- a/php_xdebug.h
+++ b/php_xdebug.h
@@ -176,7 +176,9 @@ ZEND_BEGIN_MODULE_GLOBALS(xdebug)
void (*orig_var_dump_func)(INTERNAL_FUNCTION_PARAMETERS);
void (*orig_set_time_limit_func)(INTERNAL_FUNCTION_PARAMETERS);
- FILE *trace_file;
+ xdebug_trace_handler_t *trace_handler;
+ void *trace_context;
+
zend_bool do_trace;
zend_bool auto_trace;
zend_bool trace_enable_trigger;
@@ -184,7 +186,7 @@ ZEND_BEGIN_MODULE_GLOBALS(xdebug)
char *trace_output_name;
long trace_options;
long trace_format;
- char *tracefile_name;
+ //char *tracefile_name;
char *last_exception_trace;
char *last_eval_statement;
diff --git a/tests/bug00538-2.phpt b/tests/bug00538-2.phpt
index 03b729cc3..063e2aa3f 100644
--- a/tests/bug00538-2.phpt
+++ b/tests/bug00538-2.phpt
@@ -48,7 +48,7 @@ array(2) {
["params"]=>
array(3) {
["param1"]=>
- string(%d) "'%sxdebug'"
+ string(%d) "'%s'"
["param2"]=>
string(16) "'candena\\a\\nb'"
["param3"]=>
diff --git a/tests/stacktrace_variadic_html_0.phpt b/tests/stacktrace_variadic_html_0.phpt
index 16b224c12..57c0e7844 100644
--- a/tests/stacktrace_variadic_html_0.phpt
+++ b/tests/stacktrace_variadic_html_0.phpt
@@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 );
( ! ) Notice: notice in %sstacktrace_variadic_html_0.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_0.php:0 |
-2 | %f | %d | foo( ) | ../stacktrace_variadic_html_0.php:7 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_0.php:0 |
+2 | %f | %d | foo( ) | .../stacktrace_variadic_html_0.php:7 |
3 | %f | %d | trigger_error
-( ) | ../stacktrace_variadic_html_0.php:4 |
+( ).../stacktrace_variadic_html_0.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_0.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_0.php:0 |
-2 | %f | %d | foo( ) | ../stacktrace_variadic_html_0.php:8 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_0.php:0 |
+2 | %f | %d | foo( ) | .../stacktrace_variadic_html_0.php:8 |
3 | %f | %d | trigger_error
-( ) | ../stacktrace_variadic_html_0.php:4 |
+( ).../stacktrace_variadic_html_0.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_0.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_0.php:0 |
-2 | %f | %d | foo( ) | ../stacktrace_variadic_html_0.php:9 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_0.php:0 |
+2 | %f | %d | foo( ) | .../stacktrace_variadic_html_0.php:9 |
3 | %f | %d | trigger_error
-( ) | ../stacktrace_variadic_html_0.php:4 |
+( ).../stacktrace_variadic_html_0.php:4 |
diff --git a/tests/stacktrace_variadic_html_1.phpt b/tests/stacktrace_variadic_html_1.phpt
index 03096fcdf..0df64bafa 100644
--- a/tests/stacktrace_variadic_html_1.phpt
+++ b/tests/stacktrace_variadic_html_1.phpt
@@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 );
( ! ) Notice: notice in %sstacktrace_variadic_html_1.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_1.php:0 |
-2 | %f | %d | foo( long, ??? ) | ../stacktrace_variadic_html_1.php:7 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_1.php:0 |
+2 | %f | %d | foo( long, ??? ) | .../stacktrace_variadic_html_1.php:7 |
3 | %f | %d | trigger_error
-( string(6) ) | ../stacktrace_variadic_html_1.php:4 |
+( string(6) ).../stacktrace_variadic_html_1.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_1.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_1.php:0 |
-2 | %f | %d | foo( long, ...variadic(bool) ) | ../stacktrace_variadic_html_1.php:8 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_1.php:0 |
+2 | %f | %d | foo( long, ...variadic(bool) ) | .../stacktrace_variadic_html_1.php:8 |
3 | %f | %d | trigger_error
-( string(6) ) | ../stacktrace_variadic_html_1.php:4 |
+( string(6) ).../stacktrace_variadic_html_1.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_1.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_1.php:0 |
-2 | %f | %d | foo( string(3), ...variadic(string(3), double) ) | ../stacktrace_variadic_html_1.php:9 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_1.php:0 |
+2 | %f | %d | foo( string(3), ...variadic(string(3), double) ) | .../stacktrace_variadic_html_1.php:9 |
3 | %f | %d | trigger_error
-( string(6) ) | ../stacktrace_variadic_html_1.php:4 |
+( string(6) ).../stacktrace_variadic_html_1.php:4 |
diff --git a/tests/stacktrace_variadic_html_2.phpt b/tests/stacktrace_variadic_html_2.phpt
index bcf1c3b60..9c71c2929 100644
--- a/tests/stacktrace_variadic_html_2.phpt
+++ b/tests/stacktrace_variadic_html_2.phpt
@@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 );
( ! ) Notice: notice in %sstacktrace_variadic_html_2.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_2.php:0 |
-2 | %f | %d | foo( long, ??? ) | ../stacktrace_variadic_html_2.php:7 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_2.php:0 |
+2 | %f | %d | foo( long, ??? ) | .../stacktrace_variadic_html_2.php:7 |
3 | %f | %d | trigger_error
-( string(6) ) | ../stacktrace_variadic_html_2.php:4 |
+( string(6) ).../stacktrace_variadic_html_2.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_2.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_2.php:0 |
-2 | %f | %d | foo( long, ...variadic(bool) ) | ../stacktrace_variadic_html_2.php:8 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_2.php:0 |
+2 | %f | %d | foo( long, ...variadic(bool) ) | .../stacktrace_variadic_html_2.php:8 |
3 | %f | %d | trigger_error
-( string(6) ) | ../stacktrace_variadic_html_2.php:4 |
+( string(6) ).../stacktrace_variadic_html_2.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_2.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_2.php:0 |
-2 | %f | %d | foo( string(3), ...variadic(string(3), double) ) | ../stacktrace_variadic_html_2.php:9 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_2.php:0 |
+2 | %f | %d | foo( string(3), ...variadic(string(3), double) ) | .../stacktrace_variadic_html_2.php:9 |
3 | %f | %d | trigger_error
-( string(6) ) | ../stacktrace_variadic_html_2.php:4 |
+( string(6) ).../stacktrace_variadic_html_2.php:4 |
diff --git a/tests/stacktrace_variadic_html_3.phpt b/tests/stacktrace_variadic_html_3.phpt
index b5de17813..9590ab661 100644
--- a/tests/stacktrace_variadic_html_3.phpt
+++ b/tests/stacktrace_variadic_html_3.phpt
@@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 );
( ! ) Notice: notice in %sstacktrace_variadic_html_3.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_3.php:0 |
-2 | %f | %d | foo( 42, ??? ) | ../stacktrace_variadic_html_3.php:7 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_3.php:0 |
+2 | %f | %d | foo( 42, ??? ) | .../stacktrace_variadic_html_3.php:7 |
3 | %f | %d | trigger_error
-( 'notice' ) | ../stacktrace_variadic_html_3.php:4 |
+( 'notice' ).../stacktrace_variadic_html_3.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_3.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_3.php:0 |
-2 | %f | %d | foo( 1, ...variadic(FALSE) ) | ../stacktrace_variadic_html_3.php:8 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_3.php:0 |
+2 | %f | %d | foo( 1, ...variadic(FALSE) ) | .../stacktrace_variadic_html_3.php:8 |
3 | %f | %d | trigger_error
-( 'notice' ) | ../stacktrace_variadic_html_3.php:4 |
+( 'notice' ).../stacktrace_variadic_html_3.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_3.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_3.php:0 |
-2 | %f | %d | foo( 'foo', ...variadic('bar', 3.1415) ) | ../stacktrace_variadic_html_3.php:9 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_3.php:0 |
+2 | %f | %d | foo( 'foo', ...variadic('bar', 3.1415) ) | .../stacktrace_variadic_html_3.php:9 |
3 | %f | %d | trigger_error
-( 'notice' ) | ../stacktrace_variadic_html_3.php:4 |
+( 'notice' ).../stacktrace_variadic_html_3.php:4 |
diff --git a/tests/stacktrace_variadic_html_4.phpt b/tests/stacktrace_variadic_html_4.phpt
index afd09c964..d057ea896 100644
--- a/tests/stacktrace_variadic_html_4.phpt
+++ b/tests/stacktrace_variadic_html_4.phpt
@@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 );
( ! ) Notice: notice in %sstacktrace_variadic_html_4.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_4.php:0 |
-2 | %f | %d | foo( $a = 42, $b = ??? ) | ../stacktrace_variadic_html_4.php:7 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_4.php:0 |
+2 | %f | %d | foo( $a = 42, $b = ??? ) | .../stacktrace_variadic_html_4.php:7 |
3 | %f | %d | trigger_error
-( 'notice' ) | ../stacktrace_variadic_html_4.php:4 |
+( 'notice' ).../stacktrace_variadic_html_4.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_4.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_4.php:0 |
-2 | %f | %d | foo( $a = 1, ...$b = variadic(FALSE) ) | ../stacktrace_variadic_html_4.php:8 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_4.php:0 |
+2 | %f | %d | foo( $a = 1, ...$b = variadic(FALSE) ) | .../stacktrace_variadic_html_4.php:8 |
3 | %f | %d | trigger_error
-( 'notice' ) | ../stacktrace_variadic_html_4.php:4 |
+( 'notice' ).../stacktrace_variadic_html_4.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_4.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_4.php:0 |
-2 | %f | %d | foo( $a = 'foo', ...$b = variadic('bar', 3.1415) ) | ../stacktrace_variadic_html_4.php:9 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_4.php:0 |
+2 | %f | %d | foo( $a = 'foo', ...$b = variadic('bar', 3.1415) ) | .../stacktrace_variadic_html_4.php:9 |
3 | %f | %d | trigger_error
-( 'notice' ) | ../stacktrace_variadic_html_4.php:4 |
+( 'notice' ).../stacktrace_variadic_html_4.php:4 |
diff --git a/tests/stacktrace_variadic_html_5.phpt b/tests/stacktrace_variadic_html_5.phpt
index 333a955e2..88475de4e 100644
--- a/tests/stacktrace_variadic_html_5.phpt
+++ b/tests/stacktrace_variadic_html_5.phpt
@@ -32,28 +32,28 @@ foo( "foo", "bar", 3.1415 );
( ! ) Notice: notice in %sstacktrace_variadic_html_5.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_5.php:0 |
-2 | %f | %d | foo( aTo0Mjs=, ??? ) | ../stacktrace_variadic_html_5.php:7 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_5.php:0 |
+2 | %f | %d | foo( aTo0Mjs=, ??? ) | .../stacktrace_variadic_html_5.php:7 |
3 | %f | %d | trigger_error
-( czo2OiJub3RpY2UiOw== ) | ../stacktrace_variadic_html_5.php:4 |
+( czo2OiJub3RpY2UiOw== ).../stacktrace_variadic_html_5.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_5.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_5.php:0 |
-2 | %f | %d | foo( aToxOw==, ...variadic(YjowOw==) ) | ../stacktrace_variadic_html_5.php:8 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_5.php:0 |
+2 | %f | %d | foo( aToxOw==, ...variadic(YjowOw==) ) | .../stacktrace_variadic_html_5.php:8 |
3 | %f | %d | trigger_error
-( czo2OiJub3RpY2UiOw== ) | ../stacktrace_variadic_html_5.php:4 |
+( czo2OiJub3RpY2UiOw== ).../stacktrace_variadic_html_5.php:4 |
( ! ) Notice: notice in %sstacktrace_variadic_html_5.php on line 4 |
Call Stack |
# | Time | Memory | Function | Location |
-1 | %f | %d | {main}( ) | ../stacktrace_variadic_html_5.php:0 |
-2 | %f | %d | foo( czozOiJmb28iOw==, ...variadic(czozOiJiYXIiOw==, ZDozLjE0MTUwMDAwMDAwMDAwMDI7) ) | ../stacktrace_variadic_html_5.php:9 |
+1 | %f | %d | {main}( ) | .../stacktrace_variadic_html_5.php:0 |
+2 | %f | %d | foo( czozOiJmb28iOw==, ...variadic(czozOiJiYXIiOw==, ZDozLjE0MTUwMDAwMDAwMDAwMDI7) ) | .../stacktrace_variadic_html_5.php:9 |
3 | %f | %d | trigger_error
-( czo2OiJub3RpY2UiOw== ) | ../stacktrace_variadic_html_5.php:4 |
+( czo2OiJub3RpY2UiOw== ).../stacktrace_variadic_html_5.php:4 |
diff --git a/tests/xdebug_get_function_stack_variadic.phpt b/tests/xdebug_get_function_stack_variadic.phpt
index 7b850eb48..2691a3d0c 100644
--- a/tests/xdebug_get_function_stack_variadic.phpt
+++ b/tests/xdebug_get_function_stack_variadic.phpt
@@ -34,7 +34,7 @@ array(4) {
'function' =>
string(3) "foo"
'file' =>
- string(80) "%sxdebug_get_function_stack_variadic.php"
+ string(%d) "%sxdebug_get_function_stack_variadic.php"
'line' =>
int(8)
'params' =>
@@ -49,7 +49,7 @@ array(4) {
'function' =>
string(3) "foo"
'file' =>
- string(80) "%sxdebug_get_function_stack_variadic.php"
+ string(%d) "%sxdebug_get_function_stack_variadic.php"
'line' =>
int(9)
'params' =>
@@ -67,7 +67,7 @@ array(4) {
'function' =>
string(3) "foo"
'file' =>
- string(80) "%sxdebug_get_function_stack_variadic.php"
+ string(%d) "%sxdebug_get_function_stack_variadic.php"
'line' =>
int(10)
'params' =>
diff --git a/xdebug.c b/xdebug.c
index 8cce2905b..13f44c7c4 100644
--- a/xdebug.c
+++ b/xdebug.c
@@ -313,7 +313,8 @@ static void php_xdebug_init_globals (zend_xdebug_globals *xg TSRMLS_DC)
xg->stack = NULL;
xg->level = 0;
xg->do_trace = 0;
- xg->trace_file = NULL;
+ xg->trace_handler = NULL;
+ xg->trace_context = NULL;
xg->coverage_enable = 0;
xg->previous_filename = "";
xg->previous_file = NULL;
@@ -330,6 +331,8 @@ static void php_xdebug_init_globals (zend_xdebug_globals *xg TSRMLS_DC)
xg->output_is_tty = OUTPUT_NOT_CHECKED;
xg->stdout_mode = 0;
xg->in_at = 0;
+ xg->active_execute_data = NULL;
+ xg->active_op_array = NULL;
xdebug_llist_init(&xg->server, xdebug_superglobals_dump_dtor);
xdebug_llist_init(&xg->get, xdebug_superglobals_dump_dtor);
@@ -470,7 +473,7 @@ static int xdebug_silence_handler(ZEND_OPCODE_HANDLER_ARGS)
zend_op *cur_opcode = *EG(opline_ptr);
if (XG(do_code_coverage)) {
- xdebug_print_opcode_info('S', execute_data, cur_opcode);
+ xdebug_print_opcode_info('S', execute_data, cur_opcode TSRMLS_CC);
}
if (XG(do_scream)) {
execute_data->opline++;
@@ -490,7 +493,7 @@ static int xdebug_include_or_eval_handler(ZEND_OPCODE_HANDLER_ARGS)
if (XG(do_code_coverage)) {
zend_op *cur_opcode = *EG(opline_ptr);
- xdebug_print_opcode_info('I', execute_data, cur_opcode);
+ xdebug_print_opcode_info('I', execute_data, cur_opcode TSRMLS_CC);
}
#if PHP_VERSION_ID >= 50399
if (opline->extended_value == ZEND_EVAL) {
@@ -709,6 +712,11 @@ PHP_MINIT_FUNCTION(xdebug)
for (i = 0; i < 256; i++) {
if (zend_get_user_opcode_handler(i) == NULL) {
+#if ZTS
+ if (i == ZEND_HANDLE_EXCEPTION) {
+ continue;
+ }
+#endif
zend_set_user_opcode_handler(i, xdebug_check_branch_entry_handler);
}
}
@@ -870,8 +878,8 @@ PHP_RINIT_FUNCTION(xdebug)
XG(do_code_coverage) = 0;
XG(code_coverage) = xdebug_hash_alloc(32, xdebug_coverage_file_dtor);
XG(stack) = xdebug_llist_alloc(xdebug_stack_element_dtor);
- XG(trace_file) = NULL;
- XG(tracefile_name) = NULL;
+ XG(trace_handler) = NULL;
+ XG(trace_context) = NULL;
XG(profile_file) = NULL;
XG(profile_filename) = NULL;
XG(prev_memory) = 0;
@@ -997,7 +1005,7 @@ ZEND_MODULE_POST_ZEND_DEACTIVATE_D(xdebug)
xdebug_llist_destroy(XG(stack), NULL);
XG(stack) = NULL;
- if (XG(do_trace) && XG(trace_file)) {
+ if (XG(do_trace) && XG(trace_context)) {
xdebug_stop_trace(TSRMLS_C);
}
@@ -1294,7 +1302,7 @@ void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
zval **dummy;
function_stack_entry *fse, *xfse;
char *magic_cookie = NULL;
- int do_return = (XG(do_trace) && XG(trace_file));
+ int do_return = (XG(do_trace) && XG(trace_context));
int function_nr = 0;
xdebug_llist_element *le;
int clear = 0;
@@ -1426,7 +1434,9 @@ void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
}
function_nr = XG(function_count);
- xdebug_trace_function_begin(fse, function_nr TSRMLS_CC);
+ if (XG(do_trace) && XG(trace_context) && (XG(trace_handler)->function_entry)) {
+ XG(trace_handler)->function_entry(XG(trace_context), fse, function_nr TSRMLS_CC);
+ }
fse->symbol_table = EG(active_symbol_table);
#if PHP_VERSION_ID < 50500
@@ -1493,25 +1503,23 @@ void xdebug_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
if (XG(profiler_enabled)) {
xdebug_profiler_function_user_end(fse, op_array TSRMLS_CC);
}
-
- xdebug_trace_function_end(fse, function_nr TSRMLS_CC);
+
+ if (XG(do_trace) && XG(trace_context) && (XG(trace_handler)->function_exit)) {
+ XG(trace_handler)->function_exit(XG(trace_context), fse, function_nr TSRMLS_CC);
+ }
/* 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_context)) {
if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
- 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);
+ XG(trace_handler)->generator_return_value(XG(trace_context), fse, function_nr, (zend_generator*) EG(return_value_ptr_ptr) TSRMLS_CC);
} else {
- t = xdebug_return_trace_stack_retval(fse, function_nr, *EG(return_value_ptr_ptr) TSRMLS_CC);
+ XG(trace_handler)->return_value(XG(trace_context), fse, function_nr, *EG(return_value_ptr_ptr) TSRMLS_CC);
}
#else
- t = xdebug_return_trace_stack_retval(fse, function_nr, *EG(return_value_ptr_ptr) TSRMLS_CC);
+ XG(trace_handler)->return_value(XG(trace_context), fse, function_nr, *EG(return_value_ptr_ptr) TSRMLS_CC);
#endif
- fprintf(XG(trace_file), "%s", t);
- fflush(XG(trace_file));
- xdfree(t);
}
}
if (clear && *EG(return_value_ptr_ptr)) {
@@ -1559,7 +1567,7 @@ void xdebug_execute_internal(zend_execute_data *current_execute_data, struct _ze
zend_execute_data *edata = EG(current_execute_data);
function_stack_entry *fse;
zend_op *cur_opcode;
- int do_return = (XG(do_trace) && XG(trace_file));
+ int do_return = (XG(do_trace) && XG(trace_context));
int function_nr = 0;
int restore_error_handler_situation = 0;
@@ -1574,7 +1582,9 @@ void xdebug_execute_internal(zend_execute_data *current_execute_data, struct _ze
fse->function.internal = 1;
function_nr = XG(function_count);
- xdebug_trace_function_begin(fse, function_nr TSRMLS_CC);
+ if (XG(do_trace) && XG(trace_context) && (XG(trace_handler)->function_entry)) {
+ XG(trace_handler)->function_entry(XG(trace_context), fse, function_nr TSRMLS_CC);
+ }
/* Check for entry breakpoints */
if (XG(remote_enabled) && XG(breakpoints_allowed)) {
@@ -1616,18 +1626,17 @@ void xdebug_execute_internal(zend_execute_data *current_execute_data, struct _ze
zend_error_cb = tmp_error_cb;
}
- xdebug_trace_function_end(fse, function_nr TSRMLS_CC);
+ if (XG(do_trace) && XG(trace_context) && (XG(trace_handler)->function_exit)) {
+ XG(trace_handler)->function_exit(XG(trace_context), fse, function_nr TSRMLS_CC);
+ }
/* Store return value in the trace file */
- if (XG(collect_return) && do_return && XG(do_trace) && XG(trace_file) && EG(opline_ptr)) {
+ if (XG(collect_return) && do_return && XG(do_trace) && XG(trace_context) && EG(opline_ptr) && current_execute_data->opline) {
cur_opcode = *EG(opline_ptr);
if (cur_opcode) {
zval *ret = xdebug_zval_ptr(cur_opcode->XDEBUG_TYPE(result), &(cur_opcode->result), current_execute_data TSRMLS_CC);
if (ret) {
- char* t = xdebug_return_trace_stack_retval(fse, function_nr, ret TSRMLS_CC);
- fprintf(XG(trace_file), "%s", t);
- fflush(XG(trace_file));
- xdfree(t);
+ XG(trace_handler)->return_value(XG(trace_context), fse, function_nr, ret TSRMLS_CC);
}
}
}
diff --git a/xdebug.ini b/xdebug.ini
index 05d923121..c00edf69e 100644
--- a/xdebug.ini
+++ b/xdebug.ini
@@ -8,9 +8,9 @@
; When this setting is set to on, the tracing of function calls will be enabled
; just before the script is run. This makes it possible to trace code in the
; auto_prepend_file [1].
-;
+;
; [1] http://www.php.net/manual/en/configuration.directives.php#ini.auto-prepend-file
-;
+;
;
;xdebug.auto_trace = 0
@@ -24,17 +24,17 @@
; If this setting is 1, Xdebug will color var_dumps and stack traces output when
; in CLI mode and when the output is a tty. On Windows, the ANSICON [1] tool
; needs to be installed.
-;
+;
; [1] http://adoxa.110mb.com/ansicon/
-;
+;
; If the setting is 2, then Xdebug will always color var_dumps and stack trace,
; no matter whether it's connected to a tty or whether ANSICON is installed. In
; this case, you might end up seeing escape codes.
-;
+;
; See this article [1] for some more information.
-;
+;
; [1] http://drck.me/clicolor-9cr
-;
+;
;
;xdebug.cli_color = 0
@@ -47,7 +47,7 @@
;
; This setting, defaulting to 0, controls whether Xdebug should add variable
; assignments to function traces.
-;
+;
;
;xdebug.collect_assignments = 0
@@ -59,7 +59,7 @@
; This setting, defaulting to 1, controls whether Xdebug should write the
; filename used in include(), include_once(), require() or require_once() to the
; trace files.
-;
+;
;
;xdebug.collect_includes = 1
@@ -71,7 +71,7 @@
; This setting, defaulting to 0, controls whether Xdebug should collect the
; parameters passed to functions when a function call is recorded in either the
; function trace or the stack trace.
-;
+;
; The setting defaults to 0 because for very large scripts it may use huge
; amounts of memory and therefore make it impossible for the huge script to run.
; You can most safely turn this setting on, but you can expect some problems in
@@ -80,12 +80,12 @@
; as it will never store this information in memory. Instead it will only be
; written to disk. This means that you need to have a look at the disk usage
; though.
-;
+;
; This setting can have four different values. For each of the values a
; different amount of information is shown. Below you will see what information
; each of the values provides. See also the introduction of the feature Stack
; Traces for a few screenshots.
-;
+;
; ===== ========================================================================
; Value Argument Information Shown
; ===== ========================================================================
@@ -100,11 +100,15 @@
; xdebug.var_display_max_depth.
; ----- ------------------------------------------------------------------------
; 4 Full variable contents and variable name.
+; ----- ------------------------------------------------------------------------
+; 5 PHP serialized variable contents, without the name.
+;
+; (New in Xdebug 2.3)
; ===== ========================================================================
-;
+;
; 1 in the CLI version of PHP it will not have the tool tip, nor in output
; files.
-;
+;
;
;xdebug.collect_params = 0
@@ -115,7 +119,10 @@
;
; This setting, defaulting to 0, controls whether Xdebug should write the return
; value of function calls to the trace files.
-;
+;
+; For computerized trace files (xdebug.trace_format=1) this only works from
+; Xdebug 2.3 onwards.
+;
;
;xdebug.collect_return = 0
@@ -129,21 +136,21 @@
; engineer PHP's opcode arrays. This setting will not record which values the
; different variables have, for that use xdebug.collect_params. This setting
; needs to be enabled only if you wish to use xdebug_get_declared_vars().
-;
+;
;
;xdebug.collect_vars = 0
; -----------------------------------------------------------------------------
; xdebug.coverage_enable
;
-; Only in Xdebug versions > 2.2
+; Only in Xdebug versions >= 2.2
;
; Type: boolean, Default value: 1
;
; If this setting is set to 0, then Xdebug will not set-up internal structures
; to allow code coverage. This speeds up Xdebug quite a bit, but of course, Code
; Coverage Analysis won't work.
-;
+;
;
;xdebug.coverage_enable = 1
@@ -156,7 +163,7 @@
; event. You can disable showing stacktraces from your code with
; xdebug_disable(). As this is one of the basic functions of Xdebug, it is
; advisable to leave this setting set to 1.
-;
+;
;
;xdebug.default_enable = 1
@@ -165,15 +172,20 @@
;
; Type: string, Default value: Empty
;
-; * = COOKIE, FILES, GET, POST, REQUEST, SERVER, SESSION. These seven settings
-; control which data from the superglobals is shown when an error situation
-; occurs. Each php.ini setting can consist of a comma seperated list of
-; variables from this superglobal to dump, but make sure you do not add spaces
-; in this setting. In order to dump the REMOTE_ADDR and the REQUEST_METHOD when
-; an error occurs, add this setting:
-;
+; * can be any of COOKIE, FILES, GET, POST, REQUEST, SERVER, SESSION. These
+; seven settings control which data from the superglobals is shown when an error
+; situation occurs.
+;
+; Each of those php.ini setting can consist of a comma seperated list of
+; variables from this superglobal to dump, or ``*`` for all of them. Make sure
+; you do not add spaces in this setting.
+;
+; In order to dump the REMOTE_ADDR and the REQUEST_METHOD when an error occurs,
+; and all GET parameters, add these settings:
+;
; xdebug.dump.SERVER = REMOTE_ADDR,REQUEST_METHOD
-;
+; xdebug.dump.GET = *
+;
;
;xdebug.dump.* = Empty
@@ -183,8 +195,8 @@
; Type: boolean, Default value: 1
;
; Controls whether the values of the superglobals as defined by the
-; xdebug.dump.* settings whould be shown or not.
-;
+; xdebug.dump.* settings should be shown or not.
+;
;
;xdebug.dump_globals = 1
@@ -195,7 +207,7 @@
;
; Controls whether the values of the superglobals should be dumped on all error
; situations (set to 0) or only on the first (set to 1).
-;
+;
;
;xdebug.dump_once = 1
@@ -206,7 +218,7 @@
;
; If you want to dump undefined values from the superglobals you should set this
; setting to 1, otherwise leave it set to 0.
-;
+;
;
;xdebug.dump_undefined = 0
@@ -221,7 +233,7 @@
; this option as PHP's generated oparrays will increase with about a third of
; the size slowing down your scripts. This setting can not be set in your
; scripts with ini_set(), but only in php.ini.
-;
+;
;
;xdebug.extended_info = 1
@@ -237,11 +249,11 @@
; link-protocol that makes it possible to go directly to a line and file by
; clicking on the filenames that Xdebug shows in stack traces. An example format
; might look like:
-;
+;
; myide://%f@%l
-;
+;
; The possible format specifiers are:
-;
+;
; ========= ===============
; Specifier Meaning
; ========= ===============
@@ -249,96 +261,160 @@
; --------- ---------------
; %l the line number
; ========= ===============
-;
+;
; For various IDEs/OSses there are some instructions listed on how to make this
; work:
-;
+;
; ----------------
; Firefox on Linux
; ----------------
-;
+;
; - Open
-;
+;
; about:config
-;
+;
; - Add a new boolean setting "network.protocol-handler.expose.xdebug"
-;
+;
; - Add the following into a shell script
-;
+;
; ``~/bin/ff-xdebug.sh``:
-;
+;
; #! /bin/sh
-;
+;
; f=`echo $1 | cut -d @ -f 1 | sed 's/xdebug:\/\///'`
; l=`echo $1 | cut -d @ -f 2`
-;
+;
; Add to that one of (depending whether you have komodo or gvim):
-;
+;
; - komodo $f -l $l
-;
+;
; - gvim --remote-tab +$l $f
-;
+;
; - Make the script executable with
-;
+;
; chmod +x ~/bin/ff-xdebug.sh
-;
+;
; - Set the xdebug.file_link_format setting to
-;
+;
; xdebug://%f@%l
-;
+;
; --------------------
; Windows and netbeans
; --------------------
-;
+;
; - Create the file
-;
+;
; ``netbeans.bat`` and save it in your path ( ``C:\Windows`` will work):
-;
-; @echo off
-; setlocal enableextensions enabledelayedexpansion
+;
+; @echo off
+; setlocal enableextensions enabledelayedexpansion
; set NETBEANS=%1
; set FILE=%~2
; %NETBEANS% --nosplash --console suppress --open "%FILE:~19%"
; nircmd win activate process netbeans.exe
-;
+;
; **Note:** Remove the last line if you don't have ``nircmd``.
-;
+;
; - Save the following code as
-;
+;
; ``netbeans_protocol.reg``:
-;
+;
; Windows Registry Editor Version 5.00
-;
+;
; [HKEY_CLASSES_ROOT\netbeans]
; "URL Protocol"=""
; @="URL:Netbeans Protocol"
-;
+;
; [HKEY_CLASSES_ROOT\netbeans\DefaultIcon]
; @="\"C:\\Program Files\\NetBeans 7.1.1\\bin\\netbeans.exe,1\""
-;
+;
; [HKEY_CLASSES_ROOT\netbeans\shell]
-;
+;
; [HKEY_CLASSES_ROOT\netbeans\shell\open]
-;
+;
; [HKEY_CLASSES_ROOT\netbeans\shell\open\command]
; @="\"C:\\Windows\\netbeans.bat\" \"C:\\Program Files\\NetBeans 7.1.1\\bin\\netbeans.exe\" \"%1\""
-;
+;
; **Note:** Make sure to change the path to Netbeans (twice), as well as the
; ``netbeans.bat`` batch file if you saved it somewhere else than
; ``C:\Windows\``.
-;
+;
; - Double click on the
-;
+;
; ``netbeans_protocol.reg`` file to import it into the registry.
-;
+;
; - Set the xdebug.file_link_format setting to
-;
+;
; xdebug.file_link_format =
; "netbeans://open/?f=%f:%l"
-;
+;
;
;xdebug.file_link_format =
+; -----------------------------------------------------------------------------
+; xdebug.force_display_errors
+;
+; Only in Xdebug versions 2.3
+;
+; Type: int, Default value: 0
+;
+; If this setting is set to ``1`` then errors will **always** be displayed, no
+; matter what the setting of PHP's display_errors [1] is.
+;
+; [1] http://php.net/manual/en/errorfunc.configuration.php#ini.display-errors
+;
+;
+;xdebug.force_display_errors = 0
+
+; -----------------------------------------------------------------------------
+; xdebug.force_error_reporting
+;
+; Only in Xdebug versions 2.3
+;
+; Type: int, Default value: 0
+;
+; This setting is a bitmask, like error_reporting [1]. This bitmask will be
+; logically ORed with the bitmask represented by error_reporting [2] to dermine
+; which errors should be displayed. This setting can only be made in php.ini and
+; allows you to force certain errors from being shown no matter what an
+; application does with ini_set() [3].
+;
+; [1] http://php.net/manual/en/errorfunc.configuration.php#ini.error-reporting
+; [2] http://php.net/manual/en/errorfunc.configuration.php#ini.error-reporting
+; [3] http://php.net/manual/en/function.ini-set.php
+;
+;
+;xdebug.force_error_reporting = 0
+
+; -----------------------------------------------------------------------------
+; xdebug.halt_level
+;
+; Only in Xdebug versions 2.3
+;
+; Type: int, Default value: 0
+;
+; This setting allows you to configure a mask that determines whether, and
+; which, notices and/or warnings get converted to errors. You can configure
+; notices and warnings that are generated by PHP, and notices and warnings that
+; you generate yourself (by means of trigger_error()). For example, to convert
+; the warning of strlen() (without arguments) to an error, you would do:
+;
+; ini_set('xdebug.halt_level', E_WARNING);
+; echo "Hi!\n";
+;
+; Which will then result in the showing of the error message, and the abortion
+; of the script. ``echo "Hi!\n";`` will not be executed.
+;
+; The setting is a bit mask, so to convert all notices and warnings into errors
+; for all applications, you can set this in php.ini:
+;
+; xdebug.halt_level=E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE
+;
+; The bitmask only supports the four level that are mentioned above.
+;
+;
+;xdebug.halt_level = 0
+
; -----------------------------------------------------------------------------
; xdebug.idekey
;
@@ -350,7 +426,7 @@
; to the first environment variable that is found. If none could be found the
; setting has as default ''. If this setting is set, it always overrides the
; environment variables.
-;
+;
;
;xdebug.idekey = *complex*
@@ -364,7 +440,7 @@
; This is the base url for the links from the function traces and error message
; to the manual pages of the function from the message. It is advisable to set
; this setting to use the closest mirror.
-;
+;
;
;xdebug.manual_url = http://www.php.net
@@ -376,7 +452,7 @@
; Controls the protection mechanism for infinite recursion protection. The value
; of this setting is the maximum level of nested functions that are allowed
; before the script will be aborted.
-;
+;
;
;xdebug.max_nesting_level = 100
@@ -391,7 +467,12 @@
; displaying variables when the html_errors php.ini setting is set to 1. In case
; you do not want that, you can set this setting to 0, but check first if it's
; not smarter to turn off html_errors.
-;
+;
+; You can also use ``2`` as value for this setting. Besides formatting the
+; var_dump() output nicely, it will also add filename and line number to the
+; output. The xdebug.file_link_format setting is also respected. *(New in Xdebug
+; 2.3)*
+;
;
;xdebug.overload_var_dump = 1
@@ -404,7 +485,7 @@
; new request would map to the same file (depnding on the
; xdebug.profiler_output_name setting. Instead the file will be appended to with
; the new profile.
-;
+;
;
;xdebug.profiler_append = 0
@@ -418,7 +499,7 @@
; can not be set in your script with ini_set(). If you want to selectively
; enable the profiler, please set xdebug.profiler_enable_trigger to 1
; **instead** of using this setting.
-;
+;
;
;xdebug.profiler_enable = 0
@@ -432,7 +513,7 @@
; name XDEBUG_PROFILE. This will then write the profiler data to defined
; directory. In order to prevent the profiler to generate profile files for each
; request, you need to set xdebug.profiler_enable to 0.
-;
+;
;
;xdebug.profiler_enable_trigger = 0
@@ -444,7 +525,7 @@
; The directory where the profiler output will be written to, make sure that the
; user who the PHP will be running as has write permissions to that directory.
; This setting can not be set in your script with ini_set().
-;
+;
;
;xdebug.profiler_output_dir = /tmp
@@ -457,9 +538,9 @@
; The setting specifies the format with format specifiers, very similar to
; sprintf() and strftime(). There are several format specifiers that can be used
; to format the file name.
-;
+;
; See the xdebug.trace_output_name documentation for the supported specifiers.
-;
+;
;
;xdebug.profiler_output_name = cachegrind.out.%p
@@ -472,7 +553,7 @@
; debugging (see Remote Debugging). When this setting is set to 1, Xdebug will
; always attempt to start a remote debugging session and try to connect to a
; client, even if the GET/POST/COOKIE variable was not present.
-;
+;
;
;xdebug.remote_autostart = 0
@@ -489,7 +570,7 @@
; note that there is **no** filter available, and anybody who can connect to the
; webserver will then be able to start a debugging session, even if their
; address does not match xdebug.remote_host.
-;
+;
;
;xdebug.remote_connect_back = 0
@@ -502,7 +583,7 @@
;
; This setting can be used to increase (or decrease) the time that the remote
; debugging session stays alive via the session cookie.
-;
+;
;
;xdebug.remote_cookie_expire_time = 3600
@@ -515,7 +596,7 @@
; is listening on the host and port as set with the settings xdebug.remote_host
; and xdebug.remote_port. If a connection can not be established the script will
; just continue as if this setting was 0.
-;
+;
;
;xdebug.remote_enable = 0
@@ -526,14 +607,13 @@
;
; Can be either 'php3' which selects the old PHP 3 style debugger [1] output,
; 'gdb' which enables the GDB like debugger interface or 'dbgp' - the debugger
-; protocol [2]. The DBGp protocol is more widely supported by clients. See more
-; information in the introduction for Remote Debugging.
-;
+; protocol [2]. The DBGp protocol is the only supported protocol.
+;
; [1] http://www.php.net/manual/en/debugger.php
; [2] http://xdebug.org/docs-dbgp.php
-;
+;
; **Note**: Xdebug 2.1 and later only support 'dbgp' as protocol.
-;
+;
;
;xdebug.remote_handler = dbgp
@@ -545,7 +625,7 @@
; Selects the host where the debug client is running, you can either use a host
; name or an IP address. This setting is ignored if xdebug.remote_connect_back
; is enabled.
-;
+;
;
;xdebug.remote_host = localhost
@@ -558,13 +638,13 @@
; debugger communications are logged. The file is always opened in append-mode,
; and will therefore not be overwritten by default. There is no concurrency
; protection available. The format of the file looks something like:
-;
+;
; Log opened at 2007-05-27 14:28:15
; -> path_info.paths[i]);
+ xdebug_path_info_dump(branch_info->path_info.paths[i] TSRMLS_CC);
}
}
diff --git a/xdebug_branch_info.h b/xdebug_branch_info.h
index f1e8d77d8..8d794d670 100644
--- a/xdebug_branch_info.h
+++ b/xdebug_branch_info.h
@@ -74,8 +74,8 @@ void xdebug_path_add(xdebug_path *path, unsigned int nr);
xdebug_path *xdebug_path_new(xdebug_path *old_path);
void xdebug_path_info_dump(xdebug_path *path TSRMLS_DC);
void xdebug_path_free(xdebug_path *path);
-void xdebug_path_info_add_path_for_level(xdebug_path_info *path_info, xdebug_path *path, unsigned int level);
-xdebug_path *xdebug_path_info_get_path_for_level(xdebug_path_info *path_info, unsigned int level);
+void xdebug_path_info_add_path_for_level(xdebug_path_info *path_info, xdebug_path *path, unsigned int level TSRMLS_DC);
+xdebug_path *xdebug_path_info_get_path_for_level(xdebug_path_info *path_info, unsigned int level TSRMLS_DC);
void xdebug_create_key_for_path(xdebug_path *path, xdebug_str *str);
void xdebug_branch_info_mark_reached(char *filename, char *function_name, zend_op_array *op_array, long opcode_nr TSRMLS_DC);
diff --git a/xdebug_code_coverage.c b/xdebug_code_coverage.c
index 974b9ed0b..d07a3c1d6 100644
--- a/xdebug_code_coverage.c
+++ b/xdebug_code_coverage.c
@@ -82,7 +82,7 @@ void xdebug_coverage_function_dtor(void *data)
xdfree(function);
}
-void xdebug_print_opcode_info(char type, zend_execute_data *execute_data, zend_op *cur_opcode)
+void xdebug_print_opcode_info(char type, zend_execute_data *execute_data, zend_op *cur_opcode TSRMLS_DC)
{
zend_op_array *op_array = execute_data->op_array;
char *file = (char *) op_array->filename;
@@ -109,7 +109,7 @@ int xdebug_check_branch_entry_handler(ZEND_OPCODE_HANDLER_ARGS)
zend_op *cur_opcode;
cur_opcode = *EG(opline_ptr);
- xdebug_print_opcode_info('G', execute_data, cur_opcode);
+ xdebug_print_opcode_info('G', execute_data, cur_opcode TSRMLS_CC);
}
return ZEND_USER_OPCODE_DISPATCH;
}
@@ -135,7 +135,7 @@ int xdebug_common_override_handler(ZEND_OPCODE_HANDLER_ARGS)
file = (char *)op_array->filename;
- xdebug_print_opcode_info('C', execute_data, cur_opcode);
+ xdebug_print_opcode_info('C', execute_data, cur_opcode TSRMLS_CC);
xdebug_count_line(file, lineno, 0, 0 TSRMLS_CC);
}
return ZEND_USER_OPCODE_DISPATCH;
@@ -292,7 +292,6 @@ static int xdebug_common_assign_dim_handler(char *op, int do_cc, ZEND_OPCODE_HAN
zend_op *cur_opcode, *next_opcode;
char *full_varname;
zval *val = NULL;
- char *t;
int is_var;
function_stack_entry *fse;
@@ -302,13 +301,13 @@ static int xdebug_common_assign_dim_handler(char *op, int do_cc, ZEND_OPCODE_HAN
lineno = cur_opcode->lineno;
if (XG(do_code_coverage)) {
- xdebug_print_opcode_info('=', execute_data, cur_opcode);
+ xdebug_print_opcode_info('=', execute_data, cur_opcode TSRMLS_CC);
if (do_cc) {
xdebug_count_line(file, lineno, 0, 0 TSRMLS_CC);
}
}
- if (XG(do_trace) && XG(trace_file) && XG(collect_assignments)) {
+ if (XG(do_trace) && XG(trace_context) && XG(collect_assignments)) {
full_varname = xdebug_find_var_name(execute_data TSRMLS_CC);
if (cur_opcode->opcode >= ZEND_PRE_INC && cur_opcode->opcode <= ZEND_POST_DEC) {
@@ -344,11 +343,10 @@ static int xdebug_common_assign_dim_handler(char *op, int do_cc, ZEND_OPCODE_HAN
}
fse = XDEBUG_LLIST_VALP(XDEBUG_LLIST_TAIL(XG(stack)));
- t = xdebug_return_trace_assignment(fse, full_varname, val, op, file, lineno TSRMLS_CC);
+ if (XG(do_trace) && XG(trace_context) && XG(collect_assignments) && XG(trace_handler)->assignment) {
+ XG(trace_handler)->assignment(XG(trace_context), fse, full_varname, val, op, file, lineno TSRMLS_CC);
+ }
xdfree(full_varname);
- fprintf(XG(trace_file), "%s", t);
- fflush(XG(trace_file));
- xdfree(t);
}
return ZEND_USER_OPCODE_DISPATCH;
}
@@ -794,7 +792,7 @@ void xdebug_code_coverage_start_of_function(zend_op_array *op_array TSRMLS_DC)
xdebug_path *path = xdebug_path_new(NULL);
xdebug_prefill_code_coverage(op_array TSRMLS_CC);
- xdebug_path_info_add_path_for_level(&(XG(paths_stack)), path, XG(level));
+ xdebug_path_info_add_path_for_level(&(XG(paths_stack)), path, XG(level) TSRMLS_CC);
if (XG(branches).size == 0 || XG(level) > XG(branches).size) {
XG(branches).size += 32;
@@ -807,7 +805,7 @@ void xdebug_code_coverage_start_of_function(zend_op_array *op_array TSRMLS_DC)
void xdebug_code_coverage_end_of_function(zend_op_array *op_array TSRMLS_DC)
{
xdebug_str str = { 0, 0, NULL };
- xdebug_path *path = xdebug_path_info_get_path_for_level(&(XG(paths_stack)), XG(level));
+ xdebug_path *path = xdebug_path_info_get_path_for_level(&(XG(paths_stack)), XG(level) TSRMLS_CC);
char *file = (char *) op_array->filename;
xdebug_func func_info;
char *function_name;
@@ -988,13 +986,14 @@ static void add_cc_function(void *ret, xdebug_hash_element *e)
xdebug_coverage_function *function = (xdebug_coverage_function*) e->ptr;
zval *retval = (zval*) ret;
zval *function_info;
+ TSRMLS_FETCH();
MAKE_STD_ZVAL(function_info);
array_init(function_info);
if (function->branch_info) {
- add_branches(function_info, function->branch_info);
- add_paths(function_info, function->branch_info);
+ add_branches(function_info, function->branch_info TSRMLS_CC);
+ add_paths(function_info, function->branch_info TSRMLS_CC);
}
add_assoc_zval_ex(retval, function->name, strlen(function->name) + 1, function_info);
diff --git a/xdebug_code_coverage.h b/xdebug_code_coverage.h
index 2fe387da4..d8aaf5cbd 100644
--- a/xdebug_code_coverage.h
+++ b/xdebug_code_coverage.h
@@ -56,7 +56,7 @@ void xdebug_coverage_file_dtor(void *data);
xdebug_coverage_function *xdebug_coverage_function_ctor(char *function_name);
void xdebug_coverage_function_dtor(void *data);
-void xdebug_print_opcode_info(char type, zend_execute_data *execute_data, zend_op *cur_opcode);
+void xdebug_print_opcode_info(char type, zend_execute_data *execute_data, zend_op *cur_opcode TSRMLS_DC);
void xdebug_code_coverage_start_of_function(zend_op_array *op_array TSRMLS_DC);
void xdebug_code_coverage_end_of_function(zend_op_array *op_array TSRMLS_DC);
diff --git a/xdebug_compat.c b/xdebug_compat.c
index 24928b120..51f42ee69 100644
--- a/xdebug_compat.c
+++ b/xdebug_compat.c
@@ -72,6 +72,10 @@ void *php_zend_memrchr(const void *s, int c, size_t n)
zval *xdebug_zval_ptr(int op_type, XDEBUG_ZNODE *node, zend_execute_data *zdata TSRMLS_DC)
{
+ if (!zdata->opline) {
+ return NULL;
+ }
+
switch (op_type & 0x0F) {
case IS_CONST:
#if PHP_VERSION_ID >= 50399
diff --git a/xdebug_private.h b/xdebug_private.h
index 5aeabbc46..88500dda4 100644
--- a/xdebug_private.h
+++ b/xdebug_private.h
@@ -206,6 +206,23 @@ function_stack_entry *xdebug_get_stack_head(TSRMLS_D);
function_stack_entry *xdebug_get_stack_frame(int nr TSRMLS_DC);
function_stack_entry *xdebug_get_stack_tail(TSRMLS_D);
+typedef struct
+{
+ void *(*init)(char *fname, long options TSRMLS_DC);
+ void (*deinit)(void *ctxt TSRMLS_DC);
+ void (*write_header)(void *ctxt TSRMLS_DC);
+ void (*write_footer)(void *ctxt TSRMLS_DC);
+ char *(*get_filename)(void *ctxt TSRMLS_DC);
+ void (*function_entry)(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC);
+ void (*function_exit)(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC);
+ void (*return_value)(void *ctxt, function_stack_entry *fse, int function_nr, zval *return_value TSRMLS_DC);
+#if PHP_VERSION_ID >= 50500
+ void (*generator_return_value)(void *ctxt, function_stack_entry *fse, int function_nr, zend_generator *generator TSRMLS_DC);
+#endif
+ void (*assignment)(void *ctxt, function_stack_entry *fse, char *full_varname, zval *value, char *op, char *file, int lineno TSRMLS_DC);
+} xdebug_trace_handler_t;
+
+
xdebug_hash* xdebug_used_var_hash_from_llist(xdebug_llist *list);
void xdebug_init_debugger(TSRMLS_D);
diff --git a/xdebug_stack.c b/xdebug_stack.c
index 0d37f75f6..efbeb9f75 100644
--- a/xdebug_stack.c
+++ b/xdebug_stack.c
@@ -959,7 +959,7 @@ static void xdebug_build_fname(xdebug_func *tmp, zend_execute_data *edata TSRMLS
fname = "whoops";
}
- lineno = find_line_number_for_current_execute_point(edata TSRMLS_DC);
+ lineno = find_line_number_for_current_execute_point(edata TSRMLS_CC);
tmp->function = xdebug_sprintf(
"%s:{%s:%d}",
diff --git a/xdebug_trace_computerized.c b/xdebug_trace_computerized.c
new file mode 100644
index 000000000..4dc98417b
--- /dev/null
+++ b/xdebug_trace_computerized.c
@@ -0,0 +1,251 @@
+/*
+ +----------------------------------------------------------------------+
+ | Xdebug |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2002-2014 Derick Rethans |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 1.0 of the Xdebug license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://xdebug.derickrethans.nl/license.php |
+ | If you did not receive a copy of the Xdebug license and are unable |
+ | to obtain it through the world-wide-web, please send a note to |
+ | xdebug@derickrethans.nl so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans |
+ +----------------------------------------------------------------------+
+ */
+#include "xdebug_trace_computerized.h"
+#include "xdebug_var.h"
+#include "ext/standard/php_string.h"
+
+extern ZEND_DECLARE_MODULE_GLOBALS(xdebug);
+
+void *xdebug_trace_computerized_init(char *fname, long options TSRMLS_DC)
+{
+ xdebug_trace_computerized_context *tmp_computerized_context;
+ char *used_fname;
+
+ tmp_computerized_context = xdmalloc(sizeof(xdebug_trace_computerized_context));
+ tmp_computerized_context->trace_file = xdebug_trace_open_file(fname, options, (char**) &used_fname TSRMLS_CC);
+ tmp_computerized_context->trace_filename = used_fname;
+
+ return tmp_computerized_context;
+}
+
+void xdebug_trace_computerized_deinit(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt;
+
+ fclose(context->trace_file);
+ context->trace_file = NULL;
+ xdfree(context->trace_filename);
+
+ xdfree(context);
+}
+
+void xdebug_trace_computerized_write_header(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt;
+ char *str_time;
+
+ fprintf(context->trace_file, "Version: %s\n", XDEBUG_VERSION);
+ fprintf(context->trace_file, "File format: 4\n");
+
+ str_time = xdebug_get_time();
+ fprintf(context->trace_file, "TRACE START [%s]\n", str_time);
+ fflush(context->trace_file);
+ xdfree(str_time);
+}
+
+void xdebug_trace_computerized_write_footer(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt;
+ char *str_time;
+ double u_time;
+ char *tmp;
+
+ u_time = xdebug_get_utime();
+ tmp = xdebug_sprintf("\t\t\t%f\t", u_time - XG(start_time));
+ fprintf(context->trace_file, "%s", tmp);
+ xdfree(tmp);
+#if HAVE_PHP_MEMORY_USAGE
+ fprintf(context->trace_file, "%lu", XG_MEMORY_USAGE());
+#else
+ fprintf(context->trace_file, "");
+#endif
+ fprintf(context->trace_file, "\n");
+ str_time = xdebug_get_time();
+
+ fprintf(context->trace_file, "TRACE END [%s]\n\n", str_time);
+ fflush(context->trace_file);
+ xdfree(str_time);
+}
+
+char *xdebug_trace_computerized_get_filename(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt;
+
+ return context->trace_filename;
+}
+
+static char *render_variable(zval *var, int type TSRMLS_DC)
+{
+ char *tmp_value = NULL;
+
+ switch (XG(collect_params)) {
+ case 1: /* synopsis */
+ case 2:
+ tmp_value = xdebug_get_zval_synopsis(var, 0, NULL);
+ break;
+ case 3: /* full */
+ case 4: /* full (with var) */
+ default:
+ tmp_value = xdebug_get_zval_value(var, 0, NULL);
+ break;
+ case 5: /* serialized */
+ tmp_value = xdebug_get_zval_value_serialized(var, 0, NULL TSRMLS_CC);
+ break;
+ }
+
+ return tmp_value;
+}
+
+
+void xdebug_trace_computerized_function_entry(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC)
+{
+ xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt;
+ char *tmp_name;
+ xdebug_str str = {0, 0, NULL};
+
+ xdebug_str_add(&str, xdebug_sprintf("%d\t", fse->level), 1);
+ xdebug_str_add(&str, xdebug_sprintf("%d\t", function_nr), 1);
+
+ tmp_name = xdebug_show_fname(fse->function, 0, 0 TSRMLS_CC);
+
+ xdebug_str_add(&str, "0\t", 0);
+ xdebug_str_add(&str, xdebug_sprintf("%f\t", fse->time - XG(start_time)), 1);
+#if HAVE_PHP_MEMORY_USAGE
+ xdebug_str_add(&str, xdebug_sprintf("%lu\t", fse->memory), 1);
+#else
+ xdebug_str_add(&str, "\t", 0);
+#endif
+ xdebug_str_add(&str, xdebug_sprintf("%s\t", tmp_name), 1);
+ xdebug_str_add(&str, xdebug_sprintf("%d\t", fse->user_defined == XDEBUG_EXTERNAL ? 1 : 0), 1);
+ xdfree(tmp_name);
+
+ if (fse->include_filename) {
+ if (fse->function.type == XFUNC_EVAL) {
+ int tmp_len;
+
+ char *escaped;
+ escaped = php_addcslashes(fse->include_filename, strlen(fse->include_filename), &tmp_len, 0, "'\\\0..\37", 6 TSRMLS_CC);
+ xdebug_str_add(&str, xdebug_sprintf("'%s'", escaped), 1);
+ efree(escaped);
+ } else {
+ xdebug_str_add(&str, fse->include_filename, 0);
+ }
+ }
+
+ /* Filename and Lineno (9, 10) */
+ xdebug_str_add(&str, xdebug_sprintf("\t%s\t%d", fse->filename, fse->lineno), 1);
+
+
+ if (XG(collect_params) > 0) {
+ unsigned int j = 0; /* Counter */
+
+ /* Nr of arguments (11) */
+ xdebug_str_add(&str, xdebug_sprintf("\t%d", fse->varc), 1);
+
+ /* Arguments (12-...) */
+ for (j = 0; j < fse->varc; j++) {
+ char *tmp_value;
+
+ xdebug_str_addl(&str, "\t", 1, 0);
+
+ if (fse->var[j].is_variadic) {
+ xdebug_str_addl(&str, "...\t", 4, 0);
+ }
+
+ if (fse->var[j].name && XG(collect_params) == 4) {
+ xdebug_str_add(&str, xdebug_sprintf("$%s = ", fse->var[j].name), 1);
+ }
+
+ tmp_value = render_variable(fse->var[j].addr, XG(collect_params) TSRMLS_CC);
+
+ if (tmp_value) {
+ xdebug_str_add(&str, tmp_value, 1);
+ } else {
+ xdebug_str_add(&str, "???", 0);
+ }
+ }
+ }
+
+ /* Trailing \n */
+ xdebug_str_add(&str, "\n", 0);
+
+ fprintf(context->trace_file, "%s", str.d);
+ fflush(context->trace_file);
+ xdfree(str.d);
+}
+
+void xdebug_trace_computerized_function_exit(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC)
+{
+ xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt;
+ xdebug_str str = {0, 0, NULL};
+
+ xdebug_str_add(&str, xdebug_sprintf("%d\t", fse->level), 1);
+ xdebug_str_add(&str, xdebug_sprintf("%d\t", function_nr), 1);
+
+ xdebug_str_add(&str, "1\t", 0);
+ xdebug_str_add(&str, xdebug_sprintf("%f\t", xdebug_get_utime() - XG(start_time)), 1);
+#if HAVE_PHP_MEMORY_USAGE
+ xdebug_str_add(&str, xdebug_sprintf("%lu\n", XG_MEMORY_USAGE()), 1);
+#else
+ xdebug_str_add(&str, "\n", 0);
+#endif
+
+ fprintf(context->trace_file, "%s", str.d);
+ fflush(context->trace_file);
+ xdfree(str.d);
+}
+
+void xdebug_trace_computerized_function_return_value(void *ctxt, function_stack_entry *fse, int function_nr, zval *return_value TSRMLS_DC)
+{
+ xdebug_trace_computerized_context *context = (xdebug_trace_computerized_context*) ctxt;
+ xdebug_str str = {0, 0, NULL};
+ char *tmp_value = NULL;
+
+ xdebug_str_add(&str, xdebug_sprintf("%d\t", fse->level), 1);
+ xdebug_str_add(&str, xdebug_sprintf("%d\t", function_nr), 1);
+ xdebug_str_add(&str, "R\t\t\t", 0);
+
+ tmp_value = render_variable(return_value, XG(collect_params) TSRMLS_CC);
+
+ if (tmp_value) {
+ xdebug_str_add(&str, tmp_value, 1);
+ } else {
+ xdebug_str_add(&str, "???", 0);
+ }
+ xdebug_str_addl(&str, "\n", 2, 0);
+
+ fprintf(context->trace_file, "%s", str.d);
+ fflush(context->trace_file);
+ xdfree(str.d);
+}
+
+xdebug_trace_handler_t xdebug_trace_handler_computerized =
+{
+ xdebug_trace_computerized_init,
+ xdebug_trace_computerized_deinit,
+ xdebug_trace_computerized_write_header,
+ xdebug_trace_computerized_write_footer,
+ xdebug_trace_computerized_get_filename,
+ xdebug_trace_computerized_function_entry,
+ xdebug_trace_computerized_function_exit,
+ xdebug_trace_computerized_function_return_value,
+#if PHP_VERSION_ID >= 50500
+ NULL /* xdebug_trace_computerized_generator_return_value */,
+#endif
+ NULL /* xdebug_trace_computerized_assignment */
+};
diff --git a/xdebug_trace_computerized.h b/xdebug_trace_computerized.h
new file mode 100644
index 000000000..b5ef2d534
--- /dev/null
+++ b/xdebug_trace_computerized.h
@@ -0,0 +1,30 @@
+/*
+ +----------------------------------------------------------------------+
+ | Xdebug |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2002-2014 Derick Rethans |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 1.0 of the Xdebug license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://xdebug.derickrethans.nl/license.php |
+ | If you did not receive a copy of the Xdebug license and are unable |
+ | to obtain it through the world-wide-web, please send a note to |
+ | xdebug@derickrethans.nl so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans |
+ +----------------------------------------------------------------------+
+ */
+#ifndef XDEBUG_TRACE_COMPUTERIZED_H
+#define XDEBUG_TRACE_COMPUTERIZED_H
+
+#include "xdebug_tracing.h"
+
+typedef struct _xdebug_trace_computerized_context
+{
+ FILE *trace_file;
+ char *trace_filename;
+} xdebug_trace_computerized_context;
+
+extern xdebug_trace_handler_t xdebug_trace_handler_computerized;
+#endif
diff --git a/xdebug_trace_html.c b/xdebug_trace_html.c
new file mode 100644
index 000000000..c3465c54c
--- /dev/null
+++ b/xdebug_trace_html.c
@@ -0,0 +1,136 @@
+/*
+ +----------------------------------------------------------------------+
+ | Xdebug |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2002-2014 Derick Rethans |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 1.0 of the Xdebug license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://xdebug.derickrethans.nl/license.php |
+ | If you did not receive a copy of the Xdebug license and are unable |
+ | to obtain it through the world-wide-web, please send a note to |
+ | xdebug@derickrethans.nl so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans |
+ +----------------------------------------------------------------------+
+ */
+#include "xdebug_trace_html.h"
+#include "xdebug_var.h"
+
+extern ZEND_DECLARE_MODULE_GLOBALS(xdebug);
+
+void *xdebug_trace_html_init(char *fname, long options TSRMLS_DC)
+{
+ xdebug_trace_html_context *tmp_html_context;
+ char *used_fname;
+
+ tmp_html_context = xdmalloc(sizeof(xdebug_trace_html_context));
+ tmp_html_context->trace_file = xdebug_trace_open_file(fname, options, (char**) &used_fname TSRMLS_CC);
+ tmp_html_context->trace_filename = used_fname;
+
+ return tmp_html_context;
+}
+
+void xdebug_trace_html_deinit(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_html_context *context = (xdebug_trace_html_context*) ctxt;
+
+ fclose(context->trace_file);
+ context->trace_file = NULL;
+ xdfree(context->trace_filename);
+
+ xdfree(context);
+}
+
+void xdebug_trace_html_write_header(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_html_context *context = (xdebug_trace_html_context*) ctxt;
+
+ fprintf(context->trace_file, "\n");
+ fprintf(context->trace_file, "\t# | Time | ");
+#if HAVE_PHP_MEMORY_USAGE
+ fprintf(context->trace_file, "Mem | ");
+#endif
+ fprintf(context->trace_file, "Function | Location |
\n");
+ fflush(context->trace_file);
+}
+
+void xdebug_trace_html_write_footer(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_html_context *context = (xdebug_trace_html_context*) ctxt;
+
+ fprintf(context->trace_file, "
\n");
+ fflush(context->trace_file);
+}
+
+char *xdebug_trace_html_get_filename(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_html_context *context = (xdebug_trace_html_context*) ctxt;
+
+ return context->trace_filename;
+}
+
+void xdebug_trace_html_function_entry(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC)
+{
+ xdebug_trace_html_context *context = (xdebug_trace_html_context*) ctxt;
+ char *tmp_name;
+ unsigned int j;
+ xdebug_str str = {0, 0, NULL};
+
+ xdebug_str_add(&str, "\t", 0);
+ xdebug_str_add(&str, xdebug_sprintf("%d | ", function_nr), 1);
+ xdebug_str_add(&str, xdebug_sprintf("%0.6f | ", fse->time - XG(start_time)), 1);
+#if HAVE_PHP_MEMORY_USAGE
+ xdebug_str_add(&str, xdebug_sprintf("%lu | ", fse->memory), 1);
+#endif
+ xdebug_str_add(&str, "", 0);
+ for (j = 0; j < fse->level - 1; j++) {
+ xdebug_str_add(&str, " ", 0);
+ }
+ xdebug_str_add(&str, "-> | ", 0);
+
+ tmp_name = xdebug_show_fname(fse->function, 0, 0 TSRMLS_CC);
+ xdebug_str_add(&str, xdebug_sprintf("%s(", tmp_name), 1);
+ xdfree(tmp_name);
+
+ if (fse->include_filename) {
+ if (fse->function.type == XFUNC_EVAL) {
+ char *joined;
+ xdebug_arg *parts = (xdebug_arg*) xdmalloc(sizeof(xdebug_arg));
+
+ xdebug_arg_init(parts);
+ xdebug_explode("\n", fse->include_filename, parts, 99999);
+ joined = xdebug_join(" ", parts, 0, 99999);
+ xdebug_arg_dtor(parts);
+
+ xdebug_str_add(&str, xdebug_sprintf("'%s'", joined), 1);
+ xdfree(joined);
+ } else {
+ xdebug_str_add(&str, fse->include_filename, 0);
+ }
+ }
+
+ xdebug_str_add(&str, xdebug_sprintf(") | %s:%d | ", fse->filename, fse->lineno), 1);
+ xdebug_str_add(&str, "
\n", 0);
+
+ fprintf(context->trace_file, "%s", str.d);
+ fflush(context->trace_file);
+ xdfree(str.d);
+}
+
+xdebug_trace_handler_t xdebug_trace_handler_html =
+{
+ xdebug_trace_html_init,
+ xdebug_trace_html_deinit,
+ xdebug_trace_html_write_header,
+ xdebug_trace_html_write_footer,
+ xdebug_trace_html_get_filename,
+ xdebug_trace_html_function_entry,
+ NULL /* xdebug_trace_html_function_exit */,
+ NULL /* xdebug_trace_html_function_return_value */,
+#if PHP_VERSION_ID >= 50500
+ NULL /* xdebug_trace_html_generator_return_value */,
+#endif
+ NULL /* xdebug_trace_html_assignment */
+};
diff --git a/xdebug_trace_html.h b/xdebug_trace_html.h
new file mode 100644
index 000000000..52d506bcd
--- /dev/null
+++ b/xdebug_trace_html.h
@@ -0,0 +1,30 @@
+/*
+ +----------------------------------------------------------------------+
+ | Xdebug |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2002-2014 Derick Rethans |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 1.0 of the Xdebug license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://xdebug.derickrethans.nl/license.php |
+ | If you did not receive a copy of the Xdebug license and are unable |
+ | to obtain it through the world-wide-web, please send a note to |
+ | xdebug@derickrethans.nl so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans |
+ +----------------------------------------------------------------------+
+ */
+#ifndef XDEBUG_TRACE_HTML_H
+#define XDEBUG_TRACE_HTML_H
+
+#include "xdebug_tracing.h"
+
+typedef struct _xdebug_trace_html_context
+{
+ FILE *trace_file;
+ char *trace_filename;
+} xdebug_trace_html_context;
+
+extern xdebug_trace_handler_t xdebug_trace_handler_html;
+#endif
diff --git a/xdebug_trace_textual.c b/xdebug_trace_textual.c
new file mode 100644
index 000000000..b46ef81bb
--- /dev/null
+++ b/xdebug_trace_textual.c
@@ -0,0 +1,311 @@
+/*
+ +----------------------------------------------------------------------+
+ | Xdebug |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2002-2014 Derick Rethans |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 1.0 of the Xdebug license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://xdebug.derickrethans.nl/license.php |
+ | If you did not receive a copy of the Xdebug license and are unable |
+ | to obtain it through the world-wide-web, please send a note to |
+ | xdebug@derickrethans.nl so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans |
+ +----------------------------------------------------------------------+
+ */
+#include "xdebug_tracing.h"
+#include "xdebug_trace_textual.h"
+#include "xdebug_var.h"
+#include "ext/standard/php_string.h"
+
+extern ZEND_DECLARE_MODULE_GLOBALS(xdebug);
+
+void *xdebug_trace_textual_init(char *fname, long options TSRMLS_DC)
+{
+ xdebug_trace_textual_context *tmp_textual_context;
+ char *used_fname;
+
+ tmp_textual_context = xdmalloc(sizeof(xdebug_trace_textual_context));
+ tmp_textual_context->trace_file = xdebug_trace_open_file(fname, options, (char**) &used_fname TSRMLS_CC);
+ tmp_textual_context->trace_filename = used_fname;
+
+ return tmp_textual_context;
+}
+
+void xdebug_trace_textual_deinit(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
+
+ fclose(context->trace_file);
+ context->trace_file = NULL;
+ xdfree(context->trace_filename);
+
+ xdfree(context);
+}
+
+void xdebug_trace_textual_write_header(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
+ char *str_time;
+
+ str_time = xdebug_get_time();
+ fprintf(context->trace_file, "TRACE START [%s]\n", str_time);
+ fflush(context->trace_file);
+ xdfree(str_time);
+}
+
+void xdebug_trace_textual_write_footer(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
+ char *str_time;
+ double u_time;
+ char *tmp;
+
+ u_time = xdebug_get_utime();
+ tmp = xdebug_sprintf("%10.4f ", u_time - XG(start_time));
+ fprintf(context->trace_file, "%s", tmp);
+ xdfree(tmp);
+#if HAVE_PHP_MEMORY_USAGE
+ fprintf(context->trace_file, "%10zu", XG_MEMORY_USAGE());
+#else
+ fprintf(context->trace_file, "%10u", 0);
+#endif
+ fprintf(context->trace_file, "\n");
+ str_time = xdebug_get_time();
+ fprintf(context->trace_file, "TRACE END [%s]\n\n", str_time);
+ fflush(context->trace_file);
+ xdfree(str_time);
+}
+
+char *xdebug_trace_textual_get_filename(void *ctxt TSRMLS_DC)
+{
+ xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
+
+ return context->trace_filename;
+}
+
+void xdebug_trace_textual_function_entry(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC)
+{
+ xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
+ int c = 0; /* Comma flag */
+ unsigned int j = 0; /* Counter */
+ char *tmp_name;
+ xdebug_str str = {0, 0, NULL};
+
+ tmp_name = xdebug_show_fname(fse->function, 0, 0 TSRMLS_CC);
+
+ xdebug_str_add(&str, xdebug_sprintf("%10.4f ", fse->time - XG(start_time)), 1);
+ xdebug_str_add(&str, xdebug_sprintf("%10lu ", fse->memory), 1);
+ if (XG(show_mem_delta)) {
+ xdebug_str_add(&str, xdebug_sprintf("%+8ld ", fse->memory - fse->prev_memory), 1);
+ }
+ for (j = 0; j < fse->level; j++) {
+ xdebug_str_addl(&str, " ", 2, 0);
+ }
+ xdebug_str_add(&str, xdebug_sprintf("-> %s(", tmp_name), 1);
+
+ xdfree(tmp_name);
+
+ /* Printing vars */
+ if (XG(collect_params) > 0) {
+ int variadic_opened = 0;
+ int variadic_count = 0;
+
+ for (j = 0; j < fse->varc; j++) {
+ char *tmp_value;
+
+ if (c) {
+ xdebug_str_addl(&str, ", ", 2, 0);
+ } else {
+ c = 1;
+ }
+
+ if (fse->var[j].is_variadic && fse->var[j].addr) {
+ xdebug_str_add(&str, "...", 0);
+ variadic_opened = 1;
+ }
+
+ if (fse->var[j].name && XG(collect_params) == 4) {
+ xdebug_str_add(&str, xdebug_sprintf("$%s = ", fse->var[j].name), 1);
+ }
+
+ if (fse->var[j].is_variadic && fse->var[j].addr) {
+ xdebug_str_add(&str, "variadic(", 0);
+ }
+
+ if (variadic_opened && XG(collect_params) != 5) {
+ xdebug_str_add(&str, xdebug_sprintf("%d => ", variadic_count++), 1);
+ }
+
+ switch (XG(collect_params)) {
+ case 1: /* synopsis */
+ case 2:
+ tmp_value = xdebug_get_zval_synopsis(fse->var[j].addr, 0, NULL);
+ break;
+ case 3: /* full */
+ case 4: /* full (with var) */
+ default:
+ tmp_value = xdebug_get_zval_value(fse->var[j].addr, 0, NULL);
+ break;
+ case 5: /* serialized */
+ tmp_value = xdebug_get_zval_value_serialized(fse->var[j].addr, 0, NULL TSRMLS_CC);
+ break;
+ }
+ if (tmp_value) {
+ xdebug_str_add(&str, tmp_value, 1);
+ } else {
+ xdebug_str_add(&str, "???", 0);
+ }
+ }
+
+ if (variadic_opened) {
+ xdebug_str_add(&str, ")", 0);
+ }
+ }
+
+ if (fse->include_filename) {
+ if (fse->function.type == XFUNC_EVAL) {
+ int tmp_len;
+
+ char *escaped;
+ escaped = php_addcslashes(fse->include_filename, strlen(fse->include_filename), &tmp_len, 0, "'\\\0..\37", 6 TSRMLS_CC);
+ xdebug_str_add(&str, xdebug_sprintf("'%s'", escaped), 1);
+ efree(escaped);
+ } else {
+ xdebug_str_add(&str, fse->include_filename, 0);
+ }
+ }
+
+ xdebug_str_add(&str, xdebug_sprintf(") %s:%d\n", fse->filename, fse->lineno), 1);
+
+ fprintf(context->trace_file, "%s", str.d);
+ fflush(context->trace_file);
+
+ xdfree(str.d);
+}
+
+/* Used for normal return values, and generator return values */
+static void xdebug_return_trace_stack_common(xdebug_str *str, function_stack_entry *fse TSRMLS_DC)
+{
+ unsigned int j = 0; /* Counter */
+
+ xdebug_str_add(str, xdebug_sprintf("%10.4f ", xdebug_get_utime() - XG(start_time)), 1);
+#if HAVE_PHP_MEMORY_USAGE
+ xdebug_str_add(str, xdebug_sprintf("%10lu ", XG_MEMORY_USAGE()), 1);
+#endif
+
+ if (XG(show_mem_delta)) {
+ xdebug_str_addl(str, " ", 8, 0);
+ }
+ for (j = 0; j < fse->level; j++) {
+ xdebug_str_addl(str, " ", 2, 0);
+ }
+ xdebug_str_addl(str, " >=> ", 5, 0);
+}
+
+
+void xdebug_trace_textual_function_return_value(void *ctxt, function_stack_entry *fse, int function_nr, zval *return_value TSRMLS_DC)
+{
+ xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
+ xdebug_str str = {0, 0, NULL};
+ char *tmp_value;
+
+ xdebug_return_trace_stack_common(&str, fse TSRMLS_CC);
+
+ tmp_value = xdebug_get_zval_value(return_value, 0, NULL);
+ if (tmp_value) {
+ xdebug_str_add(&str, tmp_value, 1);
+ }
+ xdebug_str_addl(&str, "\n", 2, 0);
+
+ fprintf(context->trace_file, "%s", str.d);
+ fflush(context->trace_file);
+
+ xdfree(str.d);
+}
+
+#if PHP_VERSION_ID >= 50500
+void xdebug_trace_textual_generator_return_value(void *ctxt, function_stack_entry *fse, int function_nr, zend_generator *generator TSRMLS_DC)
+{
+ xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
+ xdebug_str str = {0, 0, NULL};
+ char *tmp_value = NULL;
+
+ /* Generator key */
+ tmp_value = xdebug_get_zval_value(generator->key, 0, NULL);
+ if (tmp_value) {
+ xdebug_return_trace_stack_common(&str, fse 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);
+
+ fprintf(context->trace_file, "%s", str.d);
+ fflush(context->trace_file);
+
+ xdfree(str.d);
+ }
+}
+#endif
+
+void xdebug_trace_textual_assignment(void *ctxt, function_stack_entry *fse, char *full_varname, zval *retval, char *op, char *filename, int lineno TSRMLS_DC)
+{
+ xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
+ unsigned int j = 0;
+ xdebug_str str = {0, 0, NULL};
+ char *tmp_value;
+
+ xdebug_str_addl(&str, " ", 20, 0);
+ if (XG(show_mem_delta)) {
+ xdebug_str_addl(&str, " ", 8, 0);
+ }
+ for (j = 0; j <= fse->level; j++) {
+ xdebug_str_addl(&str, " ", 2, 0);
+ }
+ xdebug_str_addl(&str, " => ", 6, 0);
+
+ xdebug_str_add(&str, full_varname, 0);
+
+ if (op[0] != '\0' ) { /* pre/post inc/dec ops are special */
+ xdebug_str_add(&str, xdebug_sprintf(" %s ", op), 1);
+
+ tmp_value = xdebug_get_zval_value(retval, 0, NULL);
+
+ if (tmp_value) {
+ xdebug_str_add(&str, tmp_value, 1);
+ } else {
+ xdebug_str_addl(&str, "NULL", 4, 0);
+ }
+ }
+ xdebug_str_add(&str, xdebug_sprintf(" %s:%d\n", filename, lineno), 1);
+
+ fprintf(context->trace_file, "%s", str.d);
+ fflush(context->trace_file);
+
+ xdfree(str.d);
+}
+
+xdebug_trace_handler_t xdebug_trace_handler_textual =
+{
+ xdebug_trace_textual_init,
+ xdebug_trace_textual_deinit,
+ xdebug_trace_textual_write_header,
+ xdebug_trace_textual_write_footer,
+ xdebug_trace_textual_get_filename,
+ xdebug_trace_textual_function_entry,
+ NULL /*xdebug_trace_textual_function_exit */,
+ xdebug_trace_textual_function_return_value,
+#if PHP_VERSION_ID >= 50500
+ xdebug_trace_textual_generator_return_value,
+#endif
+ xdebug_trace_textual_assignment
+};
diff --git a/xdebug_trace_textual.h b/xdebug_trace_textual.h
new file mode 100644
index 000000000..a59234b75
--- /dev/null
+++ b/xdebug_trace_textual.h
@@ -0,0 +1,30 @@
+/*
+ +----------------------------------------------------------------------+
+ | Xdebug |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2002-2014 Derick Rethans |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 1.0 of the Xdebug license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://xdebug.derickrethans.nl/license.php |
+ | If you did not receive a copy of the Xdebug license and are unable |
+ | to obtain it through the world-wide-web, please send a note to |
+ | xdebug@derickrethans.nl so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans |
+ +----------------------------------------------------------------------+
+ */
+#ifndef XDEBUG_TRACE_TEXTUAL_H
+#define XDEBUG_TRACE_TEXTUAL_H
+
+#include "xdebug_tracing.h"
+
+typedef struct _xdebug_trace_textual_context
+{
+ FILE *trace_file;
+ char *trace_filename;
+} xdebug_trace_textual_context;
+
+extern xdebug_trace_handler_t xdebug_trace_handler_textual;
+#endif
diff --git a/xdebug_tracing.c b/xdebug_tracing.c
index 02c9fc182..0ab4efe15 100644
--- a/xdebug_tracing.c
+++ b/xdebug_tracing.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Xdebug |
+----------------------------------------------------------------------+
- | Copyright (c) 2002-2013 Derick Rethans |
+ | Copyright (c) 2002-2014 Derick Rethans |
+----------------------------------------------------------------------+
| This source file is subject to version 1.0 of the Xdebug license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -12,7 +12,7 @@
| to obtain it through the world-wide-web, please send a note to |
| xdebug@derickrethans.nl so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Derick Rethans |
+ | Authors: Derick Rethans |
+----------------------------------------------------------------------+
*/
#include "php_xdebug.h"
@@ -22,449 +22,85 @@
#include "xdebug_var.h"
#include "ext/standard/php_string.h"
-ZEND_EXTERN_MODULE_GLOBALS(xdebug)
-
-static char* return_trace_stack_frame_begin(function_stack_entry* i, int fnr TSRMLS_DC);
-static char* return_trace_stack_frame_end(function_stack_entry* i, int fnr TSRMLS_DC);
-
-void xdebug_trace_function_begin(function_stack_entry *fse, int function_nr TSRMLS_DC)
-{
- if (XG(do_trace) && XG(trace_file)) {
- char *t = return_trace_stack_frame_begin(fse, function_nr TSRMLS_CC);
- if (fprintf(XG(trace_file), "%s", t) < 0) {
- fclose(XG(trace_file));
- XG(trace_file) = NULL;
- } else {
- fflush(XG(trace_file));
- }
- xdfree(t);
- }
-}
-
-void xdebug_trace_function_end(function_stack_entry *fse, int function_nr TSRMLS_DC)
-{
- if (XG(do_trace) && XG(trace_file)) {
- char *t = return_trace_stack_frame_end(fse, function_nr TSRMLS_CC);
- if (fprintf(XG(trace_file), "%s", t) < 0) {
- fclose(XG(trace_file));
- XG(trace_file) = NULL;
- } else {
- fflush(XG(trace_file));
- }
- xdfree(t);
- }
-}
-
-
-char* xdebug_return_trace_assignment(function_stack_entry *i, char *varname, zval *retval, char *op, char *filename, int lineno TSRMLS_DC)
-{
- unsigned int j = 0;
- xdebug_str str = {0, 0, NULL};
- char *tmp_value;
-
- if (XG(trace_format) != 0) {
- return xdstrdup("");
- }
-
- 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, " => ", 6, 0);
-
- xdebug_str_add(&str, varname, 0);
-
- if (op[0] != '\0' ) { /* pre/post inc/dec ops are special */
- xdebug_str_add(&str, xdebug_sprintf(" %s ", op), 1);
-
- tmp_value = xdebug_get_zval_value(retval, 0, NULL);
-
- if (tmp_value) {
- xdebug_str_add(&str, tmp_value, 1);
- } else {
- xdebug_str_addl(&str, "NULL", 4, 0);
- }
- }
- xdebug_str_add(&str, xdebug_sprintf(" %s:%d\n", filename, lineno), 1);
-
- return str.d;
-}
-
-static void xdebug_return_trace_stack_common(xdebug_str *str, function_stack_entry *i TSRMLS_DC)
-{
- unsigned int j = 0; /* Counter */
-
- xdebug_str_add(str, xdebug_sprintf("%10.4f ", xdebug_get_utime() - XG(start_time)), 1);
-#if HAVE_PHP_MEMORY_USAGE
- xdebug_str_add(str, xdebug_sprintf("%10lu ", XG_MEMORY_USAGE()), 1);
-#endif
+#include "xdebug_tracing.h"
+#include "xdebug_trace_textual.h"
+#include "xdebug_trace_computerized.h"
+#include "xdebug_trace_html.h"
- 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, " >=> ", 5, 0);
-}
+ZEND_EXTERN_MODULE_GLOBALS(xdebug)
-static char* return_trace_stack_retval_normal(function_stack_entry* i, zval* retval TSRMLS_DC)
+xdebug_trace_handler_t *xdebug_select_trace_handler(int options TSRMLS_DC)
{
- xdebug_str str = {0, 0, NULL};
- char *tmp_value;
-
- xdebug_return_trace_stack_common(&str, i TSRMLS_CC);
+ xdebug_trace_handler_t *tmp;
- tmp_value = xdebug_get_zval_value(retval, 0, NULL);
- if (tmp_value) {
- xdebug_str_add(&str, tmp_value, 1);
+ switch (XG(trace_format)) {
+ case 0: tmp = &xdebug_trace_handler_textual; break;
+ case 1: tmp = &xdebug_trace_handler_computerized; break;
+ case 2: tmp = &xdebug_trace_handler_html; break;
}
- xdebug_str_addl(&str, "\n", 2, 0);
-
- return str.d;
-}
-static char *render_variable(zval *var, int type TSRMLS_DC)
-{
- char *tmp_value = NULL;
-
- switch (XG(collect_params)) {
- case 1: /* synopsis */
- case 2:
- tmp_value = xdebug_get_zval_synopsis(var, 0, NULL);
- break;
- case 3: /* full */
- case 4: /* full (with var) */
- default:
- tmp_value = xdebug_get_zval_value(var, 0, NULL);
- break;
- case 5: /* serialized */
- tmp_value = xdebug_get_zval_value_serialized(var, 0, NULL TSRMLS_CC);
- break;
+ if (options & XDEBUG_TRACE_OPTION_COMPUTERIZED) {
+ tmp = &xdebug_trace_handler_computerized;
}
-
- return tmp_value;
-}
-
-static char* return_trace_stack_retval_computerized(function_stack_entry* i, int fnr, zval* retval TSRMLS_DC)
-{
- xdebug_str str = {0, 0, NULL};
- char *tmp_value = NULL;
-
- xdebug_str_add(&str, xdebug_sprintf("%d\t", i->level), 1);
- xdebug_str_add(&str, xdebug_sprintf("%d\t", fnr), 1);
- xdebug_str_add(&str, "R\t\t\t", 0);
-
- tmp_value = render_variable(retval, XG(collect_params) TSRMLS_CC);
-
- if (tmp_value) {
- xdebug_str_add(&str, tmp_value, 1);
- } else {
- xdebug_str_add(&str, "???", 0);
+ if (options & XDEBUG_TRACE_OPTION_HTML) {
+ tmp = &xdebug_trace_handler_html;
}
- xdebug_str_addl(&str, "\n", 2, 0);
- return str.d;
+ return tmp;
}
-char* xdebug_return_trace_stack_retval(function_stack_entry* i, int fnr, zval* retval TSRMLS_DC)
+FILE *xdebug_trace_open_file(char *fname, long options, char **used_fname TSRMLS_DC)
{
- switch (XG(trace_format)) {
- case 0:
- return return_trace_stack_retval_normal(i, retval TSRMLS_CC);
- case 1:
- return return_trace_stack_retval_computerized(i, fnr, retval TSRMLS_CC);
- default:
- return xdstrdup("");
- }
-}
-
-#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);
+ FILE *file;
+ char *filename;
- 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;
+ if (fname && strlen(fname)) {
+ filename = xdstrdup(fname);
} else {
- return xdstrdup("");
- }
-}
-#endif
-
-static char* return_trace_stack_frame_begin_normal(function_stack_entry* i TSRMLS_DC)
-{
- int c = 0; /* Comma flag */
- unsigned int j = 0; /* Counter */
- char *tmp_name;
- xdebug_str str = {0, 0, NULL};
-
- tmp_name = xdebug_show_fname(i->function, 0, 0 TSRMLS_CC);
-
- xdebug_str_add(&str, xdebug_sprintf("%10.4f ", i->time - XG(start_time)), 1);
- xdebug_str_add(&str, xdebug_sprintf("%10lu ", i->memory), 1);
- if (XG(show_mem_delta)) {
- xdebug_str_add(&str, xdebug_sprintf("%+8ld ", i->memory - i->prev_memory), 1);
- }
- for (j = 0; j < i->level; j++) {
- xdebug_str_addl(&str, " ", 2, 0);
- }
- xdebug_str_add(&str, xdebug_sprintf("-> %s(", tmp_name), 1);
-
- xdfree(tmp_name);
-
- /* Printing vars */
- if (XG(collect_params) > 0) {
- int variadic_opened = 0;
- int variadic_count = 0;
-
- for (j = 0; j < i->varc; j++) {
- char *tmp_value;
-
- if (c) {
- xdebug_str_addl(&str, ", ", 2, 0);
- } else {
- c = 1;
- }
-
- if (i->var[j].is_variadic && i->var[j].addr) {
- xdebug_str_add(&str, "...", 0);
- variadic_opened = 1;
- }
-
- if (i->var[j].name && XG(collect_params) == 4) {
- xdebug_str_add(&str, xdebug_sprintf("$%s = ", i->var[j].name), 1);
- }
-
- if (i->var[j].is_variadic && i->var[j].addr) {
- xdebug_str_add(&str, "variadic(", 0);
- }
-
- if (variadic_opened && XG(collect_params) != 5) {
- xdebug_str_add(&str, xdebug_sprintf("%d => ", variadic_count++), 1);
- }
-
- switch (XG(collect_params)) {
- case 1: /* synopsis */
- case 2:
- tmp_value = xdebug_get_zval_synopsis(i->var[j].addr, 0, NULL);
- break;
- case 3: /* full */
- case 4: /* full (with var) */
- default:
- tmp_value = xdebug_get_zval_value(i->var[j].addr, 0, NULL);
- break;
- case 5: /* serialized */
- tmp_value = xdebug_get_zval_value_serialized(i->var[j].addr, 0, NULL TSRMLS_CC);
- break;
- }
- if (tmp_value) {
- xdebug_str_add(&str, tmp_value, 1);
- } else {
- xdebug_str_add(&str, "???", 0);
- }
- }
-
- if (variadic_opened) {
- xdebug_str_add(&str, ")", 0);
+ if (!strlen(XG(trace_output_name)) ||
+ xdebug_format_output_filename(&fname, XG(trace_output_name), NULL) <= 0
+ ) {
+ /* Invalid or empty xdebug.trace_output_name */
+ return NULL;
}
- }
-
- if (i->include_filename) {
- if (i->function.type == XFUNC_EVAL) {
- int tmp_len;
-
- char *escaped;
- escaped = php_addcslashes(i->include_filename, strlen(i->include_filename), &tmp_len, 0, "'\\\0..\37", 6 TSRMLS_CC);
- xdebug_str_add(&str, xdebug_sprintf("'%s'", escaped), 1);
- efree(escaped);
+ if (IS_SLASH(XG(trace_output_dir)[strlen(XG(trace_output_dir)) - 1])) {
+ filename = xdebug_sprintf("%s%s", XG(trace_output_dir), fname);
} else {
- xdebug_str_add(&str, i->include_filename, 0);
+ filename = xdebug_sprintf("%s%c%s", XG(trace_output_dir), DEFAULT_SLASH, fname);
}
+ xdfree(fname);
}
-
- xdebug_str_add(&str, xdebug_sprintf(") %s:%d\n", i->filename, i->lineno), 1);
-
- return str.d;
-}
-
-#define return_trace_stack_frame_begin_computerized(i,f) return_trace_stack_frame_computerized((i), (f), 0 TSRMLS_CC)
-#define return_trace_stack_frame_end_computerized(i,f) return_trace_stack_frame_computerized((i), (f), 1 TSRMLS_CC)
-
-static char* return_trace_stack_frame_computerized(function_stack_entry* i, int fnr, int whence TSRMLS_DC)
-{
- char *tmp_name;
- xdebug_str str = {0, 0, NULL};
-
- xdebug_str_add(&str, xdebug_sprintf("%d\t", i->level), 1);
- xdebug_str_add(&str, xdebug_sprintf("%d\t", fnr), 1);
- if (whence == 0) { /* start */
- tmp_name = xdebug_show_fname(i->function, 0, 0 TSRMLS_CC);
-
- xdebug_str_add(&str, "0\t", 0);
- xdebug_str_add(&str, xdebug_sprintf("%f\t", i->time - XG(start_time)), 1);
-#if HAVE_PHP_MEMORY_USAGE
- xdebug_str_add(&str, xdebug_sprintf("%lu\t", i->memory), 1);
-#else
- xdebug_str_add(&str, "\t", 0);
-#endif
- xdebug_str_add(&str, xdebug_sprintf("%s\t", tmp_name), 1);
- xdebug_str_add(&str, xdebug_sprintf("%d\t", i->user_defined == XDEBUG_EXTERNAL ? 1 : 0), 1);
- xdfree(tmp_name);
-
- if (i->include_filename) {
- if (i->function.type == XFUNC_EVAL) {
- int tmp_len;
-
- char *escaped;
- escaped = php_addcslashes(i->include_filename, strlen(i->include_filename), &tmp_len, 0, "'\\\0..\37", 6 TSRMLS_CC);
- xdebug_str_add(&str, xdebug_sprintf("'%s'", escaped), 1);
- efree(escaped);
- } else {
- xdebug_str_add(&str, i->include_filename, 0);
- }
- }
-
- /* Filename and Lineno (9, 10) */
- xdebug_str_add(&str, xdebug_sprintf("\t%s\t%d", i->filename, i->lineno), 1);
-
-
- if (XG(collect_params) > 0) {
- unsigned int j = 0; /* Counter */
-
- /* Nr of arguments (11) */
- xdebug_str_add(&str, xdebug_sprintf("\t%d", i->varc), 1);
-
- /* Arguments (12-...) */
- for (j = 0; j < i->varc; j++) {
- char *tmp_value;
-
- xdebug_str_addl(&str, "\t", 1, 0);
-
- if (i->var[j].is_variadic) {
- xdebug_str_addl(&str, "...\t", 4, 0);
- }
-
- if (i->var[j].name && XG(collect_params) == 4) {
- xdebug_str_add(&str, xdebug_sprintf("$%s = ", i->var[j].name), 1);
- }
-
- tmp_value = render_variable(i->var[j].addr, XG(collect_params) TSRMLS_CC);
-
- if (tmp_value) {
- xdebug_str_add(&str, tmp_value, 1);
- } else {
- xdebug_str_add(&str, "???", 0);
- }
- }
- }
-
- /* Trailing \n */
- xdebug_str_add(&str, "\n", 0);
-
- } else if (whence == 1) { /* end */
- xdebug_str_add(&str, "1\t", 0);
- xdebug_str_add(&str, xdebug_sprintf("%f\t", xdebug_get_utime() - XG(start_time)), 1);
-#if HAVE_PHP_MEMORY_USAGE
- xdebug_str_add(&str, xdebug_sprintf("%lu\n", XG_MEMORY_USAGE()), 1);
-#else
- xdebug_str_add(&str, "\n", 0);
-#endif
+ if (options & XDEBUG_TRACE_OPTION_APPEND) {
+ file = xdebug_fopen(filename, "a", (options & XDEBUG_TRACE_OPTION_NAKED_FILENAME) ? NULL : "xt", used_fname);
+ } else {
+ file = xdebug_fopen(filename, "w", (options & XDEBUG_TRACE_OPTION_NAKED_FILENAME) ? NULL : "xt", used_fname);
}
+ xdfree(filename);
- return str.d;
+ return file;
}
-static char* return_trace_stack_frame_begin_html(function_stack_entry* i, int fnr TSRMLS_DC)
+char* xdebug_start_trace(char* fname, long options TSRMLS_DC)
{
- char *tmp_name;
- unsigned int j;
- xdebug_str str = {0, 0, NULL};
-
- xdebug_str_add(&str, "\t", 0);
- xdebug_str_add(&str, xdebug_sprintf("%d | ", fnr), 1);
- xdebug_str_add(&str, xdebug_sprintf("%0.6f | ", i->time - XG(start_time)), 1);
-#if HAVE_PHP_MEMORY_USAGE
- xdebug_str_add(&str, xdebug_sprintf("%lu | ", i->memory), 1);
-#endif
- xdebug_str_add(&str, "", 0);
- for (j = 0; j < i->level - 1; j++) {
- xdebug_str_add(&str, " ", 0);
- }
- xdebug_str_add(&str, "-> | ", 0);
-
- tmp_name = xdebug_show_fname(i->function, 0, 0 TSRMLS_CC);
- xdebug_str_add(&str, xdebug_sprintf("%s(", tmp_name), 1);
- xdfree(tmp_name);
-
- if (i->include_filename) {
- if (i->function.type == XFUNC_EVAL) {
- char *joined;
- xdebug_arg *parts = (xdebug_arg*) xdmalloc(sizeof(xdebug_arg));
+ XG(trace_handler) = xdebug_select_trace_handler(options TSRMLS_CC);
+ XG(trace_context) = (void*) XG(trace_handler)->init(fname, options TSRMLS_CC);
- xdebug_arg_init(parts);
- xdebug_explode("\n", i->include_filename, parts, 99999);
- joined = xdebug_join(" ", parts, 0, 99999);
- xdebug_arg_dtor(parts);
-
- xdebug_str_add(&str, xdebug_sprintf("'%s'", joined), 1);
- xdfree(joined);
- } else {
- xdebug_str_add(&str, i->include_filename, 0);
- }
+ if (XG(trace_context)) {
+ XG(do_trace) = 1;
+ XG(trace_handler)->write_header(XG(trace_context) TSRMLS_CC);
+ return xdstrdup(XG(trace_handler)->get_filename(XG(trace_context) TSRMLS_CC));
}
- xdebug_str_add(&str, xdebug_sprintf(") | %s:%d | ", i->filename, i->lineno), 1);
- xdebug_str_add(&str, "
\n", 0);
-
- return str.d;
-}
-
-
-static char* return_trace_stack_frame_begin(function_stack_entry* i, int fnr TSRMLS_DC)
-{
- switch (XG(trace_format)) {
- case 0:
- return return_trace_stack_frame_begin_normal(i TSRMLS_CC);
- case 1:
- return return_trace_stack_frame_begin_computerized(i, fnr);
- case 2:
- return return_trace_stack_frame_begin_html(i, fnr TSRMLS_CC);
- default:
- return xdstrdup("");
- }
+ return NULL;
}
-
-static char* return_trace_stack_frame_end(function_stack_entry* i, int fnr TSRMLS_DC)
+void xdebug_stop_trace(TSRMLS_D)
{
- switch (XG(trace_format)) {
- case 1:
- return return_trace_stack_frame_end_computerized(i, fnr);
- default:
- return xdstrdup("");
+ XG(do_trace) = 0;
+ if (XG(trace_context)) {
+ XG(trace_handler)->write_footer(XG(trace_context) TSRMLS_CC);
+ XG(trace_handler)->deinit(XG(trace_context) TSRMLS_CC);
+ XG(trace_context) = NULL;
}
}
@@ -497,105 +133,10 @@ PHP_FUNCTION(xdebug_start_trace)
}
}
-char* xdebug_start_trace(char* fname, long options TSRMLS_DC)
-{
- char *str_time;
- char *filename;
- char *tmp_fname = NULL;
-
- if (fname && strlen(fname)) {
- filename = xdstrdup(fname);
- } else {
- if (!strlen(XG(trace_output_name)) ||
- xdebug_format_output_filename(&fname, XG(trace_output_name), NULL) <= 0
- ) {
- /* Invalid or empty xdebug.trace_output_name */
- return NULL;
- }
- if (IS_SLASH(XG(trace_output_dir)[strlen(XG(trace_output_dir)) - 1])) {
- filename = xdebug_sprintf("%s%s", XG(trace_output_dir), fname);
- } else {
- filename = xdebug_sprintf("%s%c%s", XG(trace_output_dir), DEFAULT_SLASH, fname);
- }
- xdfree(fname);
- }
- if (options & XDEBUG_TRACE_OPTION_APPEND) {
- XG(trace_file) = xdebug_fopen(filename, "a", (options & XDEBUG_TRACE_OPTION_NAKED_FILENAME) ? NULL : "xt", (char**) &tmp_fname);
- } else {
- XG(trace_file) = xdebug_fopen(filename, "w", (options & XDEBUG_TRACE_OPTION_NAKED_FILENAME) ? NULL : "xt", (char**) &tmp_fname);
- }
- xdfree(filename);
- if (options & XDEBUG_TRACE_OPTION_COMPUTERIZED) {
- XG(trace_format) = 1;
- }
- if (options & XDEBUG_TRACE_OPTION_HTML) {
- XG(trace_format) = 2;
- }
- if (XG(trace_file)) {
- if (XG(trace_format) == 1) {
- fprintf(XG(trace_file), "Version: %s\n", XDEBUG_VERSION);
- fprintf(XG(trace_file), "File format: 4\n");
- }
- if (XG(trace_format) == 0 || XG(trace_format) == 1) {
- str_time = xdebug_get_time();
- fprintf(XG(trace_file), "TRACE START [%s]\n", str_time);
- xdfree(str_time);
- }
- if (XG(trace_format) == 2) {
- fprintf(XG(trace_file), "\n");
- fprintf(XG(trace_file), "\t# | Time | ");
-#if HAVE_PHP_MEMORY_USAGE
- fprintf(XG(trace_file), "Mem | ");
-#endif
- fprintf(XG(trace_file), "Function | Location |
\n");
- }
- XG(do_trace) = 1;
- XG(tracefile_name) = tmp_fname;
- return xdstrdup(XG(tracefile_name));
- }
- return NULL;
-}
-
-void xdebug_stop_trace(TSRMLS_D)
-{
- char *str_time;
- double u_time;
- char *tmp;
-
- XG(do_trace) = 0;
- if (XG(trace_file)) {
- if (XG(trace_format) == 0 || XG(trace_format) == 1) {
- u_time = xdebug_get_utime();
- tmp = xdebug_sprintf(XG(trace_format) == 0 ? "%10.4f " : "\t\t\t%f\t", u_time - XG(start_time));
- fprintf(XG(trace_file), "%s", tmp);
- xdfree(tmp);
-#if HAVE_PHP_MEMORY_USAGE
- fprintf(XG(trace_file), XG(trace_format) == 0 ? "%10zu" : "%lu", XG_MEMORY_USAGE());
-#else
- fprintf(XG(trace_file), XG(trace_format) == 0 ? "%10u" : "", 0);
-#endif
- fprintf(XG(trace_file), "\n");
- str_time = xdebug_get_time();
- fprintf(XG(trace_file), "TRACE END [%s]\n\n", str_time);
- xdfree(str_time);
- }
- if (XG(trace_format) == 2) {
- fprintf(XG(trace_file), "
\n");
- }
-
- fclose(XG(trace_file));
- XG(trace_file) = NULL;
- }
- if (XG(tracefile_name)) {
- xdfree(XG(tracefile_name));
- XG(tracefile_name) = NULL;
- }
-}
-
PHP_FUNCTION(xdebug_stop_trace)
{
if (XG(do_trace) == 1) {
- RETVAL_STRING(XG(tracefile_name), 1);
+ RETVAL_STRING(XG(trace_handler)->get_filename(XG(trace_context) TSRMLS_CC), 1);
xdebug_stop_trace(TSRMLS_C);
} else {
RETVAL_FALSE;
@@ -605,8 +146,8 @@ PHP_FUNCTION(xdebug_stop_trace)
PHP_FUNCTION(xdebug_get_tracefile_name)
{
- if (XG(tracefile_name)) {
- RETURN_STRING(XG(tracefile_name), 1);
+ if (XG(do_trace) == 1 && XG(trace_handler) && XG(trace_handler)->get_filename) {
+ RETURN_STRING(XG(trace_handler)->get_filename(XG(trace_context) TSRMLS_CC), 1);
} else {
RETURN_FALSE;
}
diff --git a/xdebug_tracing.h b/xdebug_tracing.h
index 6b7c68234..6078a12a3 100644
--- a/xdebug_tracing.h
+++ b/xdebug_tracing.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Xdebug |
+----------------------------------------------------------------------+
- | Copyright (c) 2002-2013 Derick Rethans |
+ | Copyright (c) 2002-2014 Derick Rethans |
+----------------------------------------------------------------------+
| This source file is subject to version 1.0 of the Xdebug license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -12,18 +12,21 @@
| to obtain it through the world-wide-web, please send a note to |
| xdebug@derickrethans.nl so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Derick Rethans |
+ | Authors: Derick Rethans |
+----------------------------------------------------------------------+
*/
-
#ifndef XDEBUG_TRACING_H
#define XDEBUG_TRACING_H
+#include "php.h"
+#include "php_xdebug.h"
+
char* xdebug_return_trace_stack_retval(function_stack_entry* i, int fnr, 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);
+FILE *xdebug_trace_open_file(char *fname, long options, char **used_fname TSRMLS_DC);
void xdebug_trace_function_begin(function_stack_entry *fse, int function_nr TSRMLS_DC);
void xdebug_trace_function_end(function_stack_entry *fse, int function_nr TSRMLS_DC);