2003-03-23 12:32:24 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Zend Engine |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2016-01-02 17:51:24 +08:00
| Copyright ( c ) 1998 - 2016 Zend Technologies Ltd . ( http : //www.zend.com) |
2003-03-23 12:32:24 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| This source file is subject to version 2.00 of the Zend license , |
2003-03-23 14:57:16 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-11 04:04:29 +08:00
| available through the world - wide - web at the following url : |
2003-03-23 12:32:24 +08:00
| http : //www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ zend . com so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-02-12 18:38:14 +08:00
| Authors : Andi Gutmans < andi @ zend . com > |
2003-08-24 03:48:52 +08:00
| Marcus Boerger < helly @ php . net > |
2004-02-12 18:38:14 +08:00
| Sterling Hughes < sterling @ php . net > |
| Zeev Suraski < zeev @ zend . com > |
2003-03-23 12:32:24 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
# include "zend.h"
# include "zend_API.h"
2003-08-29 04:35:54 +08:00
# include "zend_builtin_functions.h"
2003-10-23 04:04:48 +08:00
# include "zend_interfaces.h"
2004-07-16 06:21:36 +08:00
# include "zend_exceptions.h"
2008-01-22 03:39:55 +08:00
# include "zend_vm.h"
2010-04-24 21:32:30 +08:00
# include "zend_dtrace.h"
2003-03-23 12:32:24 +08:00
2012-08-02 18:44:15 +08:00
static zend_class_entry * default_exception_ce ;
static zend_class_entry * error_exception_ce ;
2003-09-05 19:40:30 +08:00
static zend_object_handlers default_exception_handlers ;
2004-04-13 23:19:21 +08:00
ZEND_API void ( * zend_throw_exception_hook ) ( zval * ex TSRMLS_DC ) ;
2003-03-23 12:32:24 +08:00
2008-08-14 18:24:52 +08:00
void zend_exception_set_previous ( zval * exception , zval * add_previous TSRMLS_DC )
2008-07-14 05:42:49 +08:00
{
2015-11-20 16:24:53 +08:00
zval * previous , * ancestor ;
2008-07-14 05:42:49 +08:00
2008-08-14 18:24:52 +08:00
if ( exception = = add_previous | | ! add_previous | | ! exception ) {
2008-07-14 05:42:49 +08:00
return ;
}
2015-07-27 08:09:34 +08:00
if ( Z_TYPE_P ( add_previous ) ! = IS_OBJECT | | ! instanceof_function ( Z_OBJCE_P ( add_previous ) , default_exception_ce TSRMLS_CC ) ) {
2008-07-14 05:42:49 +08:00
zend_error ( E_ERROR , " Cannot set non exception as previous exception " ) ;
return ;
}
while ( exception & & exception ! = add_previous & & Z_OBJ_HANDLE_P ( exception ) ! = Z_OBJ_HANDLE_P ( add_previous ) ) {
2015-11-21 16:27:56 +08:00
ancestor = zend_read_property ( default_exception_ce , add_previous , " previous " , sizeof ( " previous " ) - 1 , 1 TSRMLS_CC ) ;
while ( Z_TYPE_P ( ancestor ) = = IS_OBJECT ) {
if ( Z_OBJ_HANDLE_P ( ancestor ) = = Z_OBJ_HANDLE_P ( exception ) ) {
zval_ptr_dtor ( & add_previous ) ;
return ;
}
ancestor = zend_read_property ( default_exception_ce , ancestor , " previous " , sizeof ( " previous " ) - 1 , 1 TSRMLS_CC ) ;
}
2008-07-14 05:42:49 +08:00
previous = zend_read_property ( default_exception_ce , exception , " previous " , sizeof ( " previous " ) - 1 , 1 TSRMLS_CC ) ;
if ( Z_TYPE_P ( previous ) = = IS_NULL ) {
zend_update_property ( default_exception_ce , exception , " previous " , sizeof ( " previous " ) - 1 , add_previous TSRMLS_CC ) ;
2008-07-29 22:28:11 +08:00
Z_DELREF_P ( add_previous ) ;
2008-07-14 05:42:49 +08:00
return ;
}
exception = previous ;
}
}
2008-08-14 18:24:52 +08:00
void zend_exception_save ( TSRMLS_D ) /* { { { */
{
if ( EG ( prev_exception ) ) {
zend_exception_set_previous ( EG ( exception ) , EG ( prev_exception ) TSRMLS_CC ) ;
}
if ( EG ( exception ) ) {
EG ( prev_exception ) = EG ( exception ) ;
}
EG ( exception ) = NULL ;
}
/* }}} */
void zend_exception_restore ( TSRMLS_D ) /* { { { */
{
if ( EG ( prev_exception ) ) {
if ( EG ( exception ) ) {
zend_exception_set_previous ( EG ( exception ) , EG ( prev_exception ) TSRMLS_CC ) ;
} else {
EG ( exception ) = EG ( prev_exception ) ;
}
EG ( prev_exception ) = NULL ;
}
}
/* }}} */
2010-08-18 17:45:52 +08:00
void zend_throw_exception_internal ( zval * exception TSRMLS_DC ) /* { { { */
2004-02-12 18:38:14 +08:00
{
2010-04-24 21:32:30 +08:00
# ifdef HAVE_DTRACE
if ( DTRACE_EXCEPTION_THROWN_ENABLED ( ) ) {
2013-08-15 11:47:44 +08:00
const char * classname ;
zend_uint name_len ;
2010-11-18 05:41:30 +08:00
if ( exception ! = NULL ) {
2011-08-21 19:51:00 +08:00
zend_get_object_classname ( exception , & classname , & name_len TSRMLS_CC ) ;
2013-08-15 11:47:44 +08:00
DTRACE_EXCEPTION_THROWN ( ( char * ) classname ) ;
2010-11-18 05:41:30 +08:00
} else {
DTRACE_EXCEPTION_THROWN ( NULL ) ;
}
2010-04-24 21:32:30 +08:00
}
2010-04-26 03:17:16 +08:00
# endif /* HAVE_DTRACE */
2010-04-24 21:32:30 +08:00
2004-02-12 18:38:14 +08:00
if ( exception ! = NULL ) {
2008-07-14 05:42:49 +08:00
zval * previous = EG ( exception ) ;
2008-08-14 18:24:52 +08:00
zend_exception_set_previous ( exception , EG ( exception ) TSRMLS_CC ) ;
2004-02-12 18:38:14 +08:00
EG ( exception ) = exception ;
2008-08-14 18:24:52 +08:00
if ( previous ) {
return ;
}
2004-02-12 18:38:14 +08:00
}
if ( ! EG ( current_execute_data ) ) {
2011-01-17 05:24:43 +08:00
if ( EG ( exception ) ) {
zend_exception_error ( EG ( exception ) , E_ERROR TSRMLS_CC ) ;
}
2004-02-12 18:38:14 +08:00
zend_error ( E_ERROR , " Exception thrown without a stack frame " ) ;
}
2004-04-13 23:19:21 +08:00
if ( zend_throw_exception_hook ) {
zend_throw_exception_hook ( exception TSRMLS_CC ) ;
}
2004-12-07 15:46:12 +08:00
if ( EG ( current_execute_data ) - > opline = = NULL | |
( EG ( current_execute_data ) - > opline + 1 ) - > opcode = = ZEND_HANDLE_EXCEPTION ) {
2004-02-12 18:38:14 +08:00
/* no need to rethrow the exception */
return ;
}
EG ( opline_before_exception ) = EG ( current_execute_data ) - > opline ;
2008-01-22 03:39:55 +08:00
EG ( current_execute_data ) - > opline = EG ( exception_op ) ;
2004-02-12 18:38:14 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2004-02-12 18:38:14 +08:00
2007-01-18 20:20:15 +08:00
ZEND_API void zend_clear_exception ( TSRMLS_D ) /* { { { */
2004-02-12 18:38:14 +08:00
{
2008-08-14 18:24:52 +08:00
if ( EG ( prev_exception ) ) {
zval_ptr_dtor ( & EG ( prev_exception ) ) ;
EG ( prev_exception ) = NULL ;
}
2004-02-12 18:38:14 +08:00
if ( ! EG ( exception ) ) {
return ;
}
zval_ptr_dtor ( & EG ( exception ) ) ;
EG ( exception ) = NULL ;
EG ( current_execute_data ) - > opline = EG ( opline_before_exception ) ;
# if ZEND_DEBUG
EG ( opline_before_exception ) = NULL ;
# endif
}
2007-01-18 20:20:15 +08:00
/* }}} */
2004-02-12 18:38:14 +08:00
2007-01-18 20:20:15 +08:00
static zend_object_value zend_default_exception_new_ex ( zend_class_entry * class_type , int skip_top_traces TSRMLS_DC ) /* { { { */
2003-08-24 03:41:22 +08:00
{
2010-05-24 22:11:39 +08:00
zval obj ;
2003-08-24 03:41:22 +08:00
zend_object * object ;
2003-08-29 04:35:54 +08:00
zval * trace ;
2003-08-24 03:41:22 +08:00
2006-05-10 07:53:23 +08:00
Z_OBJVAL ( obj ) = zend_objects_new ( & object , class_type TSRMLS_CC ) ;
Z_OBJ_HT ( obj ) = & default_exception_handlers ;
2003-08-24 03:41:22 +08:00
2010-05-24 22:11:39 +08:00
object_properties_init ( object , class_type ) ;
2003-08-24 03:41:22 +08:00
2003-08-29 04:35:54 +08:00
ALLOC_ZVAL ( trace ) ;
2007-10-07 13:22:07 +08:00
Z_UNSET_ISREF_P ( trace ) ;
Z_SET_REFCOUNT_P ( trace , 0 ) ;
2011-04-09 17:52:24 +08:00
zend_fetch_debug_backtrace ( trace , skip_top_traces , 0 , 0 TSRMLS_CC ) ;
2003-08-29 04:35:54 +08:00
2004-02-11 00:08:01 +08:00
zend_update_property_string ( default_exception_ce , & obj , " file " , sizeof ( " file " ) - 1 , zend_get_executed_filename ( TSRMLS_C ) TSRMLS_CC ) ;
zend_update_property_long ( default_exception_ce , & obj , " line " , sizeof ( " line " ) - 1 , zend_get_executed_lineno ( TSRMLS_C ) TSRMLS_CC ) ;
zend_update_property ( default_exception_ce , & obj , " trace " , sizeof ( " trace " ) - 1 , trace TSRMLS_CC ) ;
2003-08-24 03:41:22 +08:00
2006-05-10 07:53:23 +08:00
return Z_OBJVAL ( obj ) ;
2003-08-24 03:41:22 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-08-24 03:41:22 +08:00
2007-01-18 20:20:15 +08:00
static zend_object_value zend_default_exception_new ( zend_class_entry * class_type TSRMLS_DC ) /* { { { */
2004-07-16 06:21:36 +08:00
{
return zend_default_exception_new_ex ( class_type , 0 TSRMLS_CC ) ;
}
2007-01-18 20:20:15 +08:00
/* }}} */
2004-07-16 06:21:36 +08:00
2007-01-18 20:20:15 +08:00
static zend_object_value zend_error_exception_new ( zend_class_entry * class_type TSRMLS_DC ) /* { { { */
2004-07-16 06:21:36 +08:00
{
return zend_default_exception_new_ex ( class_type , 2 TSRMLS_CC ) ;
}
2007-01-18 20:20:15 +08:00
/* }}} */
2004-07-20 17:24:22 +08:00
/* {{{ proto Exception Exception::__clone()
Clone the exception object */
2003-10-26 03:13:06 +08:00
ZEND_METHOD ( exception , __clone )
2003-10-26 03:07:09 +08:00
{
/* Should never be executable */
2003-10-26 03:13:06 +08:00
zend_throw_exception ( NULL , " Cannot clone object using __clone() " , 0 TSRMLS_CC ) ;
2003-10-26 03:07:09 +08:00
}
2004-07-20 17:24:22 +08:00
/* }}} */
2008-07-12 22:57:14 +08:00
/* {{{ proto Exception::__construct(string message, int code [, Exception previous])
2004-07-20 17:24:22 +08:00
Exception constructor */
2003-08-24 19:25:08 +08:00
ZEND_METHOD ( exception , __construct )
2003-03-23 12:32:24 +08:00
{
2003-08-23 22:22:28 +08:00
char * message = NULL ;
long code = 0 ;
2008-07-12 22:57:14 +08:00
zval * object , * previous = NULL ;
2003-08-23 22:22:28 +08:00
int argc = ZEND_NUM_ARGS ( ) , message_len ;
2003-03-23 14:57:16 +08:00
2008-07-14 05:42:49 +08:00
if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , argc TSRMLS_CC , " |slO! " , & message , & message_len , & code , & previous , default_exception_ce ) = = FAILURE ) {
zend_error ( E_ERROR , " Wrong parameters for Exception([string $exception [, long $code [, Exception $previous = NULL]]]) " ) ;
2003-03-23 12:32:24 +08:00
}
object = getThis ( ) ;
2003-08-24 03:41:22 +08:00
if ( message ) {
2012-03-12 02:15:13 +08:00
zend_update_property_stringl ( default_exception_ce , object , " message " , sizeof ( " message " ) - 1 , message , message_len TSRMLS_CC ) ;
2003-08-24 03:41:22 +08:00
}
2003-03-23 12:32:24 +08:00
2003-08-24 03:41:22 +08:00
if ( code ) {
2004-02-11 00:08:01 +08:00
zend_update_property_long ( default_exception_ce , object , " code " , sizeof ( " code " ) - 1 , code TSRMLS_CC ) ;
2003-08-24 03:41:22 +08:00
}
2008-07-12 22:57:14 +08:00
if ( previous ) {
zend_update_property ( default_exception_ce , object , " previous " , sizeof ( " previous " ) - 1 , previous TSRMLS_CC ) ;
}
2003-03-23 12:32:24 +08:00
}
2004-07-20 17:24:22 +08:00
/* }}} */
2015-07-27 16:38:27 +08:00
/* {{{ proto Exception::__wakeup()
Exception unserialize checks */
# define CHECK_EXC_TYPE(name, type) \
2016-10-03 15:09:02 +08:00
value = zend_read_property ( default_exception_ce , object , name , sizeof ( name ) - 1 , 1 TSRMLS_CC ) ; \
2016-07-12 12:14:45 +08:00
if ( value & & Z_TYPE_P ( value ) ! = IS_NULL & & Z_TYPE_P ( value ) ! = type ) { \
2016-10-03 15:09:02 +08:00
zend_unset_property ( default_exception_ce , object , name , sizeof ( name ) - 1 TSRMLS_CC ) ; \
2015-07-27 16:38:27 +08:00
}
ZEND_METHOD ( exception , __wakeup )
{
zval * value ;
zval * object = getThis ( ) ;
CHECK_EXC_TYPE ( " message " , IS_STRING ) ;
CHECK_EXC_TYPE ( " string " , IS_STRING ) ;
CHECK_EXC_TYPE ( " code " , IS_LONG ) ;
CHECK_EXC_TYPE ( " file " , IS_STRING ) ;
CHECK_EXC_TYPE ( " line " , IS_LONG ) ;
CHECK_EXC_TYPE ( " trace " , IS_ARRAY ) ;
2016-10-03 15:09:02 +08:00
value = zend_read_property ( default_exception_ce , object , " previous " , sizeof ( " previous " ) - 1 , 1 TSRMLS_CC ) ;
if ( value & & Z_TYPE_P ( value ) ! = IS_NULL & & ( Z_TYPE_P ( value ) ! = IS_OBJECT | |
! instanceof_function ( Z_OBJCE_P ( value ) , default_exception_ce TSRMLS_CC ) | |
value = = object ) ) {
zend_unset_property ( default_exception_ce , object , " previous " , sizeof ( " previous " ) - 1 TSRMLS_CC ) ;
}
2015-07-27 16:38:27 +08:00
}
/* }}} */
2008-07-12 22:57:14 +08:00
/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Exception previous]]])
2004-07-20 17:24:22 +08:00
ErrorException constructor */
2004-07-16 06:21:36 +08:00
ZEND_METHOD ( error_exception , __construct )
{
2004-07-25 15:05:48 +08:00
char * message = NULL , * filename = NULL ;
long code = 0 , severity = E_ERROR , lineno ;
2008-07-12 22:57:14 +08:00
zval * object , * previous = NULL ;
2004-07-25 15:05:48 +08:00
int argc = ZEND_NUM_ARGS ( ) , message_len , filename_len ;
2004-07-16 06:21:36 +08:00
2008-07-14 05:42:49 +08:00
if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , argc TSRMLS_CC , " |sllslO! " , & message , & message_len , & code , & severity , & filename , & filename_len , & lineno , & previous , default_exception_ce ) = = FAILURE ) {
zend_error ( E_ERROR , " Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno [, Exception $previous = NULL]]]]]]) " ) ;
2004-07-16 06:21:36 +08:00
}
object = getThis ( ) ;
if ( message ) {
zend_update_property_string ( default_exception_ce , object , " message " , sizeof ( " message " ) - 1 , message TSRMLS_CC ) ;
}
if ( code ) {
zend_update_property_long ( default_exception_ce , object , " code " , sizeof ( " code " ) - 1 , code TSRMLS_CC ) ;
}
2008-07-12 22:57:14 +08:00
if ( previous ) {
zend_update_property ( default_exception_ce , object , " previous " , sizeof ( " previous " ) - 1 , previous TSRMLS_CC ) ;
}
2004-07-16 06:21:36 +08:00
zend_update_property_long ( default_exception_ce , object , " severity " , sizeof ( " severity " ) - 1 , severity TSRMLS_CC ) ;
2006-05-10 07:53:23 +08:00
2004-07-25 15:05:48 +08:00
if ( argc > = 4 ) {
zend_update_property_string ( default_exception_ce , object , " file " , sizeof ( " file " ) - 1 , filename TSRMLS_CC ) ;
if ( argc < 5 ) {
2005-04-19 19:41:04 +08:00
lineno = 0 ; /* invalidate lineno */
2004-07-25 15:05:48 +08:00
}
zend_update_property_long ( default_exception_ce , object , " line " , sizeof ( " line " ) - 1 , lineno TSRMLS_CC ) ;
}
2004-07-16 06:21:36 +08:00
}
2004-07-20 17:24:22 +08:00
/* }}} */
2004-07-16 06:21:36 +08:00
2003-03-23 12:32:24 +08:00
# define DEFAULT_0_PARAMS \
2008-03-11 06:02:41 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) { \
return ; \
2003-03-23 12:32:24 +08:00
}
2007-01-18 20:20:15 +08:00
static void _default_exception_get_entry ( zval * object , char * name , int name_len , zval * return_value TSRMLS_DC ) /* { { { */
2003-03-23 12:32:24 +08:00
{
2003-08-24 08:36:53 +08:00
zval * value ;
2003-03-23 12:32:24 +08:00
2004-02-11 00:08:01 +08:00
value = zend_read_property ( default_exception_ce , object , name , name_len , 0 TSRMLS_CC ) ;
2003-03-23 12:32:24 +08:00
2003-08-24 08:36:53 +08:00
* return_value = * value ;
2003-03-23 12:32:24 +08:00
zval_copy_ctor ( return_value ) ;
2005-08-16 18:49:25 +08:00
INIT_PZVAL ( return_value ) ;
2003-03-23 12:32:24 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2004-07-20 17:24:22 +08:00
/* {{{ proto string Exception::getFile()
Get the file in which the exception occurred */
2003-09-17 18:15:00 +08:00
ZEND_METHOD ( exception , getFile )
2003-03-23 12:32:24 +08:00
{
DEFAULT_0_PARAMS ;
2003-08-24 08:36:53 +08:00
_default_exception_get_entry ( getThis ( ) , " file " , sizeof ( " file " ) - 1 , return_value TSRMLS_CC ) ;
2003-03-23 12:32:24 +08:00
}
2004-07-20 17:24:22 +08:00
/* }}} */
/* {{{ proto int Exception::getLine()
Get the line in which the exception occurred */
2003-09-17 18:15:00 +08:00
ZEND_METHOD ( exception , getLine )
2003-03-23 12:32:24 +08:00
{
DEFAULT_0_PARAMS ;
2003-08-24 08:36:53 +08:00
_default_exception_get_entry ( getThis ( ) , " line " , sizeof ( " line " ) - 1 , return_value TSRMLS_CC ) ;
2003-03-23 12:32:24 +08:00
}
2004-07-20 17:24:22 +08:00
/* }}} */
/* {{{ proto string Exception::getMessage()
Get the exception message */
2003-09-17 18:15:00 +08:00
ZEND_METHOD ( exception , getMessage )
2003-03-23 12:32:24 +08:00
{
DEFAULT_0_PARAMS ;
2003-08-24 08:36:53 +08:00
_default_exception_get_entry ( getThis ( ) , " message " , sizeof ( " message " ) - 1 , return_value TSRMLS_CC ) ;
2003-03-23 12:32:24 +08:00
}
2004-07-20 17:24:22 +08:00
/* }}} */
/* {{{ proto int Exception::getCode()
Get the exception code */
2003-09-17 18:15:00 +08:00
ZEND_METHOD ( exception , getCode )
2003-03-23 12:32:24 +08:00
{
DEFAULT_0_PARAMS ;
2003-08-24 08:36:53 +08:00
_default_exception_get_entry ( getThis ( ) , " code " , sizeof ( " code " ) - 1 , return_value TSRMLS_CC ) ;
2003-03-23 12:32:24 +08:00
}
2004-07-20 17:24:22 +08:00
/* }}} */
2003-03-23 12:32:24 +08:00
2004-07-20 17:24:22 +08:00
/* {{{ proto array Exception::getTrace()
Get the stack trace for the location in which the exception occurred */
2003-09-17 18:15:00 +08:00
ZEND_METHOD ( exception , getTrace )
2003-08-29 07:43:56 +08:00
{
DEFAULT_0_PARAMS ;
_default_exception_get_entry ( getThis ( ) , " trace " , sizeof ( " trace " ) - 1 , return_value TSRMLS_CC ) ;
}
2004-07-20 17:24:22 +08:00
/* }}} */
2003-08-29 07:43:56 +08:00
2004-07-20 18:43:19 +08:00
/* {{{ proto int ErrorException::getSeverity()
2004-07-20 17:24:22 +08:00
Get the exception severity */
2004-07-16 06:21:36 +08:00
ZEND_METHOD ( error_exception , getSeverity )
{
DEFAULT_0_PARAMS ;
_default_exception_get_entry ( getThis ( ) , " severity " , sizeof ( " severity " ) - 1 , return_value TSRMLS_CC ) ;
}
2004-07-20 17:24:22 +08:00
/* }}} */
2004-07-16 06:21:36 +08:00
2007-01-18 20:20:15 +08:00
/* {{{ gettraceasstring() macros */
2003-08-31 02:28:24 +08:00
# define TRACE_APPEND_CHR(chr) \
* str = ( char * ) erealloc ( * str , * len + 1 + 1 ) ; \
( * str ) [ ( * len ) + + ] = chr
# define TRACE_APPEND_STRL(val, vallen) \
{ \
2006-05-10 07:53:23 +08:00
int l = vallen ; \
2003-08-31 02:28:24 +08:00
* str = ( char * ) erealloc ( * str , * len + l + 1 ) ; \
memcpy ( ( * str ) + * len , val , l ) ; \
* len + = l ; \
}
# define TRACE_APPEND_STR(val) \
TRACE_APPEND_STRL ( val , sizeof ( val ) - 1 )
2012-12-14 05:39:35 +08:00
# define TRACE_APPEND_KEY(key) \
if ( zend_hash_find ( ht , key , sizeof ( key ) , ( void * * ) & tmp ) = = SUCCESS ) { \
if ( Z_TYPE_PP ( tmp ) ! = IS_STRING ) { \
zend_error ( E_WARNING , " Value for %s is no string " , key ) ; \
TRACE_APPEND_STR ( " [unknown] " ) ; \
} else { \
TRACE_APPEND_STRL ( Z_STRVAL_PP ( tmp ) , Z_STRLEN_PP ( tmp ) ) ; \
} \
2003-08-31 02:28:24 +08:00
}
2014-02-21 00:39:58 +08:00
# define TRACE_ARG_APPEND(vallen) \
* str = ( char * ) erealloc ( * str , * len + 1 + vallen ) ; \
2014-05-11 21:11:03 +08:00
memmove ( ( * str ) + * len - l_added + 1 + vallen , ( * str ) + * len - l_added + 1 , l_added ) ;
2014-02-21 00:39:58 +08:00
2007-01-18 20:20:15 +08:00
/* }}} */
2008-07-25 03:52:24 +08:00
static int _build_trace_args ( zval * * arg TSRMLS_DC , int num_args , va_list args , zend_hash_key * hash_key ) /* { { { */
2003-08-31 02:28:24 +08:00
{
char * * str ;
int * len ;
str = va_arg ( args , char * * ) ;
len = va_arg ( args , int * ) ;
/* the trivial way would be to do:
2014-02-21 00:39:58 +08:00
* convert_to_string_ex ( arg ) ;
2003-08-31 02:28:24 +08:00
* append it and kill the now tmp arg .
* but that could cause some E_NOTICE and also damn long lines .
*/
switch ( Z_TYPE_PP ( arg ) ) {
case IS_NULL :
TRACE_APPEND_STR ( " NULL, " ) ;
break ;
2003-08-31 20:40:29 +08:00
case IS_STRING : {
int l_added ;
2003-08-31 02:28:24 +08:00
TRACE_APPEND_CHR ( ' \' ' ) ;
if ( Z_STRLEN_PP ( arg ) > 15 ) {
TRACE_APPEND_STRL ( Z_STRVAL_PP ( arg ) , 15 ) ;
TRACE_APPEND_STR ( " ...', " ) ;
2003-08-31 20:40:29 +08:00
l_added = 15 + 6 + 1 ; /* +1 because of while (--l_added) */
2003-08-31 02:28:24 +08:00
} else {
2003-08-31 20:40:29 +08:00
l_added = Z_STRLEN_PP ( arg ) ;
TRACE_APPEND_STRL ( Z_STRVAL_PP ( arg ) , l_added ) ;
2003-08-31 02:28:24 +08:00
TRACE_APPEND_STR ( " ', " ) ;
2003-08-31 20:40:29 +08:00
l_added + = 3 + 1 ;
}
while ( - - l_added ) {
2014-02-21 00:39:58 +08:00
unsigned char chr = ( * str ) [ * len - l_added ] ;
if ( chr < 32 | | chr = = ' \\ ' | | chr > 126 ) {
( * str ) [ * len - l_added ] = ' \\ ' ;
switch ( chr ) {
case ' \n ' :
TRACE_ARG_APPEND ( 1 ) ;
( * str ) [ + + ( * len ) - l_added ] = ' n ' ;
break ;
case ' \r ' :
TRACE_ARG_APPEND ( 1 ) ;
( * str ) [ + + ( * len ) - l_added ] = ' r ' ;
break ;
case ' \t ' :
TRACE_ARG_APPEND ( 1 ) ;
( * str ) [ + + ( * len ) - l_added ] = ' t ' ;
break ;
case ' \f ' :
TRACE_ARG_APPEND ( 1 ) ;
( * str ) [ + + ( * len ) - l_added ] = ' f ' ;
break ;
case ' \v ' :
TRACE_ARG_APPEND ( 1 ) ;
( * str ) [ + + ( * len ) - l_added ] = ' v ' ;
break ;
# ifndef PHP_WIN32
case ' \e ' :
# else
case VK_ESCAPE :
# endif
TRACE_ARG_APPEND ( 1 ) ;
( * str ) [ + + ( * len ) - l_added ] = ' e ' ;
break ;
case ' \\ ' :
TRACE_ARG_APPEND ( 1 ) ;
( * str ) [ + + ( * len ) - l_added ] = ' \\ ' ;
break ;
default :
TRACE_ARG_APPEND ( 3 ) ;
( * str ) [ * len - l_added + 1 ] = ' x ' ;
if ( ( chr > > 4 ) < 10 ) {
( * str ) [ * len - l_added + 2 ] = ( chr > > 4 ) + ' 0 ' ;
} else {
( * str ) [ * len - l_added + 2 ] = ( chr > > 4 ) + ' A ' - 10 ;
}
if ( chr % 16 < 10 ) {
( * str ) [ * len - l_added + 3 ] = chr % 16 + ' 0 ' ;
} else {
( * str ) [ * len - l_added + 3 ] = chr % 16 + ' A ' - 10 ;
}
* len + = 3 ;
}
2003-08-31 20:40:29 +08:00
}
2003-08-31 02:28:24 +08:00
}
break ;
2003-08-31 20:40:29 +08:00
}
2003-08-31 02:28:24 +08:00
case IS_BOOL :
if ( Z_LVAL_PP ( arg ) ) {
TRACE_APPEND_STR ( " true, " ) ;
} else {
TRACE_APPEND_STR ( " false, " ) ;
}
break ;
case IS_RESOURCE :
TRACE_APPEND_STR ( " Resource id # " ) ;
/* break; */
case IS_LONG : {
long lval = Z_LVAL_PP ( arg ) ;
char s_tmp [ MAX_LENGTH_OF_LONG + 1 ] ;
int l_tmp = zend_sprintf ( s_tmp , " %ld " , lval ) ; /* SAFE */
TRACE_APPEND_STRL ( s_tmp , l_tmp ) ;
TRACE_APPEND_STR ( " , " ) ;
break ;
}
case IS_DOUBLE : {
double dval = Z_DVAL_PP ( arg ) ;
char * s_tmp ;
int l_tmp ;
s_tmp = emalloc ( MAX_LENGTH_OF_DOUBLE + EG ( precision ) + 1 ) ;
l_tmp = zend_sprintf ( s_tmp , " %.*G " , ( int ) EG ( precision ) , dval ) ; /* SAFE */
TRACE_APPEND_STRL ( s_tmp , l_tmp ) ;
/* %G already handles removing trailing zeros from the fractional part, yay */
efree ( s_tmp ) ;
TRACE_APPEND_STR ( " , " ) ;
break ;
}
case IS_ARRAY :
TRACE_APPEND_STR ( " Array, " ) ;
break ;
case IS_OBJECT : {
2011-09-13 21:29:35 +08:00
const char * class_name ;
2005-06-28 02:13:13 +08:00
zend_uint class_name_len ;
int dup ;
2003-08-31 02:28:24 +08:00
TRACE_APPEND_STR ( " Object( " ) ;
2005-06-28 02:13:13 +08:00
dup = zend_get_object_classname ( * arg , & class_name , & class_name_len TSRMLS_CC ) ;
TRACE_APPEND_STRL ( class_name , class_name_len ) ;
if ( ! dup ) {
2011-09-13 21:29:35 +08:00
efree ( ( char * ) class_name ) ;
2005-06-28 02:13:13 +08:00
}
2006-05-10 07:53:23 +08:00
2003-08-31 02:28:24 +08:00
TRACE_APPEND_STR ( " ), " ) ;
break ;
}
default :
break ;
}
return ZEND_HASH_APPLY_KEEP ;
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-08-31 02:28:24 +08:00
2008-07-25 03:52:24 +08:00
static int _build_trace_string ( zval * * frame TSRMLS_DC , int num_args , va_list args , zend_hash_key * hash_key ) /* { { { */
2003-08-31 02:28:24 +08:00
{
char * s_tmp , * * str ;
2003-08-31 02:58:40 +08:00
int * len , * num ;
2003-08-31 02:28:24 +08:00
long line ;
HashTable * ht = Z_ARRVAL_PP ( frame ) ;
zval * * file , * * tmp ;
2012-12-14 05:39:35 +08:00
if ( Z_TYPE_PP ( frame ) ! = IS_ARRAY ) {
zend_error ( E_WARNING , " Expected array for frame %lu " , hash_key - > h ) ;
return ZEND_HASH_APPLY_KEEP ;
}
2003-08-31 02:28:24 +08:00
str = va_arg ( args , char * * ) ;
len = va_arg ( args , int * ) ;
2003-08-31 07:55:04 +08:00
num = va_arg ( args , int * ) ;
2003-08-31 02:28:24 +08:00
2003-08-31 17:35:54 +08:00
s_tmp = emalloc ( 1 + MAX_LENGTH_OF_LONG + 1 + 1 ) ;
2003-08-31 02:58:40 +08:00
sprintf ( s_tmp , " #%d " , ( * num ) + + ) ;
TRACE_APPEND_STRL ( s_tmp , strlen ( s_tmp ) ) ;
efree ( s_tmp ) ;
2003-08-31 02:28:24 +08:00
if ( zend_hash_find ( ht , " file " , sizeof ( " file " ) , ( void * * ) & file ) = = SUCCESS ) {
2012-12-14 05:39:35 +08:00
if ( Z_TYPE_PP ( file ) ! = IS_STRING ) {
zend_error ( E_WARNING , " Function name is no string " ) ;
TRACE_APPEND_STR ( " [unknown function] " ) ;
} else {
if ( zend_hash_find ( ht , " line " , sizeof ( " line " ) , ( void * * ) & tmp ) = = SUCCESS ) {
if ( Z_TYPE_PP ( tmp ) = = IS_LONG ) {
line = Z_LVAL_PP ( tmp ) ;
} else {
zend_error ( E_WARNING , " Line is no long " ) ;
line = 0 ;
}
} else {
line = 0 ;
}
s_tmp = emalloc ( Z_STRLEN_PP ( file ) + MAX_LENGTH_OF_LONG + 4 + 1 ) ;
sprintf ( s_tmp , " %s(%ld): " , Z_STRVAL_PP ( file ) , line ) ;
TRACE_APPEND_STRL ( s_tmp , strlen ( s_tmp ) ) ;
efree ( s_tmp ) ;
2003-08-31 02:28:24 +08:00
}
} else {
TRACE_APPEND_STR ( " [internal function]: " ) ;
}
TRACE_APPEND_KEY ( " class " ) ;
TRACE_APPEND_KEY ( " type " ) ;
TRACE_APPEND_KEY ( " function " ) ;
TRACE_APPEND_CHR ( ' ( ' ) ;
if ( zend_hash_find ( ht , " args " , sizeof ( " args " ) , ( void * * ) & tmp ) = = SUCCESS ) {
2012-12-14 05:39:35 +08:00
if ( Z_TYPE_PP ( tmp ) = = IS_ARRAY ) {
int last_len = * len ;
zend_hash_apply_with_arguments ( Z_ARRVAL_PP ( tmp ) TSRMLS_CC , ( apply_func_args_t ) _build_trace_args , 2 , str , len ) ;
if ( last_len ! = * len ) {
* len - = 2 ; /* remove last ', ' */
}
} else {
zend_error ( E_WARNING , " args element is no array " ) ;
2003-09-02 05:40:58 +08:00
}
2003-08-31 02:28:24 +08:00
}
TRACE_APPEND_STR ( " ) \n " ) ;
return ZEND_HASH_APPLY_KEEP ;
}
2007-01-18 20:20:15 +08:00
/* }}} */
2004-07-20 17:24:22 +08:00
/* {{{ proto string Exception::getTraceAsString()
Obtain the backtrace for the exception as a string ( instead of an array ) */
2003-09-17 18:15:00 +08:00
ZEND_METHOD ( exception , getTraceAsString )
2003-08-31 02:28:24 +08:00
{
zval * trace ;
2009-05-11 23:03:47 +08:00
char * res , * * str , * s_tmp ;
2003-09-02 04:54:48 +08:00
int res_len = 0 , * len = & res_len , num = 0 ;
2006-05-10 07:53:23 +08:00
2009-05-11 22:14:52 +08:00
DEFAULT_0_PARAMS ;
2015-07-27 08:09:34 +08:00
2006-07-21 16:39:30 +08:00
trace = zend_read_property ( default_exception_ce , getThis ( ) , " trace " , sizeof ( " trace " ) - 1 , 1 TSRMLS_CC ) ;
2015-04-14 19:32:01 +08:00
if ( Z_TYPE_P ( trace ) ! = IS_ARRAY ) {
2015-04-06 08:30:59 +08:00
RETURN_FALSE ;
}
2015-04-15 10:38:55 +08:00
res = estrdup ( " " ) ;
str = & res ;
2008-07-25 03:52:24 +08:00
zend_hash_apply_with_arguments ( Z_ARRVAL_P ( trace ) TSRMLS_CC , ( apply_func_args_t ) _build_trace_string , 3 , str , len , & num ) ;
2003-08-31 02:28:24 +08:00
2003-09-02 04:54:48 +08:00
s_tmp = emalloc ( 1 + MAX_LENGTH_OF_LONG + 7 + 1 ) ;
sprintf ( s_tmp , " #%d {main} " , num ) ;
TRACE_APPEND_STRL ( s_tmp , strlen ( s_tmp ) ) ;
efree ( s_tmp ) ;
2015-07-27 08:09:34 +08:00
res [ res_len ] = ' \0 ' ;
RETURN_STRINGL ( res , res_len , 0 ) ;
2003-08-31 02:28:24 +08:00
}
/* }}} */
2008-07-12 22:57:14 +08:00
/* {{{ proto string Exception::getPrevious()
Return previous Exception or NULL . */
ZEND_METHOD ( exception , getPrevious )
{
zval * previous ;
2009-05-11 22:14:52 +08:00
DEFAULT_0_PARAMS ;
2008-07-12 22:57:14 +08:00
previous = zend_read_property ( default_exception_ce , getThis ( ) , " previous " , sizeof ( " previous " ) - 1 , 1 TSRMLS_CC ) ;
RETURN_ZVAL ( previous , 1 , 0 ) ;
}
2015-11-21 20:54:21 +08:00
/* }}} */
2008-07-12 22:57:14 +08:00
2013-09-23 19:21:57 +08:00
int zend_spprintf ( char * * message , int max_len , const char * format , . . . ) /* { { { */
2003-11-30 01:03:45 +08:00
{
va_list arg ;
int len ;
2006-05-10 07:53:23 +08:00
va_start ( arg , format ) ;
2003-11-30 01:03:45 +08:00
len = zend_vspprintf ( message , max_len , format , arg ) ;
va_end ( arg ) ;
return len ;
}
2007-01-18 20:20:15 +08:00
/* }}} */
2004-07-20 17:24:22 +08:00
/* {{{ proto string Exception::__toString()
Obtain the string representation of the Exception object */
2003-10-23 03:00:42 +08:00
ZEND_METHOD ( exception , __toString )
2003-08-31 02:28:24 +08:00
{
2008-07-12 22:57:14 +08:00
zval message , file , line , * trace , * exception ;
2009-05-11 23:03:47 +08:00
char * str , * prev_str ;
2008-07-12 22:57:14 +08:00
int len = 0 ;
2003-08-31 02:28:24 +08:00
zend_fcall_info fci ;
zval fname ;
2015-07-27 08:09:34 +08:00
2009-05-11 22:14:52 +08:00
DEFAULT_0_PARAMS ;
2015-07-27 08:09:34 +08:00
2009-05-11 23:03:47 +08:00
str = estrndup ( " " , 0 ) ;
2004-02-11 00:08:01 +08:00
2008-07-12 22:57:14 +08:00
exception = getThis ( ) ;
2008-07-13 17:32:46 +08:00
ZVAL_STRINGL ( & fname , " gettraceasstring " , sizeof ( " gettraceasstring " ) - 1 , 1 ) ;
2003-08-31 02:28:24 +08:00
2015-07-27 08:09:34 +08:00
while ( exception & & Z_TYPE_P ( exception ) = = IS_OBJECT & & instanceof_function ( Z_OBJCE_P ( exception ) , default_exception_ce TSRMLS_CC ) ) {
2008-07-12 22:57:14 +08:00
prev_str = str ;
_default_exception_get_entry ( exception , " message " , sizeof ( " message " ) - 1 , & message TSRMLS_CC ) ;
_default_exception_get_entry ( exception , " file " , sizeof ( " file " ) - 1 , & file TSRMLS_CC ) ;
_default_exception_get_entry ( exception , " line " , sizeof ( " line " ) - 1 , & line TSRMLS_CC ) ;
convert_to_string ( & message ) ;
convert_to_string ( & file ) ;
convert_to_long ( & line ) ;
2015-07-27 08:09:34 +08:00
trace = NULL ;
2008-07-12 22:57:14 +08:00
fci . size = sizeof ( fci ) ;
fci . function_table = & Z_OBJCE_P ( exception ) - > function_table ;
fci . function_name = & fname ;
fci . symbol_table = NULL ;
2008-11-28 03:01:23 +08:00
fci . object_ptr = exception ;
2008-07-12 22:57:14 +08:00
fci . retval_ptr_ptr = & trace ;
fci . param_count = 0 ;
fci . params = NULL ;
fci . no_separation = 1 ;
zend_call_function ( & fci , NULL TSRMLS_CC ) ;
2015-07-27 08:09:34 +08:00
if ( trace & & Z_TYPE_P ( trace ) ! = IS_STRING ) {
2010-08-16 16:11:08 +08:00
zval_ptr_dtor ( & trace ) ;
2008-07-12 22:57:14 +08:00
trace = NULL ;
}
2003-08-31 02:28:24 +08:00
2008-07-12 22:57:14 +08:00
if ( Z_STRLEN ( message ) > 0 ) {
len = zend_spprintf ( & str , 0 , " exception '%s' with message '%s' in %s:%ld \n Stack trace: \n %s%s%s " ,
Z_OBJCE_P ( exception ) - > name , Z_STRVAL ( message ) , Z_STRVAL ( file ) , Z_LVAL ( line ) ,
( trace & & Z_STRLEN_P ( trace ) ) ? Z_STRVAL_P ( trace ) : " #0 {main} \n " ,
len ? " \n \n Next " : " " , prev_str ) ;
} else {
len = zend_spprintf ( & str , 0 , " exception '%s' in %s:%ld \n Stack trace: \n %s%s%s " ,
Z_OBJCE_P ( exception ) - > name , Z_STRVAL ( file ) , Z_LVAL ( line ) ,
( trace & & Z_STRLEN_P ( trace ) ) ? Z_STRVAL_P ( trace ) : " #0 {main} \n " ,
len ? " \n \n Next " : " " , prev_str ) ;
}
efree ( prev_str ) ;
zval_dtor ( & message ) ;
zval_dtor ( & file ) ;
zval_dtor ( & line ) ;
2004-02-11 00:08:01 +08:00
2016-10-03 15:09:02 +08:00
Z_OBJPROP_P ( exception ) - > nApplyCount + + ;
exception = zend_read_property ( default_exception_ce , exception , " previous " , sizeof ( " previous " ) - 1 , 1 TSRMLS_CC ) ;
if ( exception & & Z_TYPE_P ( exception ) = = IS_OBJECT & & Z_OBJPROP_P ( exception ) - > nApplyCount > 0 ) {
exception = NULL ;
}
2010-08-16 16:11:08 +08:00
if ( trace ) {
zval_ptr_dtor ( & trace ) ;
}
2004-01-03 03:27:02 +08:00
}
2008-07-13 17:32:46 +08:00
zval_dtor ( & fname ) ;
2003-08-31 02:28:24 +08:00
2016-10-03 15:09:02 +08:00
/* Reset apply counts */
exception = getThis ( ) ;
while ( exception & & Z_TYPE_P ( exception ) = = IS_OBJECT & & instanceof_function ( Z_OBJCE_P ( exception ) , default_exception_ce TSRMLS_CC ) ) {
if ( Z_OBJPROP_P ( exception ) - > nApplyCount ) {
Z_OBJPROP_P ( exception ) - > nApplyCount - - ;
} else {
break ;
}
exception = zend_read_property ( default_exception_ce , exception , " previous " , sizeof ( " previous " ) - 1 , 1 TSRMLS_CC ) ;
}
2003-08-31 02:28:24 +08:00
/* We store the result in the private property string so we can access
* the result in uncaught exception handlers without memleaks . */
2004-02-11 00:08:01 +08:00
zend_update_property_string ( default_exception_ce , getThis ( ) , " string " , sizeof ( " string " ) - 1 , str TSRMLS_CC ) ;
2003-08-31 02:28:24 +08:00
RETURN_STRINGL ( str , len , 0 ) ;
}
2004-07-20 17:24:22 +08:00
/* }}} */
2003-08-31 02:28:24 +08:00
2007-01-18 20:20:15 +08:00
/* {{{ internal structs */
2003-08-30 19:33:41 +08:00
/* All functions that may be used in uncaught exception handlers must be final
* and must not throw exceptions . Otherwise we would need a facility to handle
2006-05-10 07:53:23 +08:00
* such exceptions in that handler .
2003-09-02 04:02:47 +08:00
* Also all getXY ( ) methods are final because thy serve as read only access to
2006-05-10 07:53:23 +08:00
* their corresponding properties , no more , no less . If after all you need to
2003-10-23 03:00:42 +08:00
* override somthing then it is method __toString ( ) .
2003-09-02 04:02:47 +08:00
* And never try to change the state of exceptions and never implement anything
* that gives the user anything to accomplish this .
2003-08-30 19:33:41 +08:00
*/
2006-06-14 04:57:35 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_exception___construct , 0 , 0 , 0 )
2004-07-16 06:21:36 +08:00
ZEND_ARG_INFO ( 0 , message )
ZEND_ARG_INFO ( 0 , code )
2008-07-12 22:59:46 +08:00
ZEND_ARG_INFO ( 0 , previous )
2007-05-31 00:32:02 +08:00
ZEND_END_ARG_INFO ( )
2004-07-16 06:21:36 +08:00
2007-09-28 02:00:48 +08:00
const static zend_function_entry default_exception_functions [ ] = {
2003-10-26 03:07:09 +08:00
ZEND_ME ( exception , __clone , NULL , ZEND_ACC_PRIVATE | ZEND_ACC_FINAL )
2004-07-28 00:21:56 +08:00
ZEND_ME ( exception , __construct , arginfo_exception___construct , ZEND_ACC_PUBLIC )
2015-08-05 07:13:26 +08:00
ZEND_ME ( exception , __wakeup , NULL , ZEND_ACC_PUBLIC )
2003-09-17 18:15:00 +08:00
ZEND_ME ( exception , getMessage , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_FINAL )
ZEND_ME ( exception , getCode , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_FINAL )
ZEND_ME ( exception , getFile , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_FINAL )
ZEND_ME ( exception , getLine , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_FINAL )
ZEND_ME ( exception , getTrace , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_FINAL )
2008-07-12 22:57:14 +08:00
ZEND_ME ( exception , getPrevious , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_FINAL )
2003-09-17 18:15:00 +08:00
ZEND_ME ( exception , getTraceAsString , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_FINAL )
2003-10-23 03:00:42 +08:00
ZEND_ME ( exception , __toString , NULL , 0 )
2003-03-23 12:32:24 +08:00
{ NULL , NULL , NULL }
} ;
2006-06-14 04:57:35 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_error_exception___construct , 0 , 0 , 0 )
2004-07-16 06:21:36 +08:00
ZEND_ARG_INFO ( 0 , message )
ZEND_ARG_INFO ( 0 , code )
ZEND_ARG_INFO ( 0 , severity )
2004-07-25 15:05:48 +08:00
ZEND_ARG_INFO ( 0 , filename )
ZEND_ARG_INFO ( 0 , lineno )
2008-07-12 22:57:14 +08:00
ZEND_ARG_INFO ( 0 , previous )
2007-05-31 00:32:02 +08:00
ZEND_END_ARG_INFO ( )
2004-07-16 06:21:36 +08:00
2007-09-28 02:00:48 +08:00
static const zend_function_entry error_exception_functions [ ] = {
2004-07-28 00:21:56 +08:00
ZEND_ME ( error_exception , __construct , arginfo_error_exception___construct , ZEND_ACC_PUBLIC )
2004-07-16 06:21:36 +08:00
ZEND_ME ( error_exception , getSeverity , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_FINAL )
{ NULL , NULL , NULL }
} ;
2007-01-18 20:20:15 +08:00
/* }}} */
2004-07-16 06:21:36 +08:00
2007-01-18 20:20:15 +08:00
void zend_register_default_exception ( TSRMLS_D ) /* { { { */
2003-03-23 12:32:24 +08:00
{
2003-08-30 19:40:37 +08:00
zend_class_entry ce ;
2003-03-23 12:32:24 +08:00
2004-04-14 04:25:49 +08:00
INIT_CLASS_ENTRY ( ce , " Exception " , default_exception_functions ) ;
2004-02-11 00:08:01 +08:00
default_exception_ce = zend_register_internal_class ( & ce TSRMLS_CC ) ;
2006-05-10 07:53:23 +08:00
default_exception_ce - > create_object = zend_default_exception_new ;
2003-09-05 19:40:30 +08:00
memcpy ( & default_exception_handlers , zend_get_std_object_handlers ( ) , sizeof ( zend_object_handlers ) ) ;
2003-10-26 03:28:31 +08:00
default_exception_handlers . clone_obj = NULL ;
2003-08-24 03:41:22 +08:00
2004-02-11 00:08:01 +08:00
zend_declare_property_string ( default_exception_ce , " message " , sizeof ( " message " ) - 1 , " " , ZEND_ACC_PROTECTED TSRMLS_CC ) ;
zend_declare_property_string ( default_exception_ce , " string " , sizeof ( " string " ) - 1 , " " , ZEND_ACC_PRIVATE TSRMLS_CC ) ;
zend_declare_property_long ( default_exception_ce , " code " , sizeof ( " code " ) - 1 , 0 , ZEND_ACC_PROTECTED TSRMLS_CC ) ;
zend_declare_property_null ( default_exception_ce , " file " , sizeof ( " file " ) - 1 , ZEND_ACC_PROTECTED TSRMLS_CC ) ;
zend_declare_property_null ( default_exception_ce , " line " , sizeof ( " line " ) - 1 , ZEND_ACC_PROTECTED TSRMLS_CC ) ;
zend_declare_property_null ( default_exception_ce , " trace " , sizeof ( " trace " ) - 1 , ZEND_ACC_PRIVATE TSRMLS_CC ) ;
2008-07-12 22:57:14 +08:00
zend_declare_property_null ( default_exception_ce , " previous " , sizeof ( " previous " ) - 1 , ZEND_ACC_PRIVATE TSRMLS_CC ) ;
2004-07-16 06:21:36 +08:00
INIT_CLASS_ENTRY ( ce , " ErrorException " , error_exception_functions ) ;
error_exception_ce = zend_register_internal_class_ex ( & ce , default_exception_ce , NULL TSRMLS_CC ) ;
2006-05-10 07:53:23 +08:00
error_exception_ce - > create_object = zend_error_exception_new ;
2004-07-16 06:21:36 +08:00
zend_declare_property_long ( error_exception_ce , " severity " , sizeof ( " severity " ) - 1 , E_ERROR , ZEND_ACC_PROTECTED TSRMLS_CC ) ;
2003-03-23 12:32:24 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-03-23 12:32:24 +08:00
2007-01-18 20:20:15 +08:00
ZEND_API zend_class_entry * zend_exception_get_default ( TSRMLS_D ) /* { { { */
2003-05-04 07:54:57 +08:00
{
2004-02-11 00:08:01 +08:00
return default_exception_ce ;
2003-05-04 07:54:57 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-05-04 07:54:57 +08:00
2007-01-18 20:20:15 +08:00
ZEND_API zend_class_entry * zend_get_error_exception ( TSRMLS_D ) /* { { { */
2003-08-29 06:56:41 +08:00
{
2004-07-16 06:21:36 +08:00
return error_exception_ce ;
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-08-31 17:35:54 +08:00
2013-09-23 19:21:57 +08:00
ZEND_API zval * zend_throw_exception ( zend_class_entry * exception_ce , const char * message , long code TSRMLS_DC ) /* { { { */
2004-07-16 06:21:36 +08:00
{
zval * ex ;
2003-08-29 06:56:41 +08:00
MAKE_STD_ZVAL ( ex ) ;
if ( exception_ce ) {
2004-02-11 00:08:01 +08:00
if ( ! instanceof_function ( exception_ce , default_exception_ce TSRMLS_CC ) ) {
2004-02-25 21:11:00 +08:00
zend_error ( E_NOTICE , " Exceptions must be derived from the Exception base class " ) ;
2004-02-11 00:08:01 +08:00
exception_ce = default_exception_ce ;
2003-08-29 06:56:41 +08:00
}
} else {
2004-02-11 00:08:01 +08:00
exception_ce = default_exception_ce ;
2003-08-29 06:56:41 +08:00
}
object_init_ex ( ex , exception_ce ) ;
2006-05-10 07:53:23 +08:00
2003-08-29 06:56:41 +08:00
if ( message ) {
2004-02-11 00:08:01 +08:00
zend_update_property_string ( default_exception_ce , ex , " message " , sizeof ( " message " ) - 1 , message TSRMLS_CC ) ;
2003-08-29 06:56:41 +08:00
}
if ( code ) {
2004-02-11 00:08:01 +08:00
zend_update_property_long ( default_exception_ce , ex , " code " , sizeof ( " code " ) - 1 , code TSRMLS_CC ) ;
2003-08-29 06:56:41 +08:00
}
2004-02-03 20:17:09 +08:00
zend_throw_exception_internal ( ex TSRMLS_CC ) ;
2004-07-16 06:21:36 +08:00
return ex ;
2003-08-29 06:56:41 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-08-29 06:56:41 +08:00
2013-09-23 19:21:57 +08:00
ZEND_API zval * zend_throw_exception_ex ( zend_class_entry * exception_ce , long code TSRMLS_DC , const char * format , . . . ) /* { { { */
2003-08-22 07:32:13 +08:00
{
2004-07-16 06:21:36 +08:00
va_list arg ;
char * message ;
2004-09-28 06:06:10 +08:00
zval * zexception ;
2004-07-16 06:21:36 +08:00
2006-05-10 07:53:23 +08:00
va_start ( arg , format ) ;
2004-07-16 06:21:36 +08:00
zend_vspprintf ( & message , 0 , format , arg ) ;
va_end ( arg ) ;
2004-09-28 06:06:10 +08:00
zexception = zend_throw_exception ( exception_ce , message , code TSRMLS_CC ) ;
efree ( message ) ;
return zexception ;
2003-08-22 07:32:13 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-08-22 07:32:13 +08:00
2013-09-23 19:21:57 +08:00
ZEND_API zval * zend_throw_error_exception ( zend_class_entry * exception_ce , const char * message , long code , int severity TSRMLS_DC ) /* { { { */
2004-07-16 06:21:36 +08:00
{
zval * ex = zend_throw_exception ( exception_ce , message , code TSRMLS_CC ) ;
zend_update_property_long ( default_exception_ce , ex , " severity " , sizeof ( " severity " ) - 1 , severity TSRMLS_CC ) ;
return ex ;
}
2007-01-18 20:20:15 +08:00
/* }}} */
2004-07-16 06:21:36 +08:00
2007-01-18 20:20:15 +08:00
static void zend_error_va ( int type , const char * file , uint lineno , const char * format , . . . ) /* { { { */
2003-08-24 21:10:03 +08:00
{
va_list args ;
2006-05-10 07:53:23 +08:00
2003-08-24 21:10:03 +08:00
va_start ( args , format ) ;
2003-09-11 18:26:47 +08:00
zend_error_cb ( type , file , lineno , format , args ) ;
2003-08-24 21:10:03 +08:00
va_end ( args ) ;
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-08-24 21:10:03 +08:00
2009-01-02 21:14:49 +08:00
/* This function doesn't return if it uses E_ERROR */
ZEND_API void zend_exception_error ( zval * exception , int severity TSRMLS_DC ) /* { { { */
2003-08-24 21:10:03 +08:00
{
2003-12-07 02:12:26 +08:00
zend_class_entry * ce_exception = Z_OBJCE_P ( exception ) ;
2016-10-02 01:03:54 +08:00
EG ( exception ) = NULL ;
2004-02-11 00:08:01 +08:00
if ( instanceof_function ( ce_exception , default_exception_ce TSRMLS_CC ) ) {
2003-08-31 02:58:40 +08:00
zval * str , * file , * line ;
2003-12-07 02:12:26 +08:00
zend_call_method_with_0_params ( & exception , ce_exception , NULL , " __tostring " , & str ) ;
if ( ! EG ( exception ) ) {
if ( Z_TYPE_P ( str ) ! = IS_STRING ) {
zend_error ( E_WARNING , " %s::__toString() must return a string " , ce_exception - > name ) ;
} else {
2004-02-11 00:08:01 +08:00
zend_update_property_string ( default_exception_ce , exception , " string " , sizeof ( " string " ) - 1 , EG ( exception ) ? ce_exception - > name : Z_STRVAL_P ( str ) TSRMLS_CC ) ;
2003-12-07 02:12:26 +08:00
}
2003-12-05 09:44:45 +08:00
}
2003-11-30 21:53:19 +08:00
zval_ptr_dtor ( & str ) ;
2006-05-10 07:53:23 +08:00
2003-11-30 01:03:45 +08:00
if ( EG ( exception ) ) {
/* do the best we can to inform about the inner exception */
2004-02-11 00:08:01 +08:00
if ( instanceof_function ( ce_exception , default_exception_ce TSRMLS_CC ) ) {
file = zend_read_property ( default_exception_ce , EG ( exception ) , " file " , sizeof ( " file " ) - 1 , 1 TSRMLS_CC ) ;
line = zend_read_property ( default_exception_ce , EG ( exception ) , " line " , sizeof ( " line " ) - 1 , 1 TSRMLS_CC ) ;
2013-05-12 20:00:32 +08:00
convert_to_string ( file ) ;
file = ( Z_STRLEN_P ( file ) > 0 ) ? file : NULL ;
line = ( Z_TYPE_P ( line ) = = IS_LONG ) ? line : NULL ;
2003-11-30 01:03:45 +08:00
} else {
file = NULL ;
line = NULL ;
}
2006-05-19 05:24:04 +08:00
zend_error_va ( E_WARNING , file ? Z_STRVAL_P ( file ) : NULL , line ? Z_LVAL_P ( line ) : 0 , " Uncaught %s in exception handling during call to %s::__tostring() " , Z_OBJCE_P ( EG ( exception ) ) - > name , ce_exception - > name ) ;
2003-11-30 01:03:45 +08:00
}
2004-02-11 00:08:01 +08:00
str = zend_read_property ( default_exception_ce , exception , " string " , sizeof ( " string " ) - 1 , 1 TSRMLS_CC ) ;
file = zend_read_property ( default_exception_ce , exception , " file " , sizeof ( " file " ) - 1 , 1 TSRMLS_CC ) ;
line = zend_read_property ( default_exception_ce , exception , " line " , sizeof ( " line " ) - 1 , 1 TSRMLS_CC ) ;
2003-11-30 01:03:45 +08:00
2013-05-12 20:00:32 +08:00
convert_to_string ( str ) ;
convert_to_string ( file ) ;
convert_to_long ( line ) ;
zend_error_va ( severity , ( Z_STRLEN_P ( file ) > 0 ) ? Z_STRVAL_P ( file ) : NULL , Z_LVAL_P ( line ) , " Uncaught %s \n thrown " , Z_STRVAL_P ( str ) ) ;
2003-08-24 21:10:03 +08:00
} else {
2009-01-02 21:14:49 +08:00
zend_error ( severity , " Uncaught exception '%s' " , ce_exception - > name ) ;
2003-08-24 21:10:03 +08:00
}
2016-10-02 01:03:54 +08:00
zval_ptr_dtor ( & exception ) ;
2003-08-24 21:10:03 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-08-24 21:10:03 +08:00
2007-01-18 20:20:15 +08:00
ZEND_API void zend_throw_exception_object ( zval * exception TSRMLS_DC ) /* { { { */
2004-02-12 18:24:40 +08:00
{
zend_class_entry * exception_ce ;
2006-05-10 07:53:23 +08:00
if ( exception = = NULL | | Z_TYPE_P ( exception ) ! = IS_OBJECT ) {
2004-02-12 18:24:40 +08:00
zend_error ( E_ERROR , " Need to supply an object when throwing an exception " ) ;
}
exception_ce = Z_OBJCE_P ( exception ) ;
if ( ! exception_ce | | ! instanceof_function ( exception_ce , default_exception_ce TSRMLS_CC ) ) {
2004-02-25 21:11:00 +08:00
zend_error ( E_ERROR , " Exceptions must be valid objects derived from the Exception base class " ) ;
2004-02-12 18:24:40 +08:00
}
zend_throw_exception_internal ( exception TSRMLS_CC ) ;
}
2007-01-18 20:20:15 +08:00
/* }}} */
2004-02-12 18:24:40 +08:00
2003-03-23 12:32:24 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* indent - tabs - mode : t
* End :
*/