LTP GCOV extension - code coverage report
Current view: directory - Zend - zend_exceptions.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 296
Code covered: 46.3 % Executed lines: 137
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | Zend Engine                                                          |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1998-2007 Zend Technologies Ltd. (http://www.zend.com) |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 2.00 of the Zend license,     |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.zend.com/license/2_00.txt.                                |
      11                 :    | If you did not receive a copy of the Zend license and are unable to  |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@zend.com so we can mail you a copy immediately.              |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16                 :    |          Marcus Boerger <helly@php.net>                              |
      17                 :    |          Sterling Hughes <sterling@php.net>                          |
      18                 :    |          Zeev Suraski <zeev@zend.com>                                |
      19                 :    +----------------------------------------------------------------------+
      20                 : */
      21                 : 
      22                 : /* $Id: zend_exceptions.c,v 1.79.2.6.2.8 2007/01/18 12:20:15 tony2001 Exp $ */
      23                 : 
      24                 : #include "zend.h"
      25                 : #include "zend_API.h"
      26                 : #include "zend_builtin_functions.h"
      27                 : #include "zend_interfaces.h"
      28                 : #include "zend_exceptions.h"
      29                 : 
      30                 : zend_class_entry *default_exception_ce;
      31                 : zend_class_entry *error_exception_ce;
      32                 : static zend_object_handlers default_exception_handlers;
      33                 : ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
      34                 : 
      35                 : void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
      36              40 : {
      37              40 :         if (exception != NULL) {
      38              28 :                 if (EG(exception)) {
      39                 :                         /* FIXME:  bail out? */
      40               0 :                         return;
      41                 :                 }
      42              28 :                 EG(exception) = exception;
      43                 :         }
      44              40 :         if (!EG(current_execute_data)) {
      45               0 :                 zend_error(E_ERROR, "Exception thrown without a stack frame");
      46                 :         }
      47                 : 
      48              40 :         if (zend_throw_exception_hook) {
      49               0 :                 zend_throw_exception_hook(exception TSRMLS_CC);
      50                 :         }
      51                 : 
      52              40 :         if (EG(current_execute_data)->opline == NULL ||
      53                 :             (EG(current_execute_data)->opline+1)->opcode == ZEND_HANDLE_EXCEPTION) {
      54                 :                 /* no need to rethrow the exception */
      55              16 :                 return;
      56                 :         }
      57              24 :         EG(opline_before_exception) = EG(current_execute_data)->opline;
      58              24 :         EG(current_execute_data)->opline = &EG(active_op_array)->opcodes[EG(active_op_array)->last-1-1];
      59                 : }
      60                 : /* }}} */
      61                 : 
      62                 : ZEND_API void zend_clear_exception(TSRMLS_D) /* {{{ */
      63               0 : {
      64               0 :         if (!EG(exception)) {
      65               0 :                 return;
      66                 :         }
      67               0 :         zval_ptr_dtor(&EG(exception));
      68               0 :         EG(exception) = NULL;
      69               0 :         EG(current_execute_data)->opline = EG(opline_before_exception);
      70                 : #if ZEND_DEBUG
      71                 :         EG(opline_before_exception) = NULL;
      72                 : #endif
      73                 : }
      74                 : /* }}} */
      75                 : 
      76                 : static zend_object_value zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces TSRMLS_DC) /* {{{ */
      77              30 : {
      78                 :         zval tmp, obj;
      79                 :         zend_object *object;
      80                 :         zval *trace;
      81                 : 
      82              30 :         Z_OBJVAL(obj) = zend_objects_new(&object, class_type TSRMLS_CC);
      83              30 :         Z_OBJ_HT(obj) = &default_exception_handlers;
      84                 : 
      85              30 :         ALLOC_HASHTABLE(object->properties);
      86              30 :         zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
      87              30 :         zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
      88                 : 
      89              30 :         ALLOC_ZVAL(trace);
      90              30 :         trace->is_ref = 0;
      91              30 :         trace->refcount = 0;
      92              30 :         zend_fetch_debug_backtrace(trace, skip_top_traces, 0 TSRMLS_CC);
      93                 : 
      94              30 :         zend_update_property_string(default_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename(TSRMLS_C) TSRMLS_CC);
      95              30 :         zend_update_property_long(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC);
      96              30 :         zend_update_property(default_exception_ce, &obj, "trace", sizeof("trace")-1, trace TSRMLS_CC);
      97                 : 
      98              30 :         return Z_OBJVAL(obj);
      99                 : }
     100                 : /* }}} */
     101                 : 
     102                 : static zend_object_value zend_default_exception_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
     103              30 : {
     104              30 :         return zend_default_exception_new_ex(class_type, 0 TSRMLS_CC);
     105                 : }
     106                 : /* }}} */
     107                 : 
     108                 : static zend_object_value zend_error_exception_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
     109               0 : {
     110               0 :         return zend_default_exception_new_ex(class_type, 2 TSRMLS_CC);
     111                 : }
     112                 : /* }}} */
     113                 : 
     114                 : /* {{{ proto Exception Exception::__clone()
     115                 :    Clone the exception object */
     116                 : ZEND_METHOD(exception, __clone)
     117               0 : {
     118                 :         /* Should never be executable */
     119               0 :         zend_throw_exception(NULL, "Cannot clone object using __clone()", 0 TSRMLS_CC);
     120               0 : }
     121                 : /* }}} */
     122                 : 
     123                 : /* {{{ proto Exception::__construct(string message, int code)
     124                 :    Exception constructor */
     125                 : ZEND_METHOD(exception, __construct)
     126              12 : {
     127              12 :         char  *message = NULL;
     128              12 :         long   code = 0;
     129                 :         zval  *object;
     130              12 :         int    argc = ZEND_NUM_ARGS(), message_len;
     131                 : 
     132              12 :         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|sl", &message, &message_len, &code) == FAILURE) {
     133               0 :                 zend_error(E_ERROR, "Wrong parameters for Exception([string $exception [, long $code ]])");
     134                 :         }
     135                 : 
     136              12 :         object = getThis();
     137                 : 
     138              12 :         if (message) {
     139               0 :                 zend_update_property_string(default_exception_ce, object, "message", sizeof("message")-1, message TSRMLS_CC);
     140                 :         }
     141                 : 
     142              12 :         if (code) {
     143               0 :                 zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC);
     144                 :         }
     145              12 : }
     146                 : /* }}} */
     147                 : 
     148                 : /* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno]])
     149                 :    ErrorException constructor */
     150                 : ZEND_METHOD(error_exception, __construct)
     151               0 : {
     152               0 :         char  *message = NULL, *filename = NULL;
     153               0 :         long   code = 0, severity = E_ERROR, lineno;
     154                 :         zval  *object;
     155               0 :         int    argc = ZEND_NUM_ARGS(), message_len, filename_len;
     156                 : 
     157               0 :         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|sllsl", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno) == FAILURE) {
     158               0 :                 zend_error(E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno ]]]]])");
     159                 :         }
     160                 : 
     161               0 :         object = getThis();
     162                 : 
     163               0 :         if (message) {
     164               0 :                 zend_update_property_string(default_exception_ce, object, "message", sizeof("message")-1, message TSRMLS_CC);
     165                 :         }
     166                 : 
     167               0 :         if (code) {
     168               0 :                 zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC);
     169                 :         }
     170                 : 
     171               0 :         zend_update_property_long(default_exception_ce, object, "severity", sizeof("severity")-1, severity TSRMLS_CC);
     172                 : 
     173               0 :         if (argc >= 4) {
     174               0 :             zend_update_property_string(default_exception_ce, object, "file", sizeof("file")-1, filename TSRMLS_CC);
     175               0 :         if (argc < 5) {
     176               0 :             lineno = 0; /* invalidate lineno */
     177                 :         }
     178               0 :         zend_update_property_long(default_exception_ce, object, "line", sizeof("line")-1, lineno TSRMLS_CC);
     179                 :         }
     180               0 : }
     181                 : /* }}} */
     182                 : 
     183                 : #define DEFAULT_0_PARAMS \
     184                 :         if (ZEND_NUM_ARGS() > 0) { \
     185                 :                 ZEND_WRONG_PARAM_COUNT(); \
     186                 :         }
     187                 : 
     188                 : static void _default_exception_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC) /* {{{ */
     189               8 : {
     190                 :         zval *value;
     191                 : 
     192               8 :         value = zend_read_property(default_exception_ce, object, name, name_len, 0 TSRMLS_CC);
     193                 : 
     194               8 :         *return_value = *value;
     195               8 :         zval_copy_ctor(return_value);
     196               8 :         INIT_PZVAL(return_value);
     197               8 : }
     198                 : /* }}} */
     199                 : 
     200                 : /* {{{ proto string Exception::getFile()
     201                 :    Get the file in which the exception occurred */
     202                 : ZEND_METHOD(exception, getFile)
     203               0 : {
     204               0 :         DEFAULT_0_PARAMS;
     205                 : 
     206               0 :         _default_exception_get_entry(getThis(), "file", sizeof("file")-1, return_value TSRMLS_CC);
     207                 : }
     208                 : /* }}} */
     209                 : 
     210                 : /* {{{ proto int Exception::getLine()
     211                 :    Get the line in which the exception occurred */
     212                 : ZEND_METHOD(exception, getLine)
     213               0 : {
     214               0 :         DEFAULT_0_PARAMS;
     215                 : 
     216               0 :         _default_exception_get_entry(getThis(), "line", sizeof("line")-1, return_value TSRMLS_CC);
     217                 : }
     218                 : /* }}} */
     219                 : 
     220                 : /* {{{ proto string Exception::getMessage()
     221                 :    Get the exception message */
     222                 : ZEND_METHOD(exception, getMessage)
     223               8 : {
     224               8 :         DEFAULT_0_PARAMS;
     225                 : 
     226               8 :         _default_exception_get_entry(getThis(), "message", sizeof("message")-1, return_value TSRMLS_CC);
     227                 : }
     228                 : /* }}} */
     229                 : 
     230                 : /* {{{ proto int Exception::getCode()
     231                 :    Get the exception code */
     232                 : ZEND_METHOD(exception, getCode)
     233               0 : {
     234               0 :         DEFAULT_0_PARAMS;
     235                 : 
     236               0 :         _default_exception_get_entry(getThis(), "code", sizeof("code")-1, return_value TSRMLS_CC);
     237                 : }
     238                 : /* }}} */
     239                 : 
     240                 : /* {{{ proto array Exception::getTrace()
     241                 :    Get the stack trace for the location in which the exception occurred */
     242                 : ZEND_METHOD(exception, getTrace)
     243               0 : {
     244               0 :         DEFAULT_0_PARAMS;
     245                 : 
     246               0 :         _default_exception_get_entry(getThis(), "trace", sizeof("trace")-1, return_value TSRMLS_CC);
     247                 : }
     248                 : /* }}} */
     249                 : 
     250                 : /* {{{ proto int ErrorException::getSeverity()
     251                 :    Get the exception severity */
     252                 : ZEND_METHOD(error_exception, getSeverity)
     253               0 : {
     254               0 :         DEFAULT_0_PARAMS;
     255                 : 
     256               0 :         _default_exception_get_entry(getThis(), "severity", sizeof("severity")-1, return_value TSRMLS_CC);
     257                 : }
     258                 : /* }}} */
     259                 : 
     260                 : /* {{{ gettraceasstring() macros */
     261                 : #define TRACE_APPEND_CHR(chr)                                            \
     262                 :         *str = (char*)erealloc(*str, *len + 1 + 1);                          \
     263                 :         (*str)[(*len)++] = chr
     264                 : 
     265                 : #define TRACE_APPEND_STRL(val, vallen)                                   \
     266                 :         {                                                                    \
     267                 :                 int l = vallen;                                                  \
     268                 :                 *str = (char*)erealloc(*str, *len + l + 1);                      \
     269                 :                 memcpy((*str) + *len, val, l);                                   \
     270                 :                 *len += l;                                                       \
     271                 :         }
     272                 : 
     273                 : #define TRACE_APPEND_STR(val)                                            \
     274                 :         TRACE_APPEND_STRL(val, sizeof(val)-1)
     275                 : 
     276                 : #define TRACE_APPEND_KEY(key)                                            \
     277                 :         if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
     278                 :             TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \
     279                 :         }
     280                 : 
     281                 : /* }}} */
     282                 : 
     283                 : static int _build_trace_args(zval **arg, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
     284               4 : {
     285                 :         char **str;
     286                 :         int *len;
     287                 : 
     288               4 :         str = va_arg(args, char**);
     289               4 :         len = va_arg(args, int*);
     290                 : 
     291                 :         /* the trivial way would be to do:
     292                 :          * conver_to_string_ex(arg);
     293                 :          * append it and kill the now tmp arg.
     294                 :          * but that could cause some E_NOTICE and also damn long lines.
     295                 :          */
     296                 : 
     297               4 :         switch (Z_TYPE_PP(arg)) {
     298                 :                 case IS_NULL:
     299               0 :                         TRACE_APPEND_STR("NULL, ");
     300               0 :                         break;
     301                 :                 case IS_STRING: {
     302                 :                         int l_added;
     303               0 :                         TRACE_APPEND_CHR('\'');
     304               0 :                         if (Z_STRLEN_PP(arg) > 15) {
     305               0 :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
     306               0 :                                 TRACE_APPEND_STR("...', ");
     307               0 :                                 l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
     308                 :                         } else {
     309               0 :                                 l_added = Z_STRLEN_PP(arg);
     310               0 :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
     311               0 :                                 TRACE_APPEND_STR("', ");
     312               0 :                                 l_added += 3 + 1;
     313                 :                         }
     314               0 :                         while (--l_added) {
     315               0 :                                 if ((*str)[*len - l_added] < 32) {
     316               0 :                                         (*str)[*len - l_added] = '?';
     317                 :                                 }
     318                 :                         }
     319               0 :                         break;
     320                 :                 }
     321                 :                 case IS_BOOL:
     322               0 :                         if (Z_LVAL_PP(arg)) {
     323               0 :                                 TRACE_APPEND_STR("true, ");
     324                 :                         } else {
     325               0 :                                 TRACE_APPEND_STR("false, ");
     326                 :                         }
     327               0 :                         break;
     328                 :                 case IS_RESOURCE:
     329               0 :                         TRACE_APPEND_STR("Resource id #");
     330                 :                         /* break; */
     331                 :                 case IS_LONG: {
     332               0 :                         long lval = Z_LVAL_PP(arg);
     333                 :                         char s_tmp[MAX_LENGTH_OF_LONG + 1];
     334               0 :                         int l_tmp = zend_sprintf(s_tmp, "%ld", lval);  /* SAFE */
     335               0 :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
     336               0 :                         TRACE_APPEND_STR(", ");
     337               0 :                         break;
     338                 :                 }
     339                 :                 case IS_DOUBLE: {
     340               0 :                         double dval = Z_DVAL_PP(arg);
     341                 :                         char *s_tmp;
     342                 :                         int l_tmp;
     343                 :                         TSRMLS_FETCH();
     344                 : 
     345               0 :                         s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
     346               0 :                         l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval);  /* SAFE */
     347               0 :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
     348                 :                         /* %G already handles removing trailing zeros from the fractional part, yay */
     349               0 :                         efree(s_tmp);
     350               0 :                         TRACE_APPEND_STR(", ");
     351               0 :                         break;
     352                 :                 }
     353                 :                 case IS_ARRAY:
     354               2 :                         TRACE_APPEND_STR("Array, ");
     355               2 :                         break;
     356                 :                 case IS_OBJECT: {
     357                 :                         char *class_name;
     358                 :                         zend_uint class_name_len;
     359                 :                         int dup;
     360                 :                         TSRMLS_FETCH();
     361                 : 
     362               2 :                         TRACE_APPEND_STR("Object(");
     363                 : 
     364               2 :                         dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
     365                 : 
     366               2 :                         TRACE_APPEND_STRL(class_name, class_name_len);
     367               2 :                         if(!dup) {
     368               2 :                                 efree(class_name);
     369                 :                         }
     370                 : 
     371               2 :                         TRACE_APPEND_STR("), ");
     372                 :                         break;
     373                 :                 }
     374                 :                 default:
     375                 :                         break;
     376                 :         }
     377               4 :         return ZEND_HASH_APPLY_KEEP;
     378                 : }
     379                 : /* }}} */
     380                 : 
     381                 : static int _build_trace_string(zval **frame, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
     382               6 : {
     383                 :         char *s_tmp, **str;
     384                 :         int *len, *num;
     385                 :         long line;
     386               6 :         HashTable *ht = Z_ARRVAL_PP(frame);
     387                 :         zval **file, **tmp;
     388                 : 
     389               6 :         str = va_arg(args, char**);
     390               6 :         len = va_arg(args, int*);
     391               6 :         num = va_arg(args, int*);
     392                 : 
     393               6 :         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
     394               6 :         sprintf(s_tmp, "#%d ", (*num)++);
     395               6 :         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     396               6 :         efree(s_tmp);
     397               6 :         if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
     398               4 :                 if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
     399               4 :                         line = Z_LVAL_PP(tmp);
     400                 :                 } else {
     401               0 :                         line = 0;
     402                 :                 }
     403               4 :                 s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
     404               4 :                 sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
     405               4 :                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     406               4 :                 efree(s_tmp);
     407                 :         } else {
     408               2 :                 TRACE_APPEND_STR("[internal function]: ");
     409                 :         }
     410               6 :         TRACE_APPEND_KEY("class");
     411               6 :         TRACE_APPEND_KEY("type");
     412               6 :         TRACE_APPEND_KEY("function");
     413               6 :         TRACE_APPEND_CHR('(');
     414               6 :         if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
     415               6 :                 int last_len = *len;
     416               6 :                 zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp), (apply_func_args_t)_build_trace_args, 2, str, len);
     417               6 :                 if (last_len != *len) {
     418               4 :                         *len -= 2; /* remove last ', ' */
     419                 :                 }
     420                 :         }
     421               6 :         TRACE_APPEND_STR(")\n");
     422               6 :         return ZEND_HASH_APPLY_KEEP;
     423                 : }
     424                 : /* }}} */
     425                 : 
     426                 : /* {{{ proto string Exception::getTraceAsString()
     427                 :    Obtain the backtrace for the exception as a string (instead of an array) */
     428                 : ZEND_METHOD(exception, getTraceAsString)
     429               2 : {
     430                 :         zval *trace;
     431               2 :         char *res = estrdup(""), **str = &res, *s_tmp;
     432               2 :         int res_len = 0, *len = &res_len, num = 0;
     433                 : 
     434               2 :         trace = zend_read_property(default_exception_ce, getThis(), "trace", sizeof("trace")-1, 1 TSRMLS_CC);
     435               2 :         zend_hash_apply_with_arguments(Z_ARRVAL_P(trace), (apply_func_args_t)_build_trace_string, 3, str, len, &num);
     436                 : 
     437               2 :         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
     438               2 :         sprintf(s_tmp, "#%d {main}", num);
     439               2 :         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     440               2 :         efree(s_tmp);
     441                 : 
     442               2 :         res[res_len] = '\0';    
     443               2 :         RETURN_STRINGL(res, res_len, 0); 
     444                 : }
     445                 : /* }}} */
     446                 : 
     447                 : int zend_spprintf(char **message, int max_len, char *format, ...) /* {{{ */
     448            5935 : {
     449                 :         va_list arg;
     450                 :         int len;
     451                 : 
     452            5935 :         va_start(arg, format);
     453            5935 :         len = zend_vspprintf(message, max_len, format, arg);
     454            5935 :         va_end(arg);
     455            5935 :         return len;
     456                 : }
     457                 : /* }}} */
     458                 : 
     459                 : /* {{{ proto string Exception::__toString()
     460                 :    Obtain the string representation of the Exception object */
     461                 : ZEND_METHOD(exception, __toString)
     462               0 : {
     463                 :         zval message, file, line, *trace;
     464                 :         char *str;
     465                 :         int len;
     466                 :         zend_fcall_info fci;
     467                 :         zval fname;
     468                 : 
     469               0 :         _default_exception_get_entry(getThis(), "message", sizeof("message")-1, &message TSRMLS_CC);
     470               0 :         _default_exception_get_entry(getThis(), "file", sizeof("file")-1, &file TSRMLS_CC);
     471               0 :         _default_exception_get_entry(getThis(), "line", sizeof("line")-1, &line TSRMLS_CC);
     472                 : 
     473               0 :         convert_to_string(&message);
     474               0 :         convert_to_string(&file);
     475               0 :         convert_to_long(&line);
     476                 : 
     477               0 :         ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 0);
     478                 : 
     479               0 :         fci.size = sizeof(fci);
     480               0 :         fci.function_table = &Z_OBJCE_P(getThis())->function_table;
     481               0 :         fci.function_name = &fname;
     482               0 :         fci.symbol_table = NULL;
     483               0 :         fci.object_pp = &getThis();
     484               0 :         fci.retval_ptr_ptr = &trace;
     485               0 :         fci.param_count = 0;
     486               0 :         fci.params = NULL;
     487               0 :         fci.no_separation = 1;
     488                 : 
     489               0 :         zend_call_function(&fci, NULL TSRMLS_CC);
     490                 : 
     491               0 :         if (Z_TYPE_P(trace) != IS_STRING) {
     492               0 :                 trace = NULL;
     493                 :         }
     494                 : 
     495               0 :         if (Z_STRLEN(message) > 0) {
     496               0 :                 len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s", 
     497                 :                                                         Z_OBJCE_P(getThis())->name, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line), 
     498                 :                                                         (trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
     499                 :         } else {
     500               0 :                 len = zend_spprintf(&str, 0, "exception '%s' in %s:%ld\nStack trace:\n%s", 
     501                 :                                                         Z_OBJCE_P(getThis())->name, Z_STRVAL(file), Z_LVAL(line), 
     502                 :                                                         (trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
     503                 :         }
     504                 : 
     505                 :         /* We store the result in the private property string so we can access
     506                 :          * the result in uncaught exception handlers without memleaks. */
     507               0 :         zend_update_property_string(default_exception_ce, getThis(), "string", sizeof("string")-1, str TSRMLS_CC);
     508                 : 
     509               0 :         if (trace) {
     510               0 :                 zval_ptr_dtor(&trace);
     511                 :         }
     512                 : 
     513               0 :         zval_dtor(&message);
     514               0 :         zval_dtor(&file);
     515               0 :         zval_dtor(&line);
     516                 : 
     517               0 :         RETURN_STRINGL(str, len, 0);
     518                 : }
     519                 : /* }}} */
     520                 : 
     521                 : /* {{{ internal structs */
     522                 : /* All functions that may be used in uncaught exception handlers must be final
     523                 :  * and must not throw exceptions. Otherwise we would need a facility to handle
     524                 :  * such exceptions in that handler.
     525                 :  * Also all getXY() methods are final because thy serve as read only access to
     526                 :  * their corresponding properties, no more, no less. If after all you need to
     527                 :  * override somthing then it is method __toString().
     528                 :  * And never try to change the state of exceptions and never implement anything
     529                 :  * that gives the user anything to accomplish this.
     530                 :  */
     531                 : static
     532                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_exception___construct, 0, 0, 0)
     533                 :         ZEND_ARG_INFO(0, message)
     534                 :         ZEND_ARG_INFO(0, code)
     535                 : ZEND_END_ARG_INFO();
     536                 : 
     537                 : static zend_function_entry default_exception_functions[] = {
     538                 :         ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
     539                 :         ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC)
     540                 :         ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     541                 :         ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     542                 :         ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     543                 :         ZEND_ME(exception, getLine, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     544                 :         ZEND_ME(exception, getTrace, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     545                 :         ZEND_ME(exception, getTraceAsString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     546                 :         ZEND_ME(exception, __toString, NULL, 0)
     547                 :         {NULL, NULL, NULL}
     548                 : };
     549                 : 
     550                 : static
     551                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_error_exception___construct, 0, 0, 0)
     552                 :         ZEND_ARG_INFO(0, message)
     553                 :         ZEND_ARG_INFO(0, code)
     554                 :         ZEND_ARG_INFO(0, severity)
     555                 :         ZEND_ARG_INFO(0, filename)
     556                 :         ZEND_ARG_INFO(0, lineno)
     557                 : ZEND_END_ARG_INFO();
     558                 : 
     559                 : static zend_function_entry error_exception_functions[] = {
     560                 :         ZEND_ME(error_exception, __construct, arginfo_error_exception___construct, ZEND_ACC_PUBLIC)
     561                 :         ZEND_ME(error_exception, getSeverity, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     562                 :         {NULL, NULL, NULL}
     563                 : };
     564                 : /* }}} */
     565                 : 
     566                 : void zend_register_default_exception(TSRMLS_D) /* {{{ */
     567             220 : {
     568                 :         zend_class_entry ce;
     569                 : 
     570             220 :         INIT_CLASS_ENTRY(ce, "Exception", default_exception_functions);
     571             220 :         default_exception_ce = zend_register_internal_class(&ce TSRMLS_CC);
     572             220 :         default_exception_ce->create_object = zend_default_exception_new;
     573             220 :         memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
     574             220 :         default_exception_handlers.clone_obj = NULL;
     575                 : 
     576             220 :         zend_declare_property_string(default_exception_ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
     577             220 :         zend_declare_property_string(default_exception_ce, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
     578             220 :         zend_declare_property_long(default_exception_ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED TSRMLS_CC);
     579             220 :         zend_declare_property_null(default_exception_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
     580             220 :         zend_declare_property_null(default_exception_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
     581             220 :         zend_declare_property_null(default_exception_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
     582                 : 
     583             220 :         INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions);
     584             220 :         error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce, NULL TSRMLS_CC);
     585             220 :         error_exception_ce->create_object = zend_error_exception_new;
     586             220 :         zend_declare_property_long(error_exception_ce, "severity", sizeof("severity")-1, E_ERROR, ZEND_ACC_PROTECTED TSRMLS_CC);
     587             220 : }
     588                 : /* }}} */
     589                 : 
     590                 : ZEND_API zend_class_entry *zend_exception_get_default(TSRMLS_D) /* {{{ */
     591             902 : {
     592             902 :         return default_exception_ce;
     593                 : }
     594                 : /* }}} */
     595                 : 
     596                 : ZEND_API zend_class_entry *zend_get_error_exception(TSRMLS_D) /* {{{ */
     597               0 : {
     598               0 :         return error_exception_ce;
     599                 : }
     600                 : /* }}} */
     601                 : 
     602                 : ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, char *message, long code TSRMLS_DC) /* {{{ */
     603              16 : {
     604                 :         zval *ex;
     605                 : 
     606              16 :         MAKE_STD_ZVAL(ex);
     607              16 :         if (exception_ce) {
     608              16 :                 if (!instanceof_function(exception_ce, default_exception_ce TSRMLS_CC)) {
     609               0 :                         zend_error(E_NOTICE, "Exceptions must be derived from the Exception base class");
     610               0 :                         exception_ce = default_exception_ce;
     611                 :                 }
     612                 :         } else {
     613               0 :                 exception_ce = default_exception_ce;
     614                 :         }
     615              16 :         object_init_ex(ex, exception_ce);
     616                 : 
     617                 : 
     618              16 :         if (message) {
     619              16 :                 zend_update_property_string(default_exception_ce, ex, "message", sizeof("message")-1, message TSRMLS_CC);
     620                 :         }
     621              16 :         if (code) {
     622              16 :                 zend_update_property_long(default_exception_ce, ex, "code", sizeof("code")-1, code TSRMLS_CC);
     623                 :         }
     624                 : 
     625              16 :         zend_throw_exception_internal(ex TSRMLS_CC);
     626              16 :         return ex;
     627                 : }
     628                 : /* }}} */
     629                 : 
     630                 : ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, char *format, ...) /* {{{ */
     631               0 : {
     632                 :         va_list arg;
     633                 :         char *message;
     634                 :         zval *zexception;
     635                 : 
     636               0 :         va_start(arg, format);
     637               0 :         zend_vspprintf(&message, 0, format, arg);
     638               0 :         va_end(arg);
     639               0 :         zexception = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
     640               0 :         efree(message);
     641               0 :         return zexception;
     642                 : }
     643                 : /* }}} */
     644                 : 
     645                 : ZEND_API zval * zend_throw_error_exception(zend_class_entry *exception_ce, char *message, long code, int severity TSRMLS_DC) /* {{{ */
     646               0 : {
     647               0 :         zval *ex = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
     648               0 :         zend_update_property_long(default_exception_ce, ex, "severity", sizeof("severity")-1, severity TSRMLS_CC);
     649               0 :         return ex;
     650                 : }
     651                 : /* }}} */
     652                 : 
     653                 : static void zend_error_va(int type, const char *file, uint lineno, const char *format, ...) /* {{{ */
     654               0 : {
     655                 :         va_list args;
     656                 : 
     657               0 :         va_start(args, format);
     658               0 :         zend_error_cb(type, file, lineno, format, args);
     659               0 :         va_end(args);
     660               0 : }
     661                 : /* }}} */
     662                 : 
     663                 : /* This function doesn't return as it calls E_ERROR */
     664                 : ZEND_API void zend_exception_error(zval *exception TSRMLS_DC) /* {{{ */
     665               0 : {
     666               0 :         zend_class_entry *ce_exception = Z_OBJCE_P(exception);
     667               0 :         if (instanceof_function(ce_exception, default_exception_ce TSRMLS_CC)) {
     668                 :                 zval *str, *file, *line;
     669                 : 
     670               0 :                 EG(exception) = NULL;
     671                 : 
     672               0 :                 zend_call_method_with_0_params(&exception, ce_exception, NULL, "__tostring", &str);
     673               0 :                 if (!EG(exception)) {
     674               0 :                         if (Z_TYPE_P(str) != IS_STRING) {
     675               0 :                                 zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name);
     676                 :                         } else {
     677               0 :                                 zend_update_property_string(default_exception_ce, exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name : Z_STRVAL_P(str) TSRMLS_CC);
     678                 :                         }
     679                 :                 }
     680               0 :                 zval_ptr_dtor(&str);
     681                 : 
     682               0 :                 if (EG(exception)) {
     683                 :                         /* do the best we can to inform about the inner exception */
     684               0 :                         if (instanceof_function(ce_exception, default_exception_ce TSRMLS_CC)) {
     685               0 :                                 file = zend_read_property(default_exception_ce, EG(exception), "file", sizeof("file")-1, 1 TSRMLS_CC);
     686               0 :                                 line = zend_read_property(default_exception_ce, EG(exception), "line", sizeof("line")-1, 1 TSRMLS_CC);
     687                 :                         } else {
     688               0 :                                 file = NULL;
     689               0 :                                 line = NULL;
     690                 :                         }
     691               0 :                         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);
     692                 :                 }
     693                 : 
     694               0 :                 str = zend_read_property(default_exception_ce, exception, "string", sizeof("string")-1, 1 TSRMLS_CC);
     695               0 :                 file = zend_read_property(default_exception_ce, exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
     696               0 :                 line = zend_read_property(default_exception_ce, exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
     697                 : 
     698               0 :                 zend_error_va(E_ERROR, Z_STRVAL_P(file), Z_LVAL_P(line), "Uncaught %s\n  thrown", Z_STRVAL_P(str));
     699                 :         } else {
     700               0 :                 zend_error(E_ERROR, "Uncaught exception '%s'", ce_exception->name);
     701                 :         }
     702               0 : }
     703                 : /* }}} */
     704                 : 
     705                 : ZEND_API void zend_throw_exception_object(zval *exception TSRMLS_DC) /* {{{ */
     706              12 : {
     707                 :         zend_class_entry *exception_ce;
     708                 : 
     709              12 :         if (exception == NULL || Z_TYPE_P(exception) != IS_OBJECT) {
     710               0 :                 zend_error(E_ERROR, "Need to supply an object when throwing an exception");
     711                 :         }
     712                 : 
     713              12 :         exception_ce = Z_OBJCE_P(exception);
     714                 : 
     715              12 :         if (!exception_ce || !instanceof_function(exception_ce, default_exception_ce TSRMLS_CC)) {
     716               0 :                 zend_error(E_ERROR, "Exceptions must be valid objects derived from the Exception base class");
     717                 :         }
     718              12 :         zend_throw_exception_internal(exception TSRMLS_CC);
     719              12 : }
     720                 : /* }}} */
     721                 : 
     722                 : /*
     723                 :  * Local variables:
     724                 :  * tab-width: 4
     725                 :  * c-basic-offset: 4
     726                 :  * indent-tabs-mode: t
     727                 :  * End:
     728                 :  */

Generated by: LTP GCOV extension version 1.5