2003-03-23 12:32:24 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Zend Engine |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2014-01-03 11:08:10 +08:00
| Copyright ( c ) 1998 - 2014 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
2014-02-10 14:04:30 +08:00
void zend_exception_set_previous ( zend_object * exception , zend_object * add_previous TSRMLS_DC )
2008-07-14 05:42:49 +08:00
{
2014-02-10 14:04:30 +08:00
zval tmp , * previous , zv , * pzv ;
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 ;
}
2014-02-10 14:04:30 +08:00
ZVAL_OBJ ( & tmp , add_previous ) ;
if ( ! instanceof_function ( Z_OBJCE ( tmp ) , 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 ;
}
2014-02-10 14:04:30 +08:00
ZVAL_OBJ ( & zv , exception ) ;
pzv = & zv ;
do {
previous = zend_read_property ( default_exception_ce , pzv , " previous " , sizeof ( " previous " ) - 1 , 1 TSRMLS_CC ) ;
2008-07-14 05:42:49 +08:00
if ( Z_TYPE_P ( previous ) = = IS_NULL ) {
2014-02-10 14:04:30 +08:00
zend_update_property ( default_exception_ce , pzv , " previous " , sizeof ( " previous " ) - 1 , & tmp TSRMLS_CC ) ;
2014-04-02 18:34:44 +08:00
GC_REFCOUNT ( add_previous ) - - ;
2008-07-14 05:42:49 +08:00
return ;
}
2014-02-10 14:04:30 +08:00
pzv = previous ;
} while ( pzv & & Z_OBJ_P ( pzv ) ! = add_previous ) ;
2008-07-14 05:42:49 +08:00
}
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 ( ) ) {
2014-07-22 15:12:49 +08:00
zend_string * classname ;
2010-11-18 05:41:30 +08:00
if ( exception ! = NULL ) {
2014-07-22 15:12:49 +08:00
classname = zend_get_object_classname ( Z_OBJ_P ( exception ) TSRMLS_CC ) ;
DTRACE_EXCEPTION_THROWN ( classname - > val ) ;
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 ) {
2014-02-10 14:04:30 +08:00
zend_object * previous = EG ( exception ) ;
zend_exception_set_previous ( Z_OBJ_P ( exception ) , EG ( exception ) TSRMLS_CC ) ;
EG ( exception ) = Z_OBJ_P ( 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 ) ;
}
2014-07-07 19:50:44 +08:00
if ( ! EG ( current_execute_data ) - > func | |
! ZEND_USER_CODE ( EG ( current_execute_data ) - > func - > common . type ) | |
2004-12-07 15:46:12 +08:00
( 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 ) ) {
2014-02-10 14:04:30 +08:00
2014-02-14 21:48:45 +08:00
OBJ_RELEASE ( EG ( prev_exception ) ) ;
2008-08-14 18:24:52 +08:00
EG ( prev_exception ) = NULL ;
}
2004-02-12 18:38:14 +08:00
if ( ! EG ( exception ) ) {
return ;
}
2014-02-14 21:48:45 +08:00
OBJ_RELEASE ( EG ( exception ) ) ;
2004-02-12 18:38:14 +08:00
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
2014-02-10 14:04:30 +08:00
static zend_object * 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 ;
2014-02-10 14:04:30 +08:00
zval trace ;
2003-08-24 03:41:22 +08:00
2014-02-10 14:04:30 +08:00
Z_OBJ ( obj ) = object = zend_objects_new ( class_type TSRMLS_CC ) ;
2006-05-10 07:53:23 +08:00
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
2014-02-10 14:04:30 +08:00
zend_fetch_debug_backtrace ( & trace , skip_top_traces , 0 , 0 TSRMLS_CC ) ;
2014-02-21 20:14:42 +08:00
Z_SET_REFCOUNT ( trace , 0 ) ;
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 ) ;
2014-02-10 14:04:30 +08:00
zend_update_property ( default_exception_ce , & obj , " trace " , sizeof ( " trace " ) - 1 , & trace TSRMLS_CC ) ;
2003-08-24 03:41:22 +08:00
2014-02-10 14:04:30 +08:00
return object ;
2003-08-24 03:41:22 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-08-24 03:41:22 +08:00
2014-02-10 14:04:30 +08:00
static zend_object * 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
2014-02-10 14:04:30 +08:00
static zend_object * 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
{
2014-02-21 20:14:42 +08:00
zend_string * message = NULL ;
2003-08-23 22:22:28 +08:00
long code = 0 ;
2008-07-12 22:57:14 +08:00
zval * object , * previous = NULL ;
2014-02-21 20:14:42 +08:00
int argc = ZEND_NUM_ARGS ( ) ;
2003-03-23 14:57:16 +08:00
2014-02-21 20:14:42 +08:00
if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , argc TSRMLS_CC , " |SlO! " , & message , & code , & previous , default_exception_ce ) = = FAILURE ) {
2008-07-14 05:42:49 +08:00
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 ) {
2014-02-21 20:14:42 +08:00
zend_update_property_str ( default_exception_ce , object , " message " , sizeof ( " message " ) - 1 , message 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
/* }}} */
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 ) ;
2014-06-23 21:02:22 +08:00
ZVAL_COPY ( return_value , 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 */
2014-02-19 12:13:43 +08:00
# define TRACE_APPEND_CHR(chr) \
str = STR_REALLOC ( str , str - > len + 1 , 0 ) ; \
str - > val [ str - > len - 1 ] = chr
# define TRACE_APPEND_STRL(v, l) \
{ \
str = STR_REALLOC ( str , str - > len + ( l ) , 0 ) ; \
memcpy ( str - > val + str - > len - ( l ) , ( v ) , ( l ) ) ; \
2003-08-31 02:28:24 +08:00
}
2014-02-19 12:13:43 +08:00
# define TRACE_APPEND_STR(v) \
TRACE_APPEND_STRL ( ( v ) , sizeof ( ( v ) ) - 1 )
2003-08-31 02:28:24 +08:00
2014-02-10 14:04:30 +08:00
# define TRACE_APPEND_KEY(key) do { \
2014-02-19 12:13:43 +08:00
tmp = zend_hash_str_find ( ht , key , sizeof ( key ) - 1 ) ; \
if ( tmp ) { \
if ( Z_TYPE_P ( tmp ) ! = IS_STRING ) { \
zend_error ( E_WARNING , " Value for %s is no string " , key ) ; \
TRACE_APPEND_STR ( " [unknown] " ) ; \
2014-02-10 14:04:30 +08:00
} else { \
2014-02-19 12:13:43 +08:00
TRACE_APPEND_STRL ( Z_STRVAL_P ( tmp ) , Z_STRLEN_P ( tmp ) ) ; \
2014-02-10 14:04:30 +08:00
} \
} \
} while ( 0 )
2003-08-31 02:28:24 +08:00
2014-02-21 00:39:58 +08:00
2014-04-26 04:32:51 +08:00
# define TRACE_ARG_APPEND(vallen) do { \
int len = str - > len ; \
str = STR_REALLOC ( str , len + vallen , 0 ) ; \
memmove ( str - > val + len - l_added + 1 + vallen , str - > val + len - l_added + 1 , l_added ) ; \
} while ( 0 )
2014-02-21 00:39:58 +08:00
2007-01-18 20:20:15 +08:00
/* }}} */
2014-05-28 22:45:01 +08:00
static void _build_trace_args ( zval * arg , zend_string * * str_ptr TSRMLS_DC ) /* { { { */
2003-08-31 02:28:24 +08:00
{
2014-05-28 22:45:01 +08:00
zend_string * str = * str_ptr ;
2003-08-31 02:28:24 +08:00
/* 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 .
*/
2014-03-27 17:39:09 +08:00
ZVAL_DEREF ( arg ) ;
2014-02-10 14:04:30 +08:00
switch ( Z_TYPE_P ( arg ) ) {
2003-08-31 02:28:24 +08:00
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 ( ' \' ' ) ;
2014-02-10 14:04:30 +08:00
if ( Z_STRLEN_P ( arg ) > 15 ) {
TRACE_APPEND_STRL ( Z_STRVAL_P ( arg ) , 15 ) ;
2003-08-31 02:28:24 +08:00
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 {
2014-02-10 14:04:30 +08:00
l_added = Z_STRLEN_P ( arg ) ;
TRACE_APPEND_STRL ( Z_STRVAL_P ( 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-04-26 04:32:51 +08:00
unsigned char chr = str - > val [ str - > len - l_added ] ;
2014-02-21 00:39:58 +08:00
if ( chr < 32 | | chr = = ' \\ ' | | chr > 126 ) {
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added ] = ' \\ ' ;
2014-02-21 00:39:58 +08:00
switch ( chr ) {
case ' \n ' :
TRACE_ARG_APPEND ( 1 ) ;
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added ] = ' n ' ;
2014-02-21 00:39:58 +08:00
break ;
case ' \r ' :
TRACE_ARG_APPEND ( 1 ) ;
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added ] = ' r ' ;
2014-02-21 00:39:58 +08:00
break ;
case ' \t ' :
TRACE_ARG_APPEND ( 1 ) ;
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added ] = ' t ' ;
2014-02-21 00:39:58 +08:00
break ;
case ' \f ' :
TRACE_ARG_APPEND ( 1 ) ;
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added ] = ' f ' ;
2014-02-21 00:39:58 +08:00
break ;
case ' \v ' :
TRACE_ARG_APPEND ( 1 ) ;
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added ] = ' v ' ;
2014-02-21 00:39:58 +08:00
break ;
# ifndef PHP_WIN32
case ' \e ' :
# else
case VK_ESCAPE :
# endif
TRACE_ARG_APPEND ( 1 ) ;
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added ] = ' e ' ;
2014-02-21 00:39:58 +08:00
break ;
case ' \\ ' :
TRACE_ARG_APPEND ( 1 ) ;
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added ] = ' \\ ' ;
2014-02-21 00:39:58 +08:00
break ;
default :
TRACE_ARG_APPEND ( 3 ) ;
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added - 2 ] = ' x ' ;
2014-02-21 00:39:58 +08:00
if ( ( chr > > 4 ) < 10 ) {
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added - 1 ] = ( chr > > 4 ) + ' 0 ' ;
2014-02-21 00:39:58 +08:00
} else {
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added - 1 ] = ( chr > > 4 ) + ' A ' - 10 ;
2014-02-21 00:39:58 +08:00
}
if ( chr % 16 < 10 ) {
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added ] = chr % 16 + ' 0 ' ;
2014-02-21 00:39:58 +08:00
} else {
2014-04-26 04:32:51 +08:00
str - > val [ str - > len - l_added ] = chr % 16 + ' A ' - 10 ;
2014-02-21 00:39:58 +08:00
}
}
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
}
2014-04-30 22:32:42 +08:00
case IS_FALSE :
TRACE_APPEND_STR ( " false, " ) ;
break ;
case IS_TRUE :
TRACE_APPEND_STR ( " true, " ) ;
2003-08-31 02:28:24 +08:00
break ;
2014-02-22 02:59:51 +08:00
case IS_RESOURCE : {
long lval = Z_RES_HANDLE_P ( arg ) ;
char s_tmp [ MAX_LENGTH_OF_LONG + 1 ] ;
int l_tmp = zend_sprintf ( s_tmp , " %ld " , lval ) ; /* SAFE */
2003-08-31 02:28:24 +08:00
TRACE_APPEND_STR ( " Resource id # " ) ;
2014-02-22 02:59:51 +08:00
TRACE_APPEND_STRL ( s_tmp , l_tmp ) ;
TRACE_APPEND_STR ( " , " ) ;
break ;
}
2003-08-31 02:28:24 +08:00
case IS_LONG : {
2014-02-10 14:04:30 +08:00
long lval = Z_LVAL_P ( arg ) ;
2003-08-31 02:28:24 +08:00
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 : {
2014-02-10 14:04:30 +08:00
double dval = Z_DVAL_P ( arg ) ;
2003-08-31 02:28:24 +08:00
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 : {
2014-02-10 14:04:30 +08:00
zend_string * class_name ;
2003-08-31 02:28:24 +08:00
TRACE_APPEND_STR ( " Object( " ) ;
2005-06-28 02:13:13 +08:00
2014-03-28 06:11:22 +08:00
class_name = zend_get_object_classname ( Z_OBJ_P ( arg ) TSRMLS_CC ) ;
2005-06-28 02:13:13 +08:00
2014-02-10 14:04:30 +08:00
TRACE_APPEND_STRL ( class_name - > val , class_name - > len ) ;
2003-08-31 02:28:24 +08:00
TRACE_APPEND_STR ( " ), " ) ;
break ;
}
default :
break ;
}
2014-02-19 16:03:01 +08:00
* str_ptr = str ;
2003-08-31 02:28:24 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-08-31 02:28:24 +08:00
2014-05-28 22:45:01 +08:00
static void _build_trace_string ( zval * frame , ulong index , zend_string * * str_ptr , int * num TSRMLS_DC ) /* { { { */
2003-08-31 02:28:24 +08:00
{
2014-02-19 12:13:43 +08:00
char * s_tmp ;
2014-05-28 22:45:01 +08:00
int len ;
2003-08-31 02:28:24 +08:00
long line ;
2014-05-28 22:45:01 +08:00
HashTable * ht ;
2014-02-10 14:04:30 +08:00
zval * file , * tmp ;
2014-05-28 22:45:01 +08:00
zend_string * str = * str_ptr ;
2003-08-31 02:28:24 +08:00
2014-02-10 14:04:30 +08:00
if ( Z_TYPE_P ( frame ) ! = IS_ARRAY ) {
2014-05-28 22:45:01 +08:00
zend_error ( E_WARNING , " Expected array for frame %lu " , index ) ;
return ;
2012-12-14 05:39:35 +08:00
}
2014-05-28 22:45:01 +08:00
ht = Z_ARRVAL_P ( frame ) ;
2003-08-31 17:35:54 +08:00
s_tmp = emalloc ( 1 + MAX_LENGTH_OF_LONG + 1 + 1 ) ;
2014-02-19 12:13:43 +08:00
len = sprintf ( s_tmp , " #%d " , ( * num ) + + ) ;
TRACE_APPEND_STRL ( s_tmp , len ) ;
2003-08-31 02:58:40 +08:00
efree ( s_tmp ) ;
2014-02-10 14:04:30 +08:00
file = zend_hash_str_find ( ht , " file " , sizeof ( " file " ) - 1 ) ;
if ( file ) {
if ( Z_TYPE_P ( file ) ! = IS_STRING ) {
2012-12-14 05:39:35 +08:00
zend_error ( E_WARNING , " Function name is no string " ) ;
TRACE_APPEND_STR ( " [unknown function] " ) ;
} else {
2014-02-10 14:04:30 +08:00
tmp = zend_hash_str_find ( ht , " line " , sizeof ( " line " ) - 1 ) ;
if ( tmp ) {
if ( Z_TYPE_P ( tmp ) = = IS_LONG ) {
line = Z_LVAL_P ( tmp ) ;
2012-12-14 05:39:35 +08:00
} else {
zend_error ( E_WARNING , " Line is no long " ) ;
line = 0 ;
}
} else {
line = 0 ;
}
2014-02-10 14:04:30 +08:00
s_tmp = emalloc ( Z_STRLEN_P ( file ) + MAX_LENGTH_OF_LONG + 4 + 1 ) ;
2014-02-19 12:13:43 +08:00
len = sprintf ( s_tmp , " %s(%ld): " , Z_STRVAL_P ( file ) , line ) ;
TRACE_APPEND_STRL ( s_tmp , len ) ;
2012-12-14 05:39:35 +08:00
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 ( ' ( ' ) ;
2014-02-10 14:04:30 +08:00
tmp = zend_hash_str_find ( ht , " args " , sizeof ( " args " ) - 1 ) ;
if ( tmp ) {
if ( Z_TYPE_P ( tmp ) = = IS_ARRAY ) {
2014-02-19 12:13:43 +08:00
int last_len = str - > len ;
2014-05-28 22:45:01 +08:00
zval * arg ;
ZEND_HASH_FOREACH_VAL ( Z_ARRVAL_P ( tmp ) , arg ) {
_build_trace_args ( arg , & str TSRMLS_CC ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2014-02-19 12:13:43 +08:00
if ( last_len ! = str - > len ) {
str - > len - = 2 ; /* remove last ', ' */
2012-12-14 05:39:35 +08:00
}
} 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 " ) ;
2014-02-19 16:03:01 +08:00
* str_ptr = str ;
2003-08-31 02:28:24 +08:00
}
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
{
2014-05-28 22:45:01 +08:00
zval * trace , * frame ;
ulong index ;
zend_string * str , * key ;
2014-02-19 12:13:43 +08:00
int num = 0 , len ;
char s_tmp [ MAX_LENGTH_OF_LONG + 7 + 1 + 1 ] ;
2006-05-10 07:53:23 +08:00
2009-05-11 22:14:52 +08:00
DEFAULT_0_PARAMS ;
2009-05-11 23:03:47 +08:00
2014-02-19 12:13:43 +08:00
str = STR_ALLOC ( 0 , 0 ) ;
2009-05-11 22:14:52 +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 ) ;
2014-05-28 22:45:01 +08:00
ZEND_HASH_FOREACH_KEY_VAL ( Z_ARRVAL_P ( trace ) , index , key , frame ) {
_build_trace_string ( frame , index , & str , & num TSRMLS_CC ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2003-08-31 02:28:24 +08:00
2014-02-19 12:13:43 +08:00
len = sprintf ( s_tmp , " #%d {main} " , num ) ;
TRACE_APPEND_STRL ( s_tmp , len ) ;
str - > val [ str - > len ] = ' \0 ' ;
2003-09-02 04:54:48 +08:00
2014-04-03 19:26:23 +08:00
RETURN_NEW_STR ( str ) ;
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 ) ;
2014-05-10 00:21:49 +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
2014-05-10 00:21:49 +08:00
zend_string * zend_strpprintf ( int max_len , const char * format , . . . ) /* { { { */
{
va_list arg ;
zend_string * str ;
va_start ( arg , format ) ;
str = zend_vstrpprintf ( max_len , format , arg ) ;
va_end ( arg ) ;
return str ;
}
/* }}} */
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
{
2014-02-14 21:48:45 +08:00
zval message , file , line , trace , * exception ;
2014-05-10 00:21:49 +08:00
zend_string * str , * prev_str ;
2003-08-31 02:28:24 +08:00
zend_fcall_info fci ;
zval fname ;
2009-05-11 22:14:52 +08:00
DEFAULT_0_PARAMS ;
2009-05-11 23:03:47 +08:00
2014-05-10 00:21:49 +08:00
str = STR_EMPTY_ALLOC ( ) ;
2004-02-11 00:08:01 +08:00
2008-07-12 22:57:14 +08:00
exception = getThis ( ) ;
2014-02-10 14:04:30 +08:00
ZVAL_STRINGL ( & fname , " gettraceasstring " , sizeof ( " gettraceasstring " ) - 1 ) ;
2003-08-31 02:28:24 +08:00
2008-07-12 22:57:14 +08:00
while ( exception & & Z_TYPE_P ( exception ) = = IS_OBJECT ) {
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 ) ;
fci . size = sizeof ( fci ) ;
fci . function_table = & Z_OBJCE_P ( exception ) - > function_table ;
2014-02-10 14:04:30 +08:00
ZVAL_COPY_VALUE ( & fci . function_name , & fname ) ;
2008-07-12 22:57:14 +08:00
fci . symbol_table = NULL ;
2014-03-28 06:11:22 +08:00
fci . object = Z_OBJ_P ( exception ) ;
2014-02-14 21:48:45 +08:00
fci . retval = & trace ;
2008-07-12 22:57:14 +08:00
fci . param_count = 0 ;
fci . params = NULL ;
fci . no_separation = 1 ;
zend_call_function ( & fci , NULL TSRMLS_CC ) ;
2014-02-14 21:48:45 +08:00
if ( Z_TYPE ( trace ) ! = IS_STRING ) {
zval_ptr_dtor ( & trace ) ;
ZVAL_UNDEF ( & trace ) ;
}
2003-08-31 02:28:24 +08:00
2008-07-12 22:57:14 +08:00
if ( Z_STRLEN ( message ) > 0 ) {
2014-05-10 00:21:49 +08:00
str = zend_strpprintf ( 0 , " exception '%s' with message '%s' in %s:%ld \n Stack trace: \n %s%s%s " ,
Z_OBJCE_P ( exception ) - > name - > val , Z_STRVAL ( message ) , Z_STRVAL ( file ) , Z_LVAL ( line ) ,
( Z_TYPE ( trace ) = = IS_STRING & & Z_STRLEN ( trace ) ) ? Z_STRVAL ( trace ) : " #0 {main} \n " ,
prev_str - > len ? " \n \n Next " : " " , prev_str - > val ) ;
2008-07-12 22:57:14 +08:00
} else {
2014-05-10 00:21:49 +08:00
str = zend_strpprintf ( 0 , " exception '%s' in %s:%ld \n Stack trace: \n %s%s%s " ,
Z_OBJCE_P ( exception ) - > name - > val , Z_STRVAL ( file ) , Z_LVAL ( line ) ,
( Z_TYPE ( trace ) = = IS_STRING & & Z_STRLEN ( trace ) ) ? Z_STRVAL ( trace ) : " #0 {main} \n " ,
prev_str - > len ? " \n \n Next " : " " , prev_str - > val ) ;
2008-07-12 22:57:14 +08:00
}
2014-05-10 00:21:49 +08:00
STR_RELEASE ( prev_str ) ;
2008-07-12 22:57:14 +08:00
zval_dtor ( & message ) ;
zval_dtor ( & file ) ;
zval_dtor ( & line ) ;
2004-02-11 00:08:01 +08:00
2008-07-12 22:57:14 +08:00
exception = zend_read_property ( default_exception_ce , exception , " previous " , sizeof ( " previous " ) - 1 , 0 TSRMLS_CC ) ;
2010-08-16 16:11:08 +08:00
2014-02-14 21:48:45 +08:00
zval_ptr_dtor ( & trace ) ;
2010-08-16 16:11:08 +08:00
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
/* We store the result in the private property string so we can access
* the result in uncaught exception handlers without memleaks . */
2014-05-10 00:21:49 +08:00
zend_update_property_str ( default_exception_ce , getThis ( ) , " string " , sizeof ( " string " ) - 1 , str TSRMLS_CC ) ;
2004-02-11 00:08:01 +08:00
2014-05-10 00:21:49 +08:00
RETURN_STR ( str ) ;
2003-08-31 02:28:24 +08:00
}
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 )
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 ) ;
2014-02-10 14:04:30 +08:00
error_exception_ce = zend_register_internal_class_ex ( & ce , default_exception_ce 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
2014-02-10 14:04:30 +08:00
ZEND_API zend_object * zend_throw_exception ( zend_class_entry * exception_ce , const char * message , long code TSRMLS_DC ) /* { { { */
2004-07-16 06:21:36 +08:00
{
2014-02-10 14:04:30 +08:00
zval ex ;
2003-08-29 06:56:41 +08:00
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
}
2014-02-10 14:04:30 +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 ) {
2014-02-10 14:04:30 +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 ) {
2014-02-10 14:04:30 +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
}
2014-02-10 14:04:30 +08:00
zend_throw_exception_internal ( & ex TSRMLS_CC ) ;
return Z_OBJ ( 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
2014-02-10 14:04:30 +08:00
ZEND_API zend_object * 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 ;
2014-02-10 14:04:30 +08:00
zend_object * obj ;
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 ) ;
2014-02-10 14:04:30 +08:00
obj = zend_throw_exception ( exception_ce , message , code TSRMLS_CC ) ;
2004-09-28 06:06:10 +08:00
efree ( message ) ;
2014-02-10 14:04:30 +08:00
return obj ;
2003-08-22 07:32:13 +08:00
}
2007-01-18 20:20:15 +08:00
/* }}} */
2003-08-22 07:32:13 +08:00
2014-02-10 14:04:30 +08:00
ZEND_API zend_object * 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
{
2014-02-10 14:04:30 +08:00
zval ex ;
zend_object * obj = zend_throw_exception ( exception_ce , message , code TSRMLS_CC ) ;
ZVAL_OBJ ( & ex , obj ) ;
zend_update_property_long ( default_exception_ce , & ex , " severity " , sizeof ( " severity " ) - 1 , severity TSRMLS_CC ) ;
return obj ;
2004-07-16 06:21:36 +08:00
}
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 */
2014-02-10 14:04:30 +08:00
ZEND_API void zend_exception_error ( zend_object * ex , int severity TSRMLS_DC ) /* { { { */
2003-08-24 21:10:03 +08:00
{
2014-02-10 14:04:30 +08:00
zval exception ;
zend_class_entry * ce_exception ;
ZVAL_OBJ ( & exception , ex ) ;
ce_exception = Z_OBJCE ( exception ) ;
2004-02-11 00:08:01 +08:00
if ( instanceof_function ( ce_exception , default_exception_ce TSRMLS_CC ) ) {
2014-02-10 14:04:30 +08:00
zval tmp , * str , * file , * line ;
2003-08-31 02:58:40 +08:00
2003-11-30 01:03:45 +08:00
EG ( exception ) = NULL ;
2006-05-10 07:53:23 +08:00
2014-02-10 14:04:30 +08:00
zend_call_method_with_0_params ( & exception , ce_exception , NULL , " __tostring " , & tmp ) ;
2003-12-07 02:12:26 +08:00
if ( ! EG ( exception ) ) {
2014-02-10 14:04:30 +08:00
if ( Z_TYPE ( tmp ) ! = IS_STRING ) {
zend_error ( E_WARNING , " %s::__toString() must return a string " , ce_exception - > name - > val ) ;
2003-12-07 02:12:26 +08:00
} else {
2014-02-10 14:04:30 +08:00
zend_update_property_string ( default_exception_ce , & exception , " string " , sizeof ( " string " ) - 1 , EG ( exception ) ? ce_exception - > name - > val : Z_STRVAL ( tmp ) TSRMLS_CC ) ;
2003-12-07 02:12:26 +08:00
}
2003-12-05 09:44:45 +08:00
}
2014-02-10 14:04:30 +08:00
zval_ptr_dtor ( & tmp ) ;
2006-05-10 07:53:23 +08:00
2003-11-30 01:03:45 +08:00
if ( EG ( exception ) ) {
2014-02-10 14:04:30 +08:00
zval zv ;
ZVAL_OBJ ( & zv , EG ( exception ) ) ;
2003-11-30 01:03:45 +08:00
/* 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 ) ) {
2014-02-10 14:04:30 +08:00
file = zend_read_property ( default_exception_ce , & zv , " file " , sizeof ( " file " ) - 1 , 1 TSRMLS_CC ) ;
line = zend_read_property ( default_exception_ce , & zv , " 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 ;
}
2014-02-10 14:04:30 +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 ( zv ) - > name - > val , ce_exception - > name - > val ) ;
2003-11-30 01:03:45 +08:00
}
2014-02-10 14:04:30 +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 {
2014-02-10 14:04:30 +08:00
zend_error ( severity , " Uncaught exception '%s' " , ce_exception - > name - > val ) ;
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 :
*/