PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_5_2/Zend - zend_exceptions.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 299
Code covered: 86.0 % Executed lines: 257
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | Zend Engine                                                          |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1998-2009 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 280363 2009-05-11 15:13:35Z felipe $ */
      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            1354 : {
      37            1354 :         if (exception != NULL) {
      38             608 :                 if (EG(exception)) {
      39                 :                         /* FIXME:  bail out? */
      40               0 :                         return;
      41                 :                 }
      42             608 :                 EG(exception) = exception;
      43                 :         }
      44            1354 :         if (!EG(current_execute_data)) {
      45               1 :                 zend_error(E_ERROR, "Exception thrown without a stack frame");
      46                 :         }
      47                 : 
      48            1353 :         if (zend_throw_exception_hook) {
      49               0 :                 zend_throw_exception_hook(exception TSRMLS_CC);
      50                 :         }
      51                 : 
      52            1353 :         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             540 :                 return;
      56                 :         }
      57             813 :         EG(opline_before_exception) = EG(current_execute_data)->opline;
      58             813 :         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              97 : {
      64              97 :         if (!EG(exception)) {
      65              91 :                 return;
      66                 :         }
      67               6 :         zval_ptr_dtor(&EG(exception));
      68               6 :         EG(exception) = NULL;
      69               6 :         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            1022 : {
      78                 :         zval tmp, obj;
      79                 :         zend_object *object;
      80                 :         zval *trace;
      81                 : 
      82            1022 :         Z_OBJVAL(obj) = zend_objects_new(&object, class_type TSRMLS_CC);
      83            1022 :         Z_OBJ_HT(obj) = &default_exception_handlers;
      84                 : 
      85            1022 :         ALLOC_HASHTABLE(object->properties);
      86            1022 :         zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
      87            1022 :         zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
      88                 : 
      89            1022 :         ALLOC_ZVAL(trace);
      90            1022 :         trace->is_ref = 0;
      91            1022 :         trace->refcount = 0;
      92            1022 :         zend_fetch_debug_backtrace(trace, skip_top_traces, 0 TSRMLS_CC);
      93                 : 
      94            1022 :         zend_update_property_string(default_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename(TSRMLS_C) TSRMLS_CC);
      95            1022 :         zend_update_property_long(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC);
      96            1022 :         zend_update_property(default_exception_ce, &obj, "trace", sizeof("trace")-1, trace TSRMLS_CC);
      97                 : 
      98            1022 :         return Z_OBJVAL(obj);
      99                 : }
     100                 : /* }}} */
     101                 : 
     102                 : static zend_object_value zend_default_exception_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
     103            1021 : {
     104            1021 :         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               1 : {
     110               1 :         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             162 : {
     127             162 :         char  *message = NULL;
     128             162 :         long   code = 0;
     129                 :         zval  *object;
     130             162 :         int    argc = ZEND_NUM_ARGS(), message_len;
     131                 : 
     132             162 :         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             162 :         object = getThis();
     137                 : 
     138             162 :         if (message) {
     139             104 :                 zend_update_property_string(default_exception_ce, object, "message", sizeof("message")-1, message TSRMLS_CC);
     140                 :         }
     141                 : 
     142             162 :         if (code) {
     143               8 :                 zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC);
     144                 :         }
     145             162 : }
     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               1 : {
     152               1 :         char  *message = NULL, *filename = NULL;
     153               1 :         long   code = 0, severity = E_ERROR, lineno;
     154                 :         zval  *object;
     155               1 :         int    argc = ZEND_NUM_ARGS(), message_len, filename_len;
     156                 : 
     157               1 :         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               1 :         object = getThis();
     162                 : 
     163               1 :         if (message) {
     164               1 :                 zend_update_property_string(default_exception_ce, object, "message", sizeof("message")-1, message TSRMLS_CC);
     165                 :         }
     166                 : 
     167               1 :         if (code) {
     168               0 :                 zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC);
     169                 :         }
     170                 : 
     171               1 :         zend_update_property_long(default_exception_ce, object, "severity", sizeof("severity")-1, severity TSRMLS_CC);
     172                 : 
     173               1 :         if (argc >= 4) {
     174               1 :             zend_update_property_string(default_exception_ce, object, "file", sizeof("file")-1, filename TSRMLS_CC);
     175               1 :         if (argc < 5) {
     176               0 :             lineno = 0; /* invalidate lineno */
     177                 :         }
     178               1 :         zend_update_property_long(default_exception_ce, object, "line", sizeof("line")-1, lineno TSRMLS_CC);
     179                 :         }
     180               1 : }
     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             588 : {
     190                 :         zval *value;
     191                 : 
     192             588 :         value = zend_read_property(default_exception_ce, object, name, name_len, 0 TSRMLS_CC);
     193                 : 
     194             588 :         *return_value = *value;
     195             588 :         zval_copy_ctor(return_value);
     196             588 :         INIT_PZVAL(return_value);
     197             588 : }
     198                 : /* }}} */
     199                 : 
     200                 : /* {{{ proto string Exception::getFile()
     201                 :    Get the file in which the exception occurred */
     202                 : ZEND_METHOD(exception, getFile)
     203               4 : {
     204               4 :         DEFAULT_0_PARAMS;
     205                 : 
     206               3 :         _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              10 : {
     214              10 :         DEFAULT_0_PARAMS;
     215                 : 
     216               9 :         _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             459 : {
     224             459 :         DEFAULT_0_PARAMS;
     225                 : 
     226             458 :         _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              10 : {
     234              10 :         DEFAULT_0_PARAMS;
     235                 : 
     236               9 :         _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               2 : {
     244               2 :         DEFAULT_0_PARAMS;
     245                 : 
     246               1 :         _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              44 : {
     285                 :         char **str;
     286                 :         int *len;
     287                 : 
     288              44 :         str = va_arg(args, char**);
     289              44 :         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              44 :         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              27 :                         TRACE_APPEND_CHR('\'');
     304              27 :                         if (Z_STRLEN_PP(arg) > 15) {
     305               4 :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
     306               4 :                                 TRACE_APPEND_STR("...', ");
     307               4 :                                 l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
     308                 :                         } else {
     309              23 :                                 l_added = Z_STRLEN_PP(arg);
     310              23 :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
     311              23 :                                 TRACE_APPEND_STR("', ");
     312              23 :                                 l_added += 3 + 1;
     313                 :                         }
     314             309 :                         while (--l_added) {
     315             255 :                                 if ((*str)[*len - l_added] < 32) {
     316               0 :                                         (*str)[*len - l_added] = '?';
     317                 :                                 }
     318                 :                         }
     319              27 :                         break;
     320                 :                 }
     321                 :                 case IS_BOOL:
     322               1 :                         if (Z_LVAL_PP(arg)) {
     323               1 :                                 TRACE_APPEND_STR("true, ");
     324                 :                         } else {
     325               0 :                                 TRACE_APPEND_STR("false, ");
     326                 :                         }
     327               1 :                         break;
     328                 :                 case IS_RESOURCE:
     329               1 :                         TRACE_APPEND_STR("Resource id #");
     330                 :                         /* break; */
     331                 :                 case IS_LONG: {
     332               9 :                         long lval = Z_LVAL_PP(arg);
     333                 :                         char s_tmp[MAX_LENGTH_OF_LONG + 1];
     334               9 :                         int l_tmp = zend_sprintf(s_tmp, "%ld", lval);  /* SAFE */
     335               9 :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
     336               9 :                         TRACE_APPEND_STR(", ");
     337               9 :                         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               3 :                         TRACE_APPEND_STR("Array, ");
     355               3 :                         break;
     356                 :                 case IS_OBJECT: {
     357                 :                         char *class_name;
     358                 :                         zend_uint class_name_len;
     359                 :                         int dup;
     360                 :                         TSRMLS_FETCH();
     361                 : 
     362               4 :                         TRACE_APPEND_STR("Object(");
     363                 : 
     364               4 :                         dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
     365                 : 
     366               4 :                         TRACE_APPEND_STRL(class_name, class_name_len);
     367               4 :                         if(!dup) {
     368               4 :                                 efree(class_name);
     369                 :                         }
     370                 : 
     371               4 :                         TRACE_APPEND_STR("), ");
     372                 :                         break;
     373                 :                 }
     374                 :                 default:
     375                 :                         break;
     376                 :         }
     377              44 :         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              46 : {
     383                 :         char *s_tmp, **str;
     384                 :         int *len, *num;
     385                 :         long line;
     386              46 :         HashTable *ht = Z_ARRVAL_PP(frame);
     387                 :         zval **file, **tmp;
     388                 : 
     389              46 :         str = va_arg(args, char**);
     390              46 :         len = va_arg(args, int*);
     391              46 :         num = va_arg(args, int*);
     392                 : 
     393              46 :         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
     394              46 :         sprintf(s_tmp, "#%d ", (*num)++);
     395              46 :         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     396              46 :         efree(s_tmp);
     397              46 :         if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
     398              39 :                 if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
     399              39 :                         line = Z_LVAL_PP(tmp);
     400                 :                 } else {
     401               0 :                         line = 0;
     402                 :                 }
     403              39 :                 s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
     404              39 :                 sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
     405              39 :                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     406              39 :                 efree(s_tmp);
     407                 :         } else {
     408               7 :                 TRACE_APPEND_STR("[internal function]: ");
     409                 :         }
     410              46 :         TRACE_APPEND_KEY("class");
     411              46 :         TRACE_APPEND_KEY("type");
     412              46 :         TRACE_APPEND_KEY("function");
     413              46 :         TRACE_APPEND_CHR('(');
     414              46 :         if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
     415              45 :                 int last_len = *len;
     416              45 :                 zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp), (apply_func_args_t)_build_trace_args, 2, str, len);
     417              45 :                 if (last_len != *len) {
     418              28 :                         *len -= 2; /* remove last ', ' */
     419                 :                 }
     420                 :         }
     421              46 :         TRACE_APPEND_STR(")\n");
     422              46 :         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              37 : {
     430                 :         zval *trace;
     431                 :         char *res, **str, *s_tmp;
     432              37 :         int res_len = 0, *len = &res_len, num = 0;
     433                 : 
     434              37 :         DEFAULT_0_PARAMS;
     435                 :         
     436              36 :         res = estrdup("");
     437              36 :         str = &res;
     438                 : 
     439              36 :         trace = zend_read_property(default_exception_ce, getThis(), "trace", sizeof("trace")-1, 1 TSRMLS_CC);
     440              36 :         zend_hash_apply_with_arguments(Z_ARRVAL_P(trace), (apply_func_args_t)_build_trace_string, 3, str, len, &num);
     441                 : 
     442              36 :         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
     443              36 :         sprintf(s_tmp, "#%d {main}", num);
     444              36 :         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     445              36 :         efree(s_tmp);
     446                 : 
     447              36 :         res[res_len] = '\0';    
     448              36 :         RETURN_STRINGL(res, res_len, 0); 
     449                 : }
     450                 : /* }}} */
     451                 : 
     452                 : int zend_spprintf(char **message, int max_len, char *format, ...) /* {{{ */
     453         2037151 : {
     454                 :         va_list arg;
     455                 :         int len;
     456                 : 
     457         2037151 :         va_start(arg, format);
     458         2037151 :         len = zend_vspprintf(message, max_len, format, arg);
     459         2037151 :         va_end(arg);
     460         2037151 :         return len;
     461                 : }
     462                 : /* }}} */
     463                 : 
     464                 : /* {{{ proto string Exception::__toString()
     465                 :    Obtain the string representation of the Exception object */
     466                 : ZEND_METHOD(exception, __toString)
     467              37 : {
     468                 :         zval message, file, line, *trace;
     469                 :         char *str;
     470                 :         int len;
     471                 :         zend_fcall_info fci;
     472                 :         zval fname;
     473                 :         
     474              37 :         DEFAULT_0_PARAMS;
     475                 : 
     476              36 :         _default_exception_get_entry(getThis(), "message", sizeof("message")-1, &message TSRMLS_CC);
     477              36 :         _default_exception_get_entry(getThis(), "file", sizeof("file")-1, &file TSRMLS_CC);
     478              36 :         _default_exception_get_entry(getThis(), "line", sizeof("line")-1, &line TSRMLS_CC);
     479                 : 
     480              36 :         convert_to_string(&message);
     481              35 :         convert_to_string(&file);
     482              35 :         convert_to_long(&line);
     483                 : 
     484              35 :         ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 0);
     485                 : 
     486              35 :         fci.size = sizeof(fci);
     487              35 :         fci.function_table = &Z_OBJCE_P(getThis())->function_table;
     488              35 :         fci.function_name = &fname;
     489              35 :         fci.symbol_table = NULL;
     490              35 :         fci.object_pp = &getThis();
     491              35 :         fci.retval_ptr_ptr = &trace;
     492              35 :         fci.param_count = 0;
     493              35 :         fci.params = NULL;
     494              35 :         fci.no_separation = 1;
     495                 : 
     496              35 :         zend_call_function(&fci, NULL TSRMLS_CC);
     497                 : 
     498              35 :         if (Z_TYPE_P(trace) != IS_STRING) {
     499               0 :                 trace = NULL;
     500                 :         }
     501                 : 
     502              35 :         if (Z_STRLEN(message) > 0) {
     503              28 :                 len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s", 
     504                 :                                                         Z_OBJCE_P(getThis())->name, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line), 
     505                 :                                                         (trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
     506                 :         } else {
     507               7 :                 len = zend_spprintf(&str, 0, "exception '%s' in %s:%ld\nStack trace:\n%s", 
     508                 :                                                         Z_OBJCE_P(getThis())->name, Z_STRVAL(file), Z_LVAL(line), 
     509                 :                                                         (trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
     510                 :         }
     511                 : 
     512                 :         /* We store the result in the private property string so we can access
     513                 :          * the result in uncaught exception handlers without memleaks. */
     514              35 :         zend_update_property_string(default_exception_ce, getThis(), "string", sizeof("string")-1, str TSRMLS_CC);
     515                 : 
     516              35 :         if (trace) {
     517              35 :                 zval_ptr_dtor(&trace);
     518                 :         }
     519                 : 
     520              35 :         zval_dtor(&message);
     521              35 :         zval_dtor(&file);
     522              35 :         zval_dtor(&line);
     523                 : 
     524              35 :         RETURN_STRINGL(str, len, 0);
     525                 : }
     526                 : /* }}} */
     527                 : 
     528                 : /* {{{ internal structs */
     529                 : /* All functions that may be used in uncaught exception handlers must be final
     530                 :  * and must not throw exceptions. Otherwise we would need a facility to handle
     531                 :  * such exceptions in that handler.
     532                 :  * Also all getXY() methods are final because thy serve as read only access to
     533                 :  * their corresponding properties, no more, no less. If after all you need to
     534                 :  * override somthing then it is method __toString().
     535                 :  * And never try to change the state of exceptions and never implement anything
     536                 :  * that gives the user anything to accomplish this.
     537                 :  */
     538                 : static
     539                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_exception___construct, 0, 0, 0)
     540                 :         ZEND_ARG_INFO(0, message)
     541                 :         ZEND_ARG_INFO(0, code)
     542                 : ZEND_END_ARG_INFO()
     543                 : 
     544                 : static zend_function_entry default_exception_functions[] = {
     545                 :         ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
     546                 :         ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC)
     547                 :         ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     548                 :         ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     549                 :         ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     550                 :         ZEND_ME(exception, getLine, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     551                 :         ZEND_ME(exception, getTrace, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     552                 :         ZEND_ME(exception, getTraceAsString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     553                 :         ZEND_ME(exception, __toString, NULL, 0)
     554                 :         {NULL, NULL, NULL}
     555                 : };
     556                 : 
     557                 : static
     558                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_error_exception___construct, 0, 0, 0)
     559                 :         ZEND_ARG_INFO(0, message)
     560                 :         ZEND_ARG_INFO(0, code)
     561                 :         ZEND_ARG_INFO(0, severity)
     562                 :         ZEND_ARG_INFO(0, filename)
     563                 :         ZEND_ARG_INFO(0, lineno)
     564                 : ZEND_END_ARG_INFO()
     565                 : 
     566                 : static zend_function_entry error_exception_functions[] = {
     567                 :         ZEND_ME(error_exception, __construct, arginfo_error_exception___construct, ZEND_ACC_PUBLIC)
     568                 :         ZEND_ME(error_exception, getSeverity, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     569                 :         {NULL, NULL, NULL}
     570                 : };
     571                 : /* }}} */
     572                 : 
     573                 : void zend_register_default_exception(TSRMLS_D) /* {{{ */
     574           13565 : {
     575                 :         zend_class_entry ce;
     576                 : 
     577           13565 :         INIT_CLASS_ENTRY(ce, "Exception", default_exception_functions);
     578           13565 :         default_exception_ce = zend_register_internal_class(&ce TSRMLS_CC);
     579           13565 :         default_exception_ce->create_object = zend_default_exception_new;
     580           13565 :         memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
     581           13565 :         default_exception_handlers.clone_obj = NULL;
     582                 : 
     583           13565 :         zend_declare_property_string(default_exception_ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
     584           13565 :         zend_declare_property_string(default_exception_ce, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
     585           13565 :         zend_declare_property_long(default_exception_ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED TSRMLS_CC);
     586           13565 :         zend_declare_property_null(default_exception_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
     587           13565 :         zend_declare_property_null(default_exception_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
     588           13565 :         zend_declare_property_null(default_exception_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
     589                 : 
     590           13565 :         INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions);
     591           13565 :         error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce, NULL TSRMLS_CC);
     592           13565 :         error_exception_ce->create_object = zend_error_exception_new;
     593           13565 :         zend_declare_property_long(error_exception_ce, "severity", sizeof("severity")-1, E_ERROR, ZEND_ACC_PROTECTED TSRMLS_CC);
     594           13565 : }
     595                 : /* }}} */
     596                 : 
     597                 : ZEND_API zend_class_entry *zend_exception_get_default(TSRMLS_D) /* {{{ */
     598           68428 : {
     599           68428 :         return default_exception_ce;
     600                 : }
     601                 : /* }}} */
     602                 : 
     603                 : ZEND_API zend_class_entry *zend_get_error_exception(TSRMLS_D) /* {{{ */
     604               0 : {
     605               0 :         return error_exception_ce;
     606                 : }
     607                 : /* }}} */
     608                 : 
     609                 : ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, char *message, long code TSRMLS_DC) /* {{{ */
     610             418 : {
     611                 :         zval *ex;
     612                 : 
     613             418 :         MAKE_STD_ZVAL(ex);
     614             418 :         if (exception_ce) {
     615             314 :                 if (!instanceof_function(exception_ce, default_exception_ce TSRMLS_CC)) {
     616               0 :                         zend_error(E_NOTICE, "Exceptions must be derived from the Exception base class");
     617               0 :                         exception_ce = default_exception_ce;
     618                 :                 }
     619                 :         } else {
     620             104 :                 exception_ce = default_exception_ce;
     621                 :         }
     622             418 :         object_init_ex(ex, exception_ce);
     623                 : 
     624                 : 
     625             418 :         if (message) {
     626             418 :                 zend_update_property_string(default_exception_ce, ex, "message", sizeof("message")-1, message TSRMLS_CC);
     627                 :         }
     628             418 :         if (code) {
     629              55 :                 zend_update_property_long(default_exception_ce, ex, "code", sizeof("code")-1, code TSRMLS_CC);
     630                 :         }
     631                 : 
     632             418 :         zend_throw_exception_internal(ex TSRMLS_CC);
     633             418 :         return ex;
     634                 : }
     635                 : /* }}} */
     636                 : 
     637                 : ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, char *format, ...) /* {{{ */
     638             234 : {
     639                 :         va_list arg;
     640                 :         char *message;
     641                 :         zval *zexception;
     642                 : 
     643             234 :         va_start(arg, format);
     644             234 :         zend_vspprintf(&message, 0, format, arg);
     645             234 :         va_end(arg);
     646             234 :         zexception = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
     647             234 :         efree(message);
     648             234 :         return zexception;
     649                 : }
     650                 : /* }}} */
     651                 : 
     652                 : ZEND_API zval * zend_throw_error_exception(zend_class_entry *exception_ce, char *message, long code, int severity TSRMLS_DC) /* {{{ */
     653             114 : {
     654             114 :         zval *ex = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
     655             114 :         zend_update_property_long(default_exception_ce, ex, "severity", sizeof("severity")-1, severity TSRMLS_CC);
     656             114 :         return ex;
     657                 : }
     658                 : /* }}} */
     659                 : 
     660                 : static void zend_error_va(int type, const char *file, uint lineno, const char *format, ...) /* {{{ */
     661              28 : {
     662                 :         va_list args;
     663                 : 
     664              28 :         va_start(args, format);
     665              28 :         zend_error_cb(type, file, lineno, format, args);
     666               0 :         va_end(args);
     667               0 : }
     668                 : /* }}} */
     669                 : 
     670                 : /* This function doesn't return as it calls E_ERROR */
     671                 : ZEND_API void zend_exception_error(zval *exception TSRMLS_DC) /* {{{ */
     672              29 : {
     673              29 :         zend_class_entry *ce_exception = Z_OBJCE_P(exception);
     674              29 :         if (instanceof_function(ce_exception, default_exception_ce TSRMLS_CC)) {
     675                 :                 zval *str, *file, *line;
     676                 : 
     677              29 :                 EG(exception) = NULL;
     678                 : 
     679              29 :                 zend_call_method_with_0_params(&exception, ce_exception, NULL, "__tostring", &str);
     680              28 :                 if (!EG(exception)) {
     681              28 :                         if (Z_TYPE_P(str) != IS_STRING) {
     682               0 :                                 zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name);
     683                 :                         } else {
     684              28 :                                 zend_update_property_string(default_exception_ce, exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name : Z_STRVAL_P(str) TSRMLS_CC);
     685                 :                         }
     686                 :                 }
     687              28 :                 zval_ptr_dtor(&str);
     688                 : 
     689              28 :                 if (EG(exception)) {
     690                 :                         /* do the best we can to inform about the inner exception */
     691               0 :                         if (instanceof_function(ce_exception, default_exception_ce TSRMLS_CC)) {
     692               0 :                                 file = zend_read_property(default_exception_ce, EG(exception), "file", sizeof("file")-1, 1 TSRMLS_CC);
     693               0 :                                 line = zend_read_property(default_exception_ce, EG(exception), "line", sizeof("line")-1, 1 TSRMLS_CC);
     694                 :                         } else {
     695               0 :                                 file = NULL;
     696               0 :                                 line = NULL;
     697                 :                         }
     698               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);
     699                 :                 }
     700                 : 
     701              28 :                 str = zend_read_property(default_exception_ce, exception, "string", sizeof("string")-1, 1 TSRMLS_CC);
     702              28 :                 file = zend_read_property(default_exception_ce, exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
     703              28 :                 line = zend_read_property(default_exception_ce, exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
     704                 : 
     705              28 :                 zend_error_va(E_ERROR, Z_STRVAL_P(file), Z_LVAL_P(line), "Uncaught %s\n  thrown", Z_STRVAL_P(str));
     706                 :         } else {
     707               0 :                 zend_error(E_ERROR, "Uncaught exception '%s'", ce_exception->name);
     708                 :         }
     709               0 : }
     710                 : /* }}} */
     711                 : 
     712                 : ZEND_API void zend_throw_exception_object(zval *exception TSRMLS_DC) /* {{{ */
     713             190 : {
     714                 :         zend_class_entry *exception_ce;
     715                 : 
     716             190 :         if (exception == NULL || Z_TYPE_P(exception) != IS_OBJECT) {
     717               0 :                 zend_error(E_ERROR, "Need to supply an object when throwing an exception");
     718                 :         }
     719                 : 
     720             190 :         exception_ce = Z_OBJCE_P(exception);
     721                 : 
     722             190 :         if (!exception_ce || !instanceof_function(exception_ce, default_exception_ce TSRMLS_CC)) {
     723               0 :                 zend_error(E_ERROR, "Exceptions must be valid objects derived from the Exception base class");
     724                 :         }
     725             190 :         zend_throw_exception_internal(exception TSRMLS_CC);
     726             190 : }
     727                 : /* }}} */
     728                 : 
     729                 : /*
     730                 :  * Local variables:
     731                 :  * tab-width: 4
     732                 :  * c-basic-offset: 4
     733                 :  * indent-tabs-mode: t
     734                 :  * End:
     735                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:04 +0000 (5 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.