mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Use common formatting for backtraces (#6977)
This makes debug_print_backtrace() use the same formatting as exception
backtraces. The only difference is that the final #{main} is omitted,
because it wouldn't make sense for limited backtraces, and wasn't there
previously either.
This commit is contained in:
@@ -19,8 +19,8 @@ class Test {}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 MyAttribute->__construct() called at [%s031_backtrace.php:12]
|
||||
#1 ReflectionAttribute->newInstance() called at [%s:%d]
|
||||
#0 %s031_backtrace.php(12): MyAttribute->__construct()
|
||||
#1 %s(%d): ReflectionAttribute->newInstance()
|
||||
array(2) {
|
||||
[0]=>
|
||||
array(7) {
|
||||
|
||||
@@ -22,6 +22,6 @@ function GenerateError2($A1)
|
||||
GenerateError2("Test2");
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 userErrorHandler(2, Undefined variable $b, %s, %d) called at [%s:%d]
|
||||
#1 GenerateError1(Test1) called at [%sbug29896.php:16]
|
||||
#2 GenerateError2(Test2) called at [%sbug29896.php:19]
|
||||
#0 %s(%d): userErrorHandler(2, 'Undefined varia...', '%s', %d)
|
||||
#1 %s(%d): GenerateError1('Test1')
|
||||
#2 %s(%d): GenerateError2('Test2')
|
||||
|
||||
@@ -47,15 +47,15 @@ $b->foo();
|
||||
B::bar();
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 A->__construct() called at [%sbug30828.php:30]
|
||||
#1 B->__construct() called at [%sbug30828.php:42]
|
||||
#0 %sbug30828.php(30): A->__construct()
|
||||
#1 %sbug30828.php(42): B->__construct()
|
||||
A->__construct
|
||||
B->__construct
|
||||
#0 A->foo() called at [%sbug30828.php:34]
|
||||
#1 B->foo() called at [%sbug30828.php:43]
|
||||
#0 %sbug30828.php(34): A->foo()
|
||||
#1 %sbug30828.php(43): B->foo()
|
||||
A->foo
|
||||
B->foo
|
||||
#0 A::bar() called at [%sbug30828.php:38]
|
||||
#1 B::bar() called at [%sbug30828.php:44]
|
||||
#0 %sbug30828.php(38): A::bar()
|
||||
#1 %sbug30828.php(44): B::bar()
|
||||
A::bar
|
||||
B::bar
|
||||
|
||||
@@ -27,7 +27,7 @@ $c->Bmethod();
|
||||
$c->t2method();
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 A->Bmethod() called at [%sbug64239_3.php:%d]
|
||||
#0 A->t2method() called at [%sbug64239_3.php:%d]
|
||||
#0 C->Bmethod() called at [%sbug64239_3.php:%d]
|
||||
#0 A->t2method() called at [%sbug64239_3.php:%d]
|
||||
#0 %s(%d): A->Bmethod()
|
||||
#0 %s(%d): A->t2method()
|
||||
#0 %s(%d): C->Bmethod()
|
||||
#0 %s(%d): A->t2method()
|
||||
|
||||
@@ -25,7 +25,7 @@ C::Bmethod();
|
||||
C::t2method();
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 A::Bmethod() called at [%sbug64239_4.php:%d]
|
||||
#0 A::t2method() called at [%sbug64239_4.php:%d]
|
||||
#0 C::Bmethod() called at [%sbug64239_4.php:%d]
|
||||
#0 A::t2method() called at [%sbug64239_4.php:%d]
|
||||
#0 %s(%d): A::Bmethod()
|
||||
#0 %s(%d): A::t2method()
|
||||
#0 %s(%d): C::Bmethod()
|
||||
#0 %s(%d): A::t2method()
|
||||
|
||||
@@ -32,6 +32,6 @@ class dummy {
|
||||
new dummy();
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 dummy->bar() called at [%sbug70156.php:%d]
|
||||
#1 dummy->foo1() called at [%sbug70156.php:%d]
|
||||
#2 dummy->__construct() called at [%sbug70156.php:%d]
|
||||
#0 %s(%d): dummy->bar()
|
||||
#1 %s(%d): dummy->foo1()
|
||||
#2 %s(%d): dummy->__construct()
|
||||
|
||||
@@ -13,4 +13,4 @@ function test() {
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 test(Array ([0] => Array ([0] => a),[1] => b Object ())) called at [%sbug73916.php:%d]
|
||||
#0 %s(%d): test(Array)
|
||||
|
||||
@@ -15,4 +15,4 @@ test(new class {
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 class@anonymous->__destruct() called at [%s:%d]
|
||||
#0 %s(%d): class@anonymous->__destruct()
|
||||
|
||||
@@ -19,8 +19,8 @@ eval("foo();");
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 boo() called at [%s:%d]
|
||||
#1 bar() called at [%s:%d]
|
||||
#2 foo() called at [%s(%d) : eval()'d code:1]
|
||||
#3 eval() called at [%s:%d]
|
||||
#0 %s(%d): boo()
|
||||
#1 %s(%d): bar()
|
||||
#2 %s(%d) : eval()'d code(1): foo()
|
||||
#3 %s(%d): eval()
|
||||
Done
|
||||
|
||||
@@ -29,7 +29,7 @@ Array
|
||||
)
|
||||
|
||||
)
|
||||
#0 {closure}(23) called at [%s:%d]
|
||||
#0 %s(%d): {closure}(23)
|
||||
Array
|
||||
(
|
||||
[0] => Array
|
||||
@@ -65,5 +65,5 @@ Array
|
||||
)
|
||||
|
||||
)
|
||||
#0 {closure}(23) called at [%s:%d]
|
||||
#1 test(Closure Object ()) called at [%s:%d]
|
||||
#0 %s(%d): {closure}(23)
|
||||
#1 %s(%d): test(Object(Closure))
|
||||
|
||||
@@ -45,29 +45,29 @@ foo::statCall("doit", "backtrace_print");
|
||||
?>
|
||||
--EXPECTF--
|
||||
==default
|
||||
#0 doit(a, b, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#1 foo->doCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#2 foo::statCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#0 %sdebug_backtrace_options.php(%d): doit('a', 'b', 'debug_print_bac...')
|
||||
#1 %sdebug_backtrace_options.php(%d): foo->doCall('doit', 'debug_print_bac...')
|
||||
#2 %sdebug_backtrace_options.php(%d): foo::statCall('doit', 'debug_print_bac...')
|
||||
==true
|
||||
#0 doit(a, b, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#1 foo->doCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#2 foo::statCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#0 %sdebug_backtrace_options.php(%d): doit('a', 'b', 'debug_print_bac...')
|
||||
#1 %sdebug_backtrace_options.php(%d): foo->doCall('doit', 'debug_print_bac...')
|
||||
#2 %sdebug_backtrace_options.php(%d): foo::statCall('doit', 'debug_print_bac...')
|
||||
==false
|
||||
#0 doit(a, b, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#1 foo->doCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#2 foo::statCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#0 %sdebug_backtrace_options.php(%d): doit('a', 'b', 'debug_print_bac...')
|
||||
#1 %sdebug_backtrace_options.php(%d): foo->doCall('doit', 'debug_print_bac...')
|
||||
#2 %sdebug_backtrace_options.php(%d): foo::statCall('doit', 'debug_print_bac...')
|
||||
==DEBUG_BACKTRACE_PROVIDE_OBJECT
|
||||
#0 doit(a, b, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#1 foo->doCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#2 foo::statCall(doit, debug_print_backtrace) called at [%sdebug_backtrace_options.php:%d]
|
||||
#0 %sdebug_backtrace_options.php(%d): doit('a', 'b', 'debug_print_bac...')
|
||||
#1 %sdebug_backtrace_options.php(%d): foo->doCall('doit', 'debug_print_bac...')
|
||||
#2 %sdebug_backtrace_options.php(%d): foo::statCall('doit', 'debug_print_bac...')
|
||||
==DEBUG_BACKTRACE_IGNORE_ARGS
|
||||
#0 doit() called at [%sdebug_backtrace_options.php:%d]
|
||||
#1 foo->doCall() called at [%sdebug_backtrace_options.php:%d]
|
||||
#2 foo::statCall() called at [%sdebug_backtrace_options.php:%d]
|
||||
#0 %sdebug_backtrace_options.php(%d): doit()
|
||||
#1 %sdebug_backtrace_options.php(%d): foo->doCall()
|
||||
#2 %sdebug_backtrace_options.php(%d): foo::statCall()
|
||||
==both
|
||||
#0 doit() called at [%sdebug_backtrace_options.php:%d]
|
||||
#1 foo->doCall() called at [%sdebug_backtrace_options.php:%d]
|
||||
#2 foo::statCall() called at [%sdebug_backtrace_options.php:%d]
|
||||
#0 %sdebug_backtrace_options.php(%d): doit()
|
||||
#1 %sdebug_backtrace_options.php(%d): foo->doCall()
|
||||
#2 %sdebug_backtrace_options.php(%d): foo::statCall()
|
||||
==default
|
||||
Array
|
||||
(
|
||||
|
||||
@@ -5,3 +5,4 @@ Calling debug_print_backtrace() from main script
|
||||
debug_print_backtrace();
|
||||
?>
|
||||
--EXPECT--
|
||||
|
||||
|
||||
@@ -12,20 +12,26 @@ function b() {
|
||||
|
||||
function c() {
|
||||
debug_print_backtrace(0, 1);
|
||||
echo "\n";
|
||||
debug_print_backtrace(0, 2);
|
||||
echo "\n";
|
||||
debug_print_backtrace(0, 0);
|
||||
echo "\n";
|
||||
debug_print_backtrace(0, 4);
|
||||
}
|
||||
|
||||
a();
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 c() called at [%sdebug_print_backtrace_limit.php:7]
|
||||
#0 c() called at [%sdebug_print_backtrace_limit.php:7]
|
||||
#1 b() called at [%sdebug_print_backtrace_limit.php:3]
|
||||
#0 c() called at [%sdebug_print_backtrace_limit.php:7]
|
||||
#1 b() called at [%sdebug_print_backtrace_limit.php:3]
|
||||
#2 a() called at [%sdebug_print_backtrace_limit.php:17]
|
||||
#0 c() called at [%sdebug_print_backtrace_limit.php:7]
|
||||
#1 b() called at [%sdebug_print_backtrace_limit.php:3]
|
||||
#2 a() called at [%sdebug_print_backtrace_limit.php:17]
|
||||
#0 %sdebug_print_backtrace_limit.php(7): c()
|
||||
|
||||
#0 %sdebug_print_backtrace_limit.php(7): c()
|
||||
#1 %sdebug_print_backtrace_limit.php(3): b()
|
||||
|
||||
#0 %sdebug_print_backtrace_limit.php(7): c()
|
||||
#1 %sdebug_print_backtrace_limit.php(3): b()
|
||||
#2 %sdebug_print_backtrace_limit.php(20): a()
|
||||
|
||||
#0 %sdebug_print_backtrace_limit.php(7): c()
|
||||
#1 %sdebug_print_backtrace_limit.php(3): b()
|
||||
#2 %sdebug_print_backtrace_limit.php(20): a()
|
||||
|
||||
@@ -16,6 +16,6 @@ $fiber->start();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 inner_function() called at [%sdebug-backtrace.php:9]
|
||||
#1 {closure}()
|
||||
#2 Fiber->start() called at [%sdebug-backtrace.php:12]
|
||||
#0 %sdebug-backtrace.php(9): inner_function()
|
||||
#1 [internal function]: {closure}()
|
||||
#2 %sdebug-backtrace.php(12): Fiber->start()
|
||||
|
||||
@@ -21,7 +21,7 @@ f3($gen);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 f1() called at [%s:%d]
|
||||
#1 f2(foo, bar)
|
||||
#2 Generator->rewind() called at [%s:%d]
|
||||
#3 f3(Generator Object ()) called at [%s:%d]
|
||||
#0 %s(%d): f1()
|
||||
#1 [internal function]: f2('foo', 'bar')
|
||||
#2 %s(%d): Generator->rewind()
|
||||
#3 %s(%d): f3(Object(Generator))
|
||||
|
||||
@@ -26,7 +26,7 @@ var_dump($gen2->current());
|
||||
--EXPECTF--
|
||||
int(1)
|
||||
int(1)
|
||||
#0 gen() called at [%s:10]
|
||||
#1 from(Generator Object ())
|
||||
#2 Generator->next() called at [%s:19]
|
||||
#0 %s(10): gen()
|
||||
#1 [internal function]: from(Object(Generator))
|
||||
#2 %s(19): Generator->next()
|
||||
int(2)
|
||||
|
||||
@@ -28,21 +28,21 @@ for ($gen = gen(); $gen->valid(); $gen->next()) {
|
||||
--EXPECTF--
|
||||
Implicit foreach:
|
||||
int(1)
|
||||
#0 gen() called at [%s:%d]
|
||||
#0 %s(%d): gen()
|
||||
int(2)
|
||||
#0 from(2) called at [%s:%d]
|
||||
#1 gen() called at [%s:%d]
|
||||
#0 %s(%d): from(2)
|
||||
#1 %s(%d): gen()
|
||||
int(3)
|
||||
#0 gen() called at [%s:%d]
|
||||
#0 %s(%d): gen()
|
||||
|
||||
Explicit iterator:
|
||||
int(1)
|
||||
#0 gen()
|
||||
#1 Generator->next() called at [%s:%d]
|
||||
#0 [internal function]: gen()
|
||||
#1 %s(%d): Generator->next()
|
||||
int(2)
|
||||
#0 from(2) called at [%s:%d]
|
||||
#1 gen()
|
||||
#2 Generator->next() called at [%s:%d]
|
||||
#0 %s(%d): from(2)
|
||||
#1 [internal function]: gen()
|
||||
#2 %s(%d): Generator->next()
|
||||
int(3)
|
||||
#0 gen()
|
||||
#1 Generator->next() called at [%s:%d]
|
||||
#0 [internal function]: gen()
|
||||
#1 %s(%d): Generator->next()
|
||||
|
||||
@@ -40,7 +40,7 @@ array(1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#0 test(1, 2, x: 3, y: 4) called at [%s:10]
|
||||
#0 %s(10): test(1, 2, x: 3, y: 4)
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(4) {
|
||||
|
||||
@@ -1637,33 +1637,12 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void debug_print_backtrace_args(smart_str *str, zval *arg_array) /* {{{ */
|
||||
{
|
||||
zend_string *name;
|
||||
zval *tmp;
|
||||
int i = 0;
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(arg_array), name, tmp) {
|
||||
if (i++) {
|
||||
smart_str_appends(str, ", ");
|
||||
}
|
||||
if (name) {
|
||||
smart_str_append(str, name);
|
||||
smart_str_appends(str, ": ");
|
||||
}
|
||||
zend_print_flat_zval_r_to_buf(str, tmp);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ */
|
||||
ZEND_FUNCTION(debug_print_backtrace)
|
||||
{
|
||||
zend_long options = 0;
|
||||
zend_long limit = 0;
|
||||
zval backtrace, *frame;
|
||||
zend_long frame_no;
|
||||
smart_str str = {0};
|
||||
zval backtrace;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
@@ -1671,48 +1650,11 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||
|
||||
zend_fetch_debug_backtrace(&backtrace, 1, options, limit);
|
||||
ZEND_ASSERT(Z_TYPE(backtrace) == IS_ARRAY);
|
||||
ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARR(backtrace), frame_no, frame) {
|
||||
ZEND_ASSERT(Z_TYPE_P(frame) == IS_ARRAY);
|
||||
zval *function = zend_hash_find_ex(Z_ARR_P(frame), ZSTR_KNOWN(ZEND_STR_FUNCTION), 1);
|
||||
zval *class = zend_hash_find_ex(Z_ARR_P(frame), ZSTR_KNOWN(ZEND_STR_CLASS), 1);
|
||||
zval *type = zend_hash_find_ex(Z_ARR_P(frame), ZSTR_KNOWN(ZEND_STR_TYPE), 1);
|
||||
zval *file = zend_hash_find_ex(Z_ARR_P(frame), ZSTR_KNOWN(ZEND_STR_FILE), 1);
|
||||
zval *line = zend_hash_find_ex(Z_ARR_P(frame), ZSTR_KNOWN(ZEND_STR_LINE), 1);
|
||||
zval *args = zend_hash_find_ex(Z_ARR_P(frame), ZSTR_KNOWN(ZEND_STR_ARGS), 1);
|
||||
|
||||
smart_str_append_printf(&str, "#%-2d ", (int) frame_no);
|
||||
if (class) {
|
||||
ZEND_ASSERT(Z_TYPE_P(class) == IS_STRING);
|
||||
ZEND_ASSERT(type && Z_TYPE_P(type) == IS_STRING);
|
||||
/* Cut off anonymous class names at null byte. */
|
||||
smart_str_appends(&str, Z_STRVAL_P(class));
|
||||
smart_str_append(&str, Z_STR_P(type));
|
||||
}
|
||||
smart_str_append(&str, Z_STR_P(function));
|
||||
smart_str_appendc(&str, '(');
|
||||
if (args) {
|
||||
ZEND_ASSERT(Z_TYPE_P(args) == IS_ARRAY);
|
||||
debug_print_backtrace_args(&str, args);
|
||||
}
|
||||
smart_str_appendc(&str, ')');
|
||||
if (file) {
|
||||
ZEND_ASSERT(Z_TYPE_P(file) == IS_STRING);
|
||||
ZEND_ASSERT(line && Z_TYPE_P(line) == IS_LONG);
|
||||
smart_str_appends(&str, " called at [");
|
||||
smart_str_append(&str, Z_STR_P(file));
|
||||
smart_str_appendc(&str, ':');
|
||||
smart_str_append_long(&str, Z_LVAL_P(line));
|
||||
smart_str_appendc(&str, ']');
|
||||
}
|
||||
smart_str_appendc(&str, '\n');
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
zend_string *str = zend_trace_to_string(Z_ARRVAL(backtrace), /* include_main */ false);
|
||||
ZEND_WRITE(ZSTR_VAL(str), ZSTR_LEN(str));
|
||||
zend_string_release(str);
|
||||
zval_ptr_dtor(&backtrace);
|
||||
|
||||
smart_str_0(&str);
|
||||
if (str.s) {
|
||||
ZEND_WRITE(ZSTR_VAL(str.s), ZSTR_LEN(str.s));
|
||||
}
|
||||
smart_str_free(&str);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
@@ -600,29 +600,13 @@ static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) /*
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Obtain the backtrace for the exception as a string (instead of an array) */
|
||||
ZEND_METHOD(Exception, getTraceAsString)
|
||||
{
|
||||
zval *trace, *frame, rv;
|
||||
ZEND_API zend_string *zend_trace_to_string(HashTable *trace, bool include_main) {
|
||||
zend_ulong index;
|
||||
zval *object;
|
||||
zend_class_entry *base_ce;
|
||||
smart_str str = {0};
|
||||
zval *frame;
|
||||
uint32_t num = 0;
|
||||
smart_str str = {0};
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
object = ZEND_THIS;
|
||||
base_ce = i_get_exception_base(Z_OBJ_P(object));
|
||||
|
||||
trace = zend_read_property_ex(base_ce, Z_OBJ_P(object), ZSTR_KNOWN(ZEND_STR_TRACE), 1, &rv);
|
||||
if (EG(exception)) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
/* Type should be guaranteed by property type. */
|
||||
ZEND_ASSERT(Z_TYPE_P(trace) == IS_ARRAY);
|
||||
ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) {
|
||||
ZEND_HASH_FOREACH_NUM_KEY_VAL(trace, index, frame) {
|
||||
if (Z_TYPE_P(frame) != IS_ARRAY) {
|
||||
zend_error(E_WARNING, "Expected array for frame " ZEND_ULONG_FMT, index);
|
||||
continue;
|
||||
@@ -631,12 +615,33 @@ ZEND_METHOD(Exception, getTraceAsString)
|
||||
_build_trace_string(&str, Z_ARRVAL_P(frame), num++);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
smart_str_appendc(&str, '#');
|
||||
smart_str_append_long(&str, num);
|
||||
smart_str_appends(&str, " {main}");
|
||||
smart_str_0(&str);
|
||||
if (include_main) {
|
||||
smart_str_appendc(&str, '#');
|
||||
smart_str_append_long(&str, num);
|
||||
smart_str_appends(&str, " {main}");
|
||||
}
|
||||
|
||||
RETURN_NEW_STR(str.s);
|
||||
smart_str_0(&str);
|
||||
return str.s ? str.s : ZSTR_EMPTY_ALLOC();
|
||||
}
|
||||
|
||||
/* {{{ Obtain the backtrace for the exception as a string (instead of an array) */
|
||||
ZEND_METHOD(Exception, getTraceAsString)
|
||||
{
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
zval *object = ZEND_THIS;
|
||||
zend_class_entry *base_ce = i_get_exception_base(Z_OBJ_P(object));
|
||||
zval rv;
|
||||
zval *trace = zend_read_property_ex(base_ce, Z_OBJ_P(object), ZSTR_KNOWN(ZEND_STR_TRACE), 1, &rv);
|
||||
if (EG(exception)) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
/* Type should be guaranteed by property type. */
|
||||
ZEND_ASSERT(Z_TYPE_P(trace) == IS_ARRAY);
|
||||
RETURN_NEW_STR(zend_trace_to_string(Z_ARRVAL_P(trace), /* include_main */ true));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ extern ZEND_API void (*zend_throw_exception_hook)(zend_object *ex);
|
||||
|
||||
/* show an exception using zend_error(severity,...), severity should be E_ERROR */
|
||||
ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *exception, int severity);
|
||||
ZEND_API zend_string *zend_trace_to_string(HashTable *trace, bool include_main);
|
||||
|
||||
ZEND_API ZEND_COLD void zend_throw_unwind_exit(void);
|
||||
ZEND_API ZEND_COLD void zend_throw_graceful_exit(void);
|
||||
|
||||
@@ -26,5 +26,5 @@ class c1
|
||||
c1::go();
|
||||
?>
|
||||
--EXPECTF--
|
||||
#0 require() called at [%s:19]
|
||||
#1 c1::go() called at [%s:23]
|
||||
#0 %s(19): require()
|
||||
#1 %s(23): c1::go()
|
||||
|
||||
@@ -6,5 +6,8 @@ class FooBar { static function error() { debug_print_backtrace(); } }
|
||||
set_error_handler(array('FooBar', 'error'));
|
||||
include('foobar.php');
|
||||
?>
|
||||
--EXPECTREGEX--
|
||||
.*#1\s*include.*
|
||||
--EXPECTF--
|
||||
#0 %s(%d): FooBar::error(2, 'include(foobar....', '%s', 4)
|
||||
#1 %s(%d): include()
|
||||
#0 %s(%d): FooBar::error(2, 'include(): Fail...', '%s', 4)
|
||||
#1 %s(%d): include()
|
||||
|
||||
Reference in New Issue
Block a user