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 - mysqlnd - mysqlnd_debug.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 472
Code covered: 34.7 % Executed lines: 164
Legend: not executed executed

       1                 : /*
       2                 :   +----------------------------------------------------------------------+
       3                 :   | PHP Version 6                                                        |
       4                 :   +----------------------------------------------------------------------+
       5                 :   | Copyright (c) 2006-2009 The PHP Group                                |
       6                 :   +----------------------------------------------------------------------+
       7                 :   | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt                                  |
      11                 :   | If you did not receive a copy of the PHP license and are unable to   |
      12                 :   | obtain it through the world-wide-web, please send a note to          |
      13                 :   | license@php.net so we can mail you a copy immediately.               |
      14                 :   +----------------------------------------------------------------------+
      15                 :   | Authors: Georg Richter <georg@mysql.com>                             |
      16                 :   |          Andrey Hristov <andrey@mysql.com>                           |
      17                 :   |          Ulf Wendel <uwendel@mysql.com>                              |
      18                 :   +----------------------------------------------------------------------+
      19                 : */
      20                 : 
      21                 : /* $Id: mysqlnd_debug.c 287834 2009-08-28 09:30:16Z andrey $ */
      22                 : 
      23                 : #include "php.h"
      24                 : #include "mysqlnd.h"
      25                 : #include "mysqlnd_priv.h"
      26                 : #include "mysqlnd_debug.h"
      27                 : #include "mysqlnd_wireprotocol.h"
      28                 : #include "mysqlnd_palloc.h"
      29                 : #include "mysqlnd_statistics.h"
      30                 : #include "zend_builtin_functions.h"
      31                 : 
      32                 : 
      33                 : static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace";
      34                 : 
      35                 : #ifdef ZTS 
      36                 : #define MYSQLND_ZTS(self) TSRMLS_D = (self)->TSRMLS_C
      37                 : #else
      38                 : #define MYSQLND_ZTS(self)
      39                 : #endif
      40                 : 
      41                 : #define MYSQLND_DEBUG_DUMP_TIME                         1
      42                 : #define MYSQLND_DEBUG_DUMP_TRACE                        2
      43                 : #define MYSQLND_DEBUG_DUMP_PID                          4
      44                 : #define MYSQLND_DEBUG_DUMP_LINE                         8
      45                 : #define MYSQLND_DEBUG_DUMP_FILE                         16
      46                 : #define MYSQLND_DEBUG_DUMP_LEVEL                        32
      47                 : #define MYSQLND_DEBUG_APPEND                            64
      48                 : #define MYSQLND_DEBUG_FLUSH                                     128
      49                 : #define MYSQLND_DEBUG_TRACE_MEMORY_CALLS        256
      50                 : 
      51                 : static char * mysqlnd_emalloc_name      = "_mysqlnd_emalloc";
      52                 : static char * mysqlnd_pemalloc_name     = "_mysqlnd_pemalloc";
      53                 : static char * mysqlnd_ecalloc_name      = "_mysqlnd_ecalloc";
      54                 : static char * mysqlnd_pecalloc_name     = "_mysqlnd_pecalloc";
      55                 : static char * mysqlnd_erealloc_name     = "_mysqlnd_erealloc";
      56                 : static char * mysqlnd_perealloc_name= "_mysqlnd_perealloc";
      57                 : static char * mysqlnd_efree_name        = "_mysqlnd_efree";
      58                 : static char * mysqlnd_pefree_name       = "_mysqlnd_pefree";
      59                 : static char * mysqlnd_malloc_name       = "_mysqlnd_malloc";
      60                 : static char * mysqlnd_calloc_name       = "_mysqlnd_calloc";
      61                 : static char * mysqlnd_realloc_name      = "_mysqlnd_realloc";
      62                 : static char * mysqlnd_free_name         = "_mysqlnd_free";
      63                 : 
      64                 : /* {{{ mysqlnd_debug::open */
      65                 : static enum_func_status
      66                 : MYSQLND_METHOD(mysqlnd_debug, open)(MYSQLND_DEBUG * self, zend_bool reopen)
      67               0 : {
      68                 :         MYSQLND_ZTS(self);
      69                 : 
      70               0 :         if (!self->file_name) {
      71               0 :                 return FAIL;
      72                 :         }
      73                 : 
      74               0 :         self->stream = php_stream_open_wrapper(self->file_name,
      75                 :                                                                                    reopen == TRUE || self->flags & MYSQLND_DEBUG_APPEND? "ab":"wb",
      76                 :                                                                                    REPORT_ERRORS, NULL);
      77               0 :         return self->stream? PASS:FAIL;
      78                 : }
      79                 : /* }}} */
      80                 : 
      81                 : 
      82                 : /* {{{ mysqlnd_debug::log */
      83                 : static enum_func_status
      84                 : MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * self,
      85                 :                                                                    unsigned int line, const char * const file,
      86                 :                                                                    unsigned int level, const char * type, const char * message)
      87               0 : {
      88                 :         char pipe_buffer[512];
      89                 :         enum_func_status ret;
      90                 :         int i;
      91                 :         char * message_line;
      92                 :         unsigned int message_line_len;
      93               0 :         unsigned int flags = self->flags;
      94                 :         char pid_buffer[10], time_buffer[30], file_buffer[200],
      95                 :                  line_buffer[6], level_buffer[7];
      96                 :         MYSQLND_ZTS(self);
      97                 : 
      98                 : #ifdef MYSQLND_THREADED
      99                 :         if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
     100                 :                 return PASS; /* don't trace background threads */
     101                 :         }
     102                 : #endif
     103                 : 
     104               0 :         if (!self->stream) {
     105               0 :                 if (FAIL == self->m->open(self, FALSE)) {
     106               0 :                         return FAIL;
     107                 :                 }
     108                 :         }
     109                 : 
     110               0 :         if (level == -1) {
     111               0 :                 level = zend_stack_count(&self->call_stack);
     112                 :         }
     113               0 :         i = MIN(level, sizeof(pipe_buffer) / 2  - 1);
     114               0 :         pipe_buffer[i*2] = '\0';
     115               0 :         for (;i > 0;i--) {
     116               0 :                 pipe_buffer[i*2 - 1] = ' ';
     117               0 :                 pipe_buffer[i*2 - 2] = '|';
     118                 :         }
     119                 : 
     120                 : 
     121               0 :         if (flags & MYSQLND_DEBUG_DUMP_PID) {
     122               0 :                 snprintf(pid_buffer, sizeof(pid_buffer) - 1, "%5u: ", self->pid);
     123               0 :                 pid_buffer[sizeof(pid_buffer) - 1 ] = '\0';
     124                 :         }
     125               0 :         if (flags & MYSQLND_DEBUG_DUMP_TIME) {
     126                 :                 /* The following from FF's DBUG library, which is in the public domain */
     127                 : #if defined(PHP_WIN32)
     128                 :                 /* FIXME This doesn't give microseconds as in Unix case, and the resolution is
     129                 :                 in system ticks, 10 ms intervals. See my_getsystime.c for high res */
     130                 :                 SYSTEMTIME loc_t;
     131                 :                 GetLocalTime(&loc_t);
     132                 :                 snprintf(time_buffer, sizeof(time_buffer) - 1,
     133                 :                                  /* "%04d-%02d-%02d " */
     134                 :                                  "%02d:%02d:%02d.%06d ",
     135                 :                                  /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/
     136                 :                                  loc_t.wHour, loc_t.wMinute, loc_t.wSecond, loc_t.wMilliseconds);
     137                 :                 time_buffer[sizeof(time_buffer) - 1 ] = '\0';
     138                 : #else
     139                 :                 struct timeval tv;
     140                 :                 struct tm *tm_p;
     141               0 :                 if (gettimeofday(&tv, NULL) != -1) {
     142               0 :                         if ((tm_p= localtime((const time_t *)&tv.tv_sec))) {
     143               0 :                                 snprintf(time_buffer, sizeof(time_buffer) - 1,
     144                 :                                                  /* "%04d-%02d-%02d " */
     145                 :                                                  "%02d:%02d:%02d.%06d ",
     146                 :                                                  /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/
     147                 :                                                  tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec,
     148                 :                                                  (int) (tv.tv_usec));
     149               0 :                                 time_buffer[sizeof(time_buffer) - 1 ] = '\0';
     150                 :                         }
     151                 :                 }
     152                 : #endif
     153                 :         }
     154               0 :         if (flags & MYSQLND_DEBUG_DUMP_FILE) {
     155               0 :                 snprintf(file_buffer, sizeof(file_buffer) - 1, "%14s: ", file);
     156               0 :                 file_buffer[sizeof(file_buffer) - 1 ] = '\0';
     157                 :         }
     158               0 :         if (flags & MYSQLND_DEBUG_DUMP_LINE) {
     159               0 :                 snprintf(line_buffer, sizeof(line_buffer) - 1, "%5u: ", line);
     160               0 :                 line_buffer[sizeof(line_buffer) - 1 ] = '\0';
     161                 :         }
     162               0 :         if (flags & MYSQLND_DEBUG_DUMP_LEVEL) {
     163               0 :                 snprintf(level_buffer, sizeof(level_buffer) - 1, "%4u: ", level);
     164               0 :                 level_buffer[sizeof(level_buffer) - 1 ] = '\0';
     165                 :         }
     166                 : 
     167               0 :         message_line_len = spprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
     168                 :                                                                 flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
     169                 :                                                                 flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
     170                 :                                                                 flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",
     171                 :                                                                 flags & MYSQLND_DEBUG_DUMP_LINE? line_buffer:"",
     172                 :                                                                 flags & MYSQLND_DEBUG_DUMP_LEVEL? level_buffer:"",
     173                 :                                                                 pipe_buffer, type? type:"", message);
     174                 : 
     175               0 :         ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
     176               0 :         efree(message_line);
     177               0 :         if (flags & MYSQLND_DEBUG_FLUSH) {
     178               0 :                 self->m->close(self);
     179               0 :                 self->m->open(self, TRUE);        
     180                 :         }
     181               0 :         return ret;
     182                 : }
     183                 : /* }}} */
     184                 : 
     185                 : 
     186                 : /* {{{ mysqlnd_debug::log_va */
     187                 : static enum_func_status
     188                 : MYSQLND_METHOD(mysqlnd_debug, log_va)(MYSQLND_DEBUG *self,
     189                 :                                                                           unsigned int line, const char * const file,
     190                 :                                                                           unsigned int level, const char * type,
     191                 :                                                                           const char *format, ...)
     192               0 : {
     193                 :         char pipe_buffer[512];
     194                 :         int i;
     195                 :         enum_func_status ret;
     196                 :         char * message_line, *buffer;
     197                 :         unsigned int message_line_len;
     198                 :         va_list args;
     199               0 :         unsigned int flags = self->flags;
     200                 :         char pid_buffer[10], time_buffer[30], file_buffer[200],
     201                 :                  line_buffer[6], level_buffer[7];
     202                 :         MYSQLND_ZTS(self);
     203                 : 
     204                 : #ifdef MYSQLND_THREADED
     205                 :         if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
     206                 :                 return PASS; /* don't trace background threads */
     207                 :         }
     208                 : #endif
     209                 : 
     210               0 :         if (!self->stream) {
     211               0 :                 if (FAIL == self->m->open(self, FALSE)) {
     212               0 :                         return FAIL;
     213                 :                 }
     214                 :         }
     215                 : 
     216               0 :         if (level == -1) {
     217               0 :                 level = zend_stack_count(&self->call_stack);
     218                 :         }
     219               0 :         i = MIN(level, sizeof(pipe_buffer) / 2  - 1);
     220               0 :         pipe_buffer[i*2] = '\0';
     221               0 :         for (;i > 0;i--) {
     222               0 :                 pipe_buffer[i*2 - 1] = ' ';
     223               0 :                 pipe_buffer[i*2 - 2] = '|';
     224                 :         }
     225                 : 
     226                 : 
     227               0 :         if (flags & MYSQLND_DEBUG_DUMP_PID) {
     228               0 :                 snprintf(pid_buffer, sizeof(pid_buffer) - 1, "%5u: ", self->pid);
     229               0 :                 pid_buffer[sizeof(pid_buffer) - 1 ] = '\0';
     230                 :         }
     231               0 :         if (flags & MYSQLND_DEBUG_DUMP_TIME) {
     232                 :                 /* The following from FF's DBUG library, which is in the public domain */
     233                 : #if defined(PHP_WIN32)
     234                 :                 /* FIXME This doesn't give microseconds as in Unix case, and the resolution is
     235                 :                 in system ticks, 10 ms intervals. See my_getsystime.c for high res */
     236                 :                 SYSTEMTIME loc_t;
     237                 :                 GetLocalTime(&loc_t);
     238                 :                 snprintf(time_buffer, sizeof(time_buffer) - 1,
     239                 :                                  /* "%04d-%02d-%02d " */
     240                 :                                  "%02d:%02d:%02d.%06d ",
     241                 :                                  /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/
     242                 :                                  loc_t.wHour, loc_t.wMinute, loc_t.wSecond, loc_t.wMilliseconds);
     243                 :                 time_buffer[sizeof(time_buffer) - 1 ] = '\0';
     244                 : #else
     245                 :                 struct timeval tv;
     246                 :                 struct tm *tm_p;
     247               0 :                 if (gettimeofday(&tv, NULL) != -1) {
     248               0 :                         if ((tm_p= localtime((const time_t *)&tv.tv_sec))) {
     249               0 :                                 snprintf(time_buffer, sizeof(time_buffer) - 1,
     250                 :                                                  /* "%04d-%02d-%02d " */
     251                 :                                                  "%02d:%02d:%02d.%06d ",
     252                 :                                                  /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/
     253                 :                                                  tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec,
     254                 :                                                  (int) (tv.tv_usec));
     255               0 :                                 time_buffer[sizeof(time_buffer) - 1 ] = '\0';
     256                 :                         }
     257                 :                 }
     258                 : #endif
     259                 :         }
     260               0 :         if (flags & MYSQLND_DEBUG_DUMP_FILE) {
     261               0 :                 snprintf(file_buffer, sizeof(file_buffer) - 1, "%14s: ", file);
     262               0 :                 file_buffer[sizeof(file_buffer) - 1 ] = '\0';
     263                 :         }
     264               0 :         if (flags & MYSQLND_DEBUG_DUMP_LINE) {
     265               0 :                 snprintf(line_buffer, sizeof(line_buffer) - 1, "%5u: ", line);
     266               0 :                 line_buffer[sizeof(line_buffer) - 1 ] = '\0';
     267                 :         }
     268               0 :         if (flags & MYSQLND_DEBUG_DUMP_LEVEL) {
     269               0 :                 snprintf(level_buffer, sizeof(level_buffer) - 1, "%4u: ", level);
     270               0 :                 level_buffer[sizeof(level_buffer) - 1 ] = '\0';
     271                 :         }
     272                 : 
     273                 : 
     274               0 :         va_start(args, format);
     275               0 :         vspprintf(&buffer, 0, format, args);
     276               0 :         va_end(args);
     277                 : 
     278               0 :         message_line_len = spprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
     279                 :                                                                 flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
     280                 :                                                                 flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
     281                 :                                                                 flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",
     282                 :                                                                 flags & MYSQLND_DEBUG_DUMP_LINE? line_buffer:"",
     283                 :                                                                 flags & MYSQLND_DEBUG_DUMP_LEVEL? level_buffer:"",
     284                 :                                                                 pipe_buffer, type? type:"", buffer);
     285               0 :         efree(buffer);
     286                 : 
     287               0 :         ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
     288               0 :         efree(message_line);
     289                 : 
     290               0 :         if (flags & MYSQLND_DEBUG_FLUSH) {
     291               0 :                 self->m->close(self);
     292               0 :                 self->m->open(self, TRUE);        
     293                 :         }
     294               0 :         return ret;
     295                 : }
     296                 : /* }}} */
     297                 : 
     298                 : 
     299                 : /* FALSE - The DBG_ calls won't be traced, TRUE - will be traced */
     300                 : /* {{{ mysqlnd_res_meta::func_enter */
     301                 : static zend_bool
     302                 : MYSQLND_METHOD(mysqlnd_debug, func_enter)(MYSQLND_DEBUG * self,
     303                 :                                                                                   unsigned int line, const char * const file,
     304                 :                                                                                   char * func_name, unsigned int func_name_len)
     305               0 : {
     306                 : #ifdef MYSQLND_THREADED
     307                 :         MYSQLND_ZTS(self);
     308                 : #endif
     309               0 :         if ((self->flags & MYSQLND_DEBUG_DUMP_TRACE) == 0 || self->file_name == NULL) {
     310               0 :                 return FALSE;
     311                 :         }
     312                 : #ifdef MYSQLND_THREADED
     313                 :         if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
     314                 :                 return FALSE; /* don't trace background threads */
     315                 :         }
     316                 : #endif
     317               0 :         if (zend_stack_count(&self->call_stack) >= self->nest_level_limit) {
     318               0 :                 return FALSE;
     319                 :         }
     320                 : 
     321               0 :         if ((self->flags & MYSQLND_DEBUG_TRACE_MEMORY_CALLS) == 0 && 
     322                 :                 (func_name == mysqlnd_emalloc_name      || func_name == mysqlnd_pemalloc_name   ||
     323                 :                  func_name == mysqlnd_ecalloc_name      || func_name == mysqlnd_pecalloc_name   ||
     324                 :                  func_name == mysqlnd_erealloc_name || func_name == mysqlnd_perealloc_name      ||
     325                 :                  func_name == mysqlnd_efree_name        || func_name == mysqlnd_pefree_name             || 
     326                 :                  func_name == mysqlnd_malloc_name       || func_name == mysqlnd_calloc_name             || 
     327                 :                  func_name == mysqlnd_realloc_name      || func_name == mysqlnd_free_name               ||
     328                 :                  func_name == mysqlnd_palloc_zval_ptr_dtor_name || func_name == mysqlnd_palloc_get_zval_name ||
     329                 :                  func_name == mysqlnd_read_header_name || func_name == mysqlnd_read_body_name)) {
     330               0 :                 zend_stack_push(&self->call_stack, "", sizeof(""));
     331               0 :                 return FALSE;
     332                 :         }
     333                 : 
     334               0 :         zend_stack_push(&self->call_stack, func_name, func_name_len + 1);
     335                 : 
     336               0 :         if (zend_hash_num_elements(&self->not_filtered_functions) &&
     337                 :                 0 == zend_hash_exists(&self->not_filtered_functions, func_name, strlen(func_name) + 1))
     338                 :         {
     339               0 :                 return FALSE;
     340                 :         }
     341                 : 
     342               0 :         self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, ">%s", func_name);
     343               0 :         return TRUE;
     344                 : }
     345                 : /* }}} */
     346                 : 
     347                 : 
     348                 : /* {{{ mysqlnd_res_meta::func_leave */
     349                 : static enum_func_status
     350                 : MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int line,
     351                 :                                                                                   const char * const file)
     352               0 : {
     353                 :         char *func_name;
     354                 : #ifdef MYSQLND_THREADED
     355                 :         MYSQLND_ZTS(self);
     356                 : #endif
     357               0 :         if ((self->flags & MYSQLND_DEBUG_DUMP_TRACE) == 0 || self->file_name == NULL) {
     358               0 :                 return PASS;
     359                 :         }
     360                 : #ifdef MYSQLND_THREADED
     361                 :         if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
     362                 :                 return PASS; /* don't trace background threads */
     363                 :         }
     364                 : #endif
     365               0 :         if (zend_stack_count(&self->call_stack) >= self->nest_level_limit) {
     366               0 :                 return PASS;
     367                 :         }
     368                 : 
     369               0 :         zend_stack_top(&self->call_stack, (void **)&func_name);
     370                 : 
     371               0 :         if (func_name[0] == '\0') {
     372                 :                 ; /* don't log that function */
     373               0 :         } else if (!zend_hash_num_elements(&self->not_filtered_functions) ||
     374                 :                 1 == zend_hash_exists(&self->not_filtered_functions, func_name, strlen(func_name) + 1))
     375                 :         {
     376               0 :                 self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, "<%s", func_name);
     377                 :         }
     378                 : 
     379               0 :         return zend_stack_del_top(&self->call_stack) == SUCCESS? PASS:FAIL;
     380                 : }
     381                 : /* }}} */
     382                 : 
     383                 : 
     384                 : /* {{{ mysqlnd_res_meta::close */
     385                 : static enum_func_status
     386                 : MYSQLND_METHOD(mysqlnd_debug, close)(MYSQLND_DEBUG * self)
     387               1 : {
     388                 :         MYSQLND_ZTS(self);
     389               1 :         if (self->stream) {
     390               0 :                 php_stream_free(self->stream, PHP_STREAM_FREE_CLOSE);
     391               0 :                 self->stream = NULL;
     392                 :         }
     393               1 :         return PASS;
     394                 : }
     395                 : /* }}} */
     396                 : 
     397                 : 
     398                 : /* {{{ mysqlnd_res_meta::free */
     399                 : static enum_func_status
     400                 : MYSQLND_METHOD(mysqlnd_debug, free)(MYSQLND_DEBUG * self)
     401               1 : {
     402               1 :         if (self->file_name && self->file_name != mysqlnd_debug_default_trace_file) {
     403               1 :                 efree(self->file_name);
     404               1 :                 self->file_name = NULL;
     405                 :         }
     406               1 :         zend_stack_destroy(&self->call_stack);
     407               1 :         zend_hash_destroy(&self->not_filtered_functions);
     408               1 :         efree(self);
     409               1 :         return PASS;
     410                 : }
     411                 : /* }}} */
     412                 : 
     413                 : enum mysqlnd_debug_parser_state
     414                 : {
     415                 :         PARSER_WAIT_MODIFIER,
     416                 :         PARSER_WAIT_COLON,
     417                 :         PARSER_WAIT_VALUE
     418                 : };
     419                 : 
     420                 : 
     421                 : /* {{{ mysqlnd_res_meta::set_mode */
     422                 : static void
     423                 : MYSQLND_METHOD(mysqlnd_debug, set_mode)(MYSQLND_DEBUG * self, const char * const mode)
     424               1 : {
     425               1 :         unsigned int mode_len = strlen(mode), i;
     426               1 :         enum mysqlnd_debug_parser_state state = PARSER_WAIT_MODIFIER;
     427                 : 
     428               1 :         self->flags = 0;
     429               1 :         self->nest_level_limit = 0;
     430               1 :         if (self->file_name && self->file_name != mysqlnd_debug_default_trace_file) {
     431               0 :                 efree(self->file_name);
     432               0 :                 self->file_name = NULL;
     433                 :         }
     434               1 :         if (zend_hash_num_elements(&self->not_filtered_functions)) {
     435               0 :                 zend_hash_destroy(&self->not_filtered_functions);
     436               0 :                 zend_hash_init(&self->not_filtered_functions, 0, NULL, NULL, 0);
     437                 :         }
     438                 : 
     439               4 :         for (i = 0; i < mode_len; i++) {
     440               3 :                 switch (mode[i]) {
     441                 :                         case 'O':
     442                 :                         case 'A':
     443               1 :                                 self->flags |= MYSQLND_DEBUG_FLUSH;
     444                 :                         case 'a':
     445                 :                         case 'o':
     446               1 :                                 if (mode[i] == 'a' || mode[i] == 'A') {
     447               0 :                                         self->flags |= MYSQLND_DEBUG_APPEND;
     448                 :                                 }
     449               2 :                                 if (i + 1 < mode_len && mode[i+1] == ',') {
     450               1 :                                         unsigned int j = i + 2;
     451              30 :                                         while (j < mode_len) {
     452              28 :                                                 if (mode[j] == ':') {
     453               0 :                                                         break;
     454                 :                                                 }
     455              28 :                                                 j++;
     456                 :                                         }
     457               1 :                                         if (j > i + 2) {
     458               1 :                                                 self->file_name = estrndup(mode + i + 2, j - i - 2);
     459                 :                                         }
     460               1 :                                         i = j;
     461                 :                                 } else {
     462               0 :                                         if (!self->file_name)
     463               0 :                                                 self->file_name = (char *) mysqlnd_debug_default_trace_file;
     464                 :                                 }
     465               1 :                                 state = PARSER_WAIT_COLON;
     466               1 :                                 break;
     467                 :                         case ':':
     468                 : #if 0
     469                 :                                 if (state != PARSER_WAIT_COLON) {
     470                 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Consecutive semicolons at position %u", i);
     471                 :                                 }
     472                 : #endif
     473               1 :                                 state = PARSER_WAIT_MODIFIER;
     474               1 :                                 break;
     475                 :                         case 'f': /* limit output to these functions */
     476               0 :                                 if (i + 1 < mode_len && mode[i+1] == ',') {
     477               0 :                                         unsigned int j = i + 2;
     478               0 :                                         i++;
     479               0 :                                         while (j < mode_len) {
     480               0 :                                                 if (mode[j] == ':') {
     481                 :                                                         /* function names with :: */
     482               0 :                                                         if ((j + 1 < mode_len) && mode[j+1] == ':') {
     483               0 :                                                                 j += 2;
     484               0 :                                                                 continue;
     485                 :                                                         }
     486                 :                                                 }
     487               0 :                                                 if (mode[j] == ',' || mode[j] == ':') {
     488               0 :                                                         if (j > i + 2) {
     489                 :                                                                 char func_name[1024];
     490               0 :                                                                 unsigned int func_name_len = MIN(sizeof(func_name) - 1, j - i - 1);
     491               0 :                                                                 memcpy(func_name, mode + i + 1, func_name_len);
     492               0 :                                                                 func_name[func_name_len] = '\0'; 
     493                 : 
     494               0 :                                                                 zend_hash_add_empty_element(&self->not_filtered_functions,
     495                 :                                                                                                                         func_name, func_name_len + 1);
     496               0 :                                                                 i = j;
     497                 :                                                         }
     498               0 :                                                         if (mode[j] == ':') {
     499               0 :                                                                 break;
     500                 :                                                         }
     501                 :                                                 }
     502               0 :                                                 j++;
     503                 :                                         }
     504               0 :                                         i = j;
     505                 :                                 } else {
     506                 : #if 0
     507                 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING,
     508                 :                                                                          "Expected list of functions for '%c' found none", mode[i]);                          
     509                 : #endif
     510                 :                                 }
     511               0 :                                 state = PARSER_WAIT_COLON;
     512               0 :                                 break;
     513                 :                         case 'D':
     514                 :                         case 'd':
     515                 :                         case 'g':
     516                 :                         case 'p':
     517                 :                                 /* unsupported */
     518               0 :                                 if ((i + 1) < mode_len && mode[i+1] == ',') {
     519               0 :                                         i+= 2;
     520               0 :                                         while (i < mode_len) {
     521               0 :                                                 if (mode[i] == ':') {
     522               0 :                                                         break;
     523                 :                                                 }
     524               0 :                                                 i++;
     525                 :                                         }
     526                 :                                 }
     527               0 :                                 state = PARSER_WAIT_COLON;
     528               0 :                                 break;
     529                 :                         case 'F':
     530               0 :                                 self->flags |= MYSQLND_DEBUG_DUMP_FILE;
     531               0 :                                 state = PARSER_WAIT_COLON;
     532               0 :                                 break;
     533                 :                         case 'i':
     534               0 :                                 self->flags |= MYSQLND_DEBUG_DUMP_PID;
     535               0 :                                 state = PARSER_WAIT_COLON;
     536               0 :                                 break;
     537                 :                         case 'L':
     538               0 :                                 self->flags |= MYSQLND_DEBUG_DUMP_LINE;
     539               0 :                                 state = PARSER_WAIT_COLON;
     540               0 :                                 break;
     541                 :                         case 'n':
     542               0 :                                 self->flags |= MYSQLND_DEBUG_DUMP_LEVEL;
     543               0 :                                 state = PARSER_WAIT_COLON;
     544               0 :                                 break;
     545                 :                         case 't':
     546               1 :                                 if (mode[i+1] == ',') {
     547               0 :                                         unsigned int j = i + 2;
     548               0 :                                         while (j < mode_len) {
     549               0 :                                                 if (mode[j] == ':') {
     550               0 :                                                         break;
     551                 :                                                 }
     552               0 :                                                 j++;
     553                 :                                         }
     554               0 :                                         if (j > i + 2) {
     555               0 :                                                 char *value_str = estrndup(mode + i + 2, j - i - 2);
     556               0 :                                                 self->nest_level_limit = atoi(value_str);
     557               0 :                                                 efree(value_str);
     558                 :                                         }
     559               0 :                                         i = j;
     560                 :                                 } else {
     561               1 :                                         self->nest_level_limit = 200; /* default value for FF DBUG */
     562                 :                                 }
     563               1 :                                 self->flags |= MYSQLND_DEBUG_DUMP_TRACE;
     564               1 :                                 state = PARSER_WAIT_COLON;
     565               1 :                                 break;
     566                 :                         case 'T':
     567               0 :                                 self->flags |= MYSQLND_DEBUG_DUMP_TIME;
     568               0 :                                 state = PARSER_WAIT_COLON;
     569               0 :                                 break;
     570                 :                         case 'N':
     571                 :                         case 'P':
     572                 :                         case 'r':
     573                 :                         case 'S':
     574               0 :                                 state = PARSER_WAIT_COLON;
     575               0 :                                 break;
     576                 :                         case 'm': /* mysqlnd extension - trace memory functions */
     577               0 :                                 self->flags |= MYSQLND_DEBUG_TRACE_MEMORY_CALLS;
     578               0 :                                 state = PARSER_WAIT_COLON;
     579               0 :                                 break;
     580                 :                         default:
     581               0 :                                 if (state == PARSER_WAIT_MODIFIER) {
     582                 : #if 0
     583                 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unrecognized format '%c'", mode[i]);
     584                 : #endif
     585               0 :                                         if (i+1 < mode_len && mode[i+1] == ',') {
     586               0 :                                                 i+= 2;
     587               0 :                                                 while (i < mode_len) {
     588               0 :                                                         if (mode[i] == ':') {
     589               0 :                                                                 break;
     590                 :                                                         }
     591               0 :                                                         i++;
     592                 :                                                 }
     593                 :                                         }
     594               0 :                                         state = PARSER_WAIT_COLON;
     595                 :                                 } else if (state == PARSER_WAIT_COLON) {
     596                 : #if 0
     597                 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Colon expected, '%c' found", mode[i]);                           
     598                 : #endif
     599                 :                                 }
     600                 :                                 break;
     601                 :                 }
     602                 :         }
     603               1 : }
     604                 : /* }}} */
     605                 : 
     606                 : 
     607                 : MYSQLND_CLASS_METHODS_START(mysqlnd_debug)
     608                 :         MYSQLND_METHOD(mysqlnd_debug, open),
     609                 :         MYSQLND_METHOD(mysqlnd_debug, set_mode),
     610                 :         MYSQLND_METHOD(mysqlnd_debug, log),
     611                 :         MYSQLND_METHOD(mysqlnd_debug, log_va),
     612                 :         MYSQLND_METHOD(mysqlnd_debug, func_enter),
     613                 :         MYSQLND_METHOD(mysqlnd_debug, func_leave),
     614                 :         MYSQLND_METHOD(mysqlnd_debug, close),
     615                 :         MYSQLND_METHOD(mysqlnd_debug, free),
     616                 : MYSQLND_CLASS_METHODS_END;
     617                 : 
     618                 : 
     619                 : 
     620                 : /* {{{ mysqlnd_debug_init */
     621                 : PHPAPI MYSQLND_DEBUG *mysqlnd_debug_init(TSRMLS_D)
     622               1 : {
     623               1 :         MYSQLND_DEBUG *ret = ecalloc(1, sizeof(MYSQLND_DEBUG));
     624                 : #ifdef ZTS
     625                 :         ret->TSRMLS_C = TSRMLS_C;
     626                 : #endif
     627               1 :         ret->nest_level_limit = 0;
     628               1 :         ret->pid = getpid();
     629               1 :         zend_stack_init(&ret->call_stack);
     630               1 :         zend_hash_init(&ret->not_filtered_functions, 0, NULL, NULL, 0);
     631                 : 
     632               1 :         ret->m = & mysqlnd_mysqlnd_debug_methods;
     633                 :         
     634               1 :         return ret;
     635                 : }
     636                 : /* }}} */
     637                 : 
     638                 : 
     639                 : /* {{{ _mysqlnd_debug */
     640                 : PHPAPI void _mysqlnd_debug(const char *mode TSRMLS_DC)
     641               0 : {
     642                 : #ifdef PHP_DEBUG
     643               0 :         MYSQLND_DEBUG *dbg = MYSQLND_G(dbg);
     644               0 :         if (!dbg) {
     645               0 :                 MYSQLND_G(dbg) = dbg = mysqlnd_debug_init(TSRMLS_C);
     646               0 :                 if (!dbg) {
     647               0 :                         return;
     648                 :                 }
     649                 :         }
     650                 :         
     651               0 :         dbg->m->close(dbg);
     652               0 :         dbg->m->set_mode(dbg, mode);
     653               0 :         while (zend_stack_count(&dbg->call_stack)) {
     654               0 :                 zend_stack_del_top(&dbg->call_stack);
     655                 :         }
     656                 : #endif
     657                 : }
     658                 : /* }}} */
     659                 : 
     660                 : 
     661                 : #if ZEND_DEBUG
     662                 : #else
     663                 : #define __zend_filename "/unknown/unknown"
     664                 : #define __zend_lineno   0
     665                 : #endif
     666                 : 
     667                 : 
     668                 : /* {{{ _mysqlnd_emalloc */
     669                 : void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
     670           32224 : {
     671                 :         void *ret;
     672           32224 :         DBG_ENTER(mysqlnd_emalloc_name);
     673                 : #ifdef MYSQLND_THREADED
     674                 :         if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
     675                 :                 DBG_RETURN(_mysqlnd_pemalloc(size, 1 TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC));
     676                 :         }
     677                 : #endif
     678                 : 
     679           32224 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     680           32224 :         DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
     681           32224 :         ret = emalloc(size);
     682           32224 :         DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
     683           32224 :         DBG_INF_FMT("size=%lu ptr=%p", size, ret); 
     684                 : 
     685           32224 :         if (MYSQLND_G(collect_memory_statistics)) {
     686              69 :                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMMOUNT, size);
     687                 :         }
     688           32224 :         DBG_RETURN(ret);
     689                 : }
     690                 : /* }}} */
     691                 : 
     692                 : 
     693                 : /* {{{ _mysqlnd_pemalloc */
     694                 : void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
     695           18121 : {
     696                 :         void *ret;
     697           18121 :         DBG_ENTER(mysqlnd_pemalloc_name);
     698           18121 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     699           18121 :         if (persistent == FALSE) {
     700           16188 :                 DBG_INF_FMT("before: %lu", zend_memory_usage(persistent TSRMLS_CC));
     701                 :         }
     702                 : 
     703           18121 :         ret = pemalloc(size, persistent);
     704           18121 :         DBG_INF_FMT("size=%lu ptr=%p persistent=%d", size, ret, persistent); 
     705                 : 
     706           18121 :         if (persistent == FALSE) {
     707           16188 :                 DBG_INF_FMT("after : %lu", zend_memory_usage(persistent TSRMLS_CC));
     708                 :         }
     709                 : 
     710           18121 :         if (MYSQLND_G(collect_memory_statistics)) {
     711              58 :                 enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT;
     712              58 :                 enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_MALLOC_AMMOUNT:STAT_MEM_EMALLOC_AMMOUNT;
     713              58 :                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
     714                 :         }
     715                 : 
     716           18121 :         DBG_RETURN(ret);
     717                 : }
     718                 : /* }}} */
     719                 : 
     720                 : 
     721                 : /* {{{ _mysqlnd_ecalloc */
     722                 : void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
     723           44244 : {
     724                 :         void *ret;
     725           44244 :         DBG_ENTER(mysqlnd_ecalloc_name);
     726                 : #ifdef MYSQLND_THREADED
     727                 :         if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
     728                 :                 DBG_RETURN(_mysqlnd_pecalloc(nmemb, size, 1 TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC));
     729                 :         }
     730                 : #endif
     731           44244 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     732           44244 :         DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
     733                 : 
     734           44244 :         ret = ecalloc(nmemb, size);
     735                 : 
     736           44244 :         DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
     737           44244 :         DBG_INF_FMT("size=%lu ptr=%p", size, ret); 
     738           44244 :         if (MYSQLND_G(collect_memory_statistics)) {
     739             136 :                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMMOUNT, size);
     740                 :         }
     741           44244 :         DBG_RETURN(ret);
     742                 : }
     743                 : /* }}} */
     744                 : 
     745                 : 
     746                 : /* {{{ _mysqlnd_pecalloc */
     747                 : void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
     748           11160 : {
     749                 :         void *ret;
     750           11160 :         DBG_ENTER(mysqlnd_pecalloc_name);
     751           11160 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     752           11160 :         if (persistent == FALSE) {
     753           10138 :                 DBG_INF_FMT("before: %lu", zend_memory_usage(persistent TSRMLS_CC));
     754                 :         }
     755                 : 
     756           11160 :         ret = pecalloc(nmemb, size, persistent);
     757           11160 :         DBG_INF_FMT("size=%lu ptr=%p", size, ret); 
     758                 : 
     759           11160 :         if (persistent == FALSE) {
     760           10138 :                 DBG_INF_FMT("after : %lu", zend_memory_usage(persistent TSRMLS_CC));
     761                 :         }
     762                 : 
     763           11160 :         if (MYSQLND_G(collect_memory_statistics)) {
     764              66 :                 enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT;
     765              66 :                 enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_CALLOC_AMMOUNT:STAT_MEM_ECALLOC_AMMOUNT;
     766              66 :                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
     767                 :         }
     768                 : 
     769           11160 :         DBG_RETURN(ret);
     770                 : }
     771                 : /* }}} */
     772                 : 
     773                 : 
     774                 : /* {{{ _mysqlnd_erealloc */
     775                 : void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
     776             372 : {
     777                 :         void *ret;
     778             372 :         DBG_ENTER(mysqlnd_erealloc_name);
     779                 : #ifdef MYSQLND_THREADED
     780                 :         if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
     781                 :                 DBG_RETURN(_mysqlnd_perealloc(ptr, new_size, 1 TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC));
     782                 :         }
     783                 : #endif
     784             372 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     785             372 :         DBG_INF_FMT("ptr=%p new_size=%lu", ptr, new_size); 
     786             372 :         DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
     787                 : 
     788             372 :         ret = erealloc(ptr, new_size);
     789                 : 
     790             372 :         DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
     791             372 :         DBG_INF_FMT("new_ptr=%p", ret); 
     792             372 :         if (MYSQLND_G(collect_memory_statistics)) {
     793               0 :                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMMOUNT, new_size);
     794                 :         }
     795             372 :         DBG_RETURN(ret);
     796                 : }
     797                 : /* }}} */
     798                 : 
     799                 : 
     800                 : /* {{{ _mysqlnd_perealloc */
     801                 : void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
     802            8462 : {
     803                 :         void *ret;
     804            8462 :         DBG_ENTER(mysqlnd_perealloc_name);
     805            8462 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     806            8462 :         DBG_INF_FMT("ptr=%p new_size=%lu persist=%d", ptr, new_size, persistent); 
     807            8462 :         if (persistent == FALSE) {
     808            8453 :                 DBG_INF_FMT("before: %lu", zend_memory_usage(persistent TSRMLS_CC));
     809                 :         }
     810                 : 
     811            8462 :         ret = perealloc(ptr, new_size, persistent);
     812                 : 
     813            8462 :         DBG_INF_FMT("new_ptr=%p", ret); 
     814                 : 
     815            8462 :         if (persistent == FALSE) {
     816            8453 :                 DBG_INF_FMT("after : %lu", zend_memory_usage(persistent TSRMLS_CC));
     817                 :         }
     818            8462 :         MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT);
     819            8462 :         if (MYSQLND_G(collect_memory_statistics)) {
     820              42 :                 enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;
     821              42 :                 enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_REALLOC_AMMOUNT:STAT_MEM_EREALLOC_AMMOUNT;
     822              42 :                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size);
     823                 :         }
     824            8462 :         DBG_RETURN(ret);
     825                 : }
     826                 : /* }}} */
     827                 : 
     828                 : 
     829                 : /* {{{ _mysqlnd_efree */
     830                 : void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
     831           60438 : {
     832           60438 :         DBG_ENTER(mysqlnd_efree_name);
     833                 : #ifdef MYSQLND_THREADED
     834                 :         if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
     835                 :                 DBG_RETURN(_mysqlnd_pefree(ptr, 1 TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC));
     836                 :         }
     837                 : #endif
     838           60438 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     839           60438 :         DBG_INF_FMT("ptr=%p", ptr); 
     840           60438 :         DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
     841           60438 :         MYSQLND_INC_GLOBAL_STATISTIC(STAT_MEM_EFREE_COUNT);
     842                 : 
     843           60438 :         efree(ptr);
     844                 : 
     845           60438 :         DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
     846                 :         DBG_VOID_RETURN;
     847                 : }
     848                 : /* }}} */
     849                 : 
     850                 : 
     851                 : /* {{{ _mysqlnd_pefree */
     852                 : void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D)
     853          129471 : {
     854          129471 :         DBG_ENTER(mysqlnd_pefree_name);
     855          129471 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     856          129471 :         DBG_INF_FMT("ptr=%p persistent=%d", ptr, persistent); 
     857          129471 :         if (persistent == FALSE) {
     858          118666 :                 DBG_INF_FMT("before: %lu", zend_memory_usage(persistent TSRMLS_CC));
     859                 :         }
     860                 : 
     861          129471 :         pefree(ptr, persistent);
     862                 : 
     863          129471 :         if (persistent == FALSE) {
     864          118666 :                 DBG_INF_FMT("after : %lu", zend_memory_usage(persistent TSRMLS_CC));
     865                 :         }
     866          129471 :         if (MYSQLND_G(collect_memory_statistics)) {
     867             434 :                 MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT);
     868                 :         }
     869                 :         DBG_VOID_RETURN;
     870                 : }
     871                 : 
     872                 : 
     873                 : /* {{{ _mysqlnd_malloc */
     874                 : void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)
     875           39916 : {
     876                 :         void *ret;
     877           39916 :         DBG_ENTER(mysqlnd_malloc_name);
     878           39916 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     879                 : 
     880           39916 :         ret = malloc(size);
     881                 : 
     882           39916 :         DBG_INF_FMT("size=%lu ptr=%p", size, ret); 
     883           39916 :         if (MYSQLND_G(collect_memory_statistics)) {
     884             114 :                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMMOUNT, size);
     885                 :         }
     886           39916 :         DBG_RETURN(ret);
     887                 : }
     888                 : /* }}} */
     889                 : 
     890                 : 
     891                 : /* {{{ _mysqlnd_calloc */
     892                 : void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
     893          261056 : {
     894                 :         void *ret;
     895          261056 :         DBG_ENTER(mysqlnd_calloc_name);
     896          261056 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     897                 : 
     898          261056 :         ret = calloc(nmemb, size);
     899                 : 
     900          261056 :         DBG_INF_FMT("size=%lu ptr=%p", size, ret); 
     901          261056 :         if (MYSQLND_G(collect_memory_statistics)) {
     902             231 :                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMMOUNT, size);
     903                 :         }
     904          261056 :         DBG_RETURN(ret);
     905                 : }
     906                 : /* }}} */
     907                 : 
     908                 : 
     909                 : /* {{{ _mysqlnd_realloc */
     910                 : void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)
     911               0 : {
     912                 :         void *ret;
     913               0 :         DBG_ENTER(mysqlnd_realloc_name);
     914               0 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     915               0 :         DBG_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr); 
     916               0 :         DBG_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC));
     917                 : 
     918               0 :         ret = realloc(ptr, new_size);
     919                 : 
     920               0 :         DBG_INF_FMT("new_ptr=%p", ret);
     921                 : 
     922               0 :         if (MYSQLND_G(collect_memory_statistics)) {
     923               0 :                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMMOUNT, new_size);
     924                 :         }
     925               0 :         DBG_RETURN(ret);
     926                 : }
     927                 : /* }}} */
     928                 : 
     929                 : 
     930                 : /* {{{ _mysqlnd_free */
     931                 : void _mysqlnd_free(void *ptr MYSQLND_MEM_D)
     932          301426 : {
     933          301426 :         DBG_ENTER(mysqlnd_free_name);
     934          301426 :         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
     935          301426 :         DBG_INF_FMT("ptr=%p", ptr); 
     936                 : 
     937          301426 :         free(ptr);
     938                 : 
     939          301426 :         if (MYSQLND_G(collect_memory_statistics)) {
     940             345 :                 MYSQLND_INC_GLOBAL_STATISTIC(STAT_MEM_FREE_COUNT);
     941                 :         }
     942                 :         DBG_VOID_RETURN;
     943                 : }
     944                 : /* }}} */
     945                 : 
     946                 : 
     947                 : 
     948                 : 
     949                 : /* Follows code borrowed from zend_builtin_functions.c because the functions there are static */
     950                 : 
     951                 : #if PHP_MAJOR_VERSION >= 6
     952                 : /* {{{ gettraceasstring() macros */
     953                 : #define TRACE_APPEND_CHR(chr)                                            \
     954                 :         *str = (char*)erealloc(*str, *len + 1 + 1);                          \
     955                 :         (*str)[(*len)++] = chr
     956                 : 
     957                 : #define TRACE_APPEND_STRL(val, vallen)                                   \
     958                 :         {                                                                    \
     959                 :                 int l = vallen;                                                  \
     960                 :                 *str = (char*)erealloc(*str, *len + l + 1);                      \
     961                 :                 memcpy((*str) + *len, val, l);                                   \
     962                 :                 *len += l;                                                       \
     963                 :         }
     964                 : 
     965                 : #define TRACE_APPEND_USTRL(val, vallen) \
     966                 :         { \
     967                 :                 zval tmp, copy; \
     968                 :                 int use_copy; \
     969                 :                 ZVAL_UNICODEL(&tmp, val, vallen, 1); \
     970                 :                 zend_make_printable_zval(&tmp, &copy, &use_copy); \
     971                 :                 TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
     972                 :                 zval_dtor(&copy); \
     973                 :                 zval_dtor(&tmp); \
     974                 :         }
     975                 : 
     976                 : #define TRACE_APPEND_ZVAL(zv) \
     977                 :         if (Z_TYPE_P((zv)) == IS_UNICODE) { \
     978                 :                 zval copy; \
     979                 :                 int use_copy; \
     980                 :                 zend_make_printable_zval((zv), &copy, &use_copy); \
     981                 :                 TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
     982                 :                 zval_dtor(&copy); \
     983                 :         } else { \
     984                 :                 TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \
     985                 :         }
     986                 : 
     987                 : #define TRACE_APPEND_STR(val)                                            \
     988                 :         TRACE_APPEND_STRL(val, sizeof(val)-1)
     989                 : 
     990                 : #define TRACE_APPEND_KEY(key)                                            \
     991                 :         if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
     992                 :                 if (Z_TYPE_PP(tmp) == IS_UNICODE) { \
     993                 :                         zval copy; \
     994                 :                         int use_copy; \
     995                 :                         zend_make_printable_zval(*tmp, &copy, &use_copy); \
     996                 :             TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
     997                 :             zval_dtor(&copy); \
     998                 :                 } else { \
     999                 :             TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \
    1000                 :           } \
    1001                 :         }
    1002                 : /* }}} */
    1003                 : 
    1004                 : /* {{{ mysqlnd_build_trace_args */
    1005                 : static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
    1006               0 : {
    1007                 :         char **str;
    1008                 :         int *len;
    1009                 : 
    1010               0 :         str = va_arg(args, char**);
    1011               0 :         len = va_arg(args, int*);
    1012                 : 
    1013                 :         /* the trivial way would be to do:
    1014                 :          * conver_to_string_ex(arg);
    1015                 :          * append it and kill the now tmp arg.
    1016                 :          * but that could cause some E_NOTICE and also damn long lines.
    1017                 :          */
    1018                 : 
    1019               0 :         switch (Z_TYPE_PP(arg)) {
    1020                 :                 case IS_NULL:
    1021               0 :                         TRACE_APPEND_STR("NULL, ");
    1022               0 :                         break;
    1023                 :                 case IS_STRING: {
    1024                 :                         int l_added;
    1025               0 :                         TRACE_APPEND_CHR('\'');
    1026               0 :                         if (Z_STRLEN_PP(arg) > 15) {
    1027               0 :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
    1028               0 :                                 TRACE_APPEND_STR("...', ");
    1029               0 :                                 l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
    1030                 :                         } else {
    1031               0 :                                 l_added = Z_STRLEN_PP(arg);
    1032               0 :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
    1033               0 :                                 TRACE_APPEND_STR("', ");
    1034               0 :                                 l_added += 3 + 1;
    1035                 :                         }
    1036               0 :                         while (--l_added) {
    1037               0 :                                 if ((unsigned char)(*str)[*len - l_added] < 32) {
    1038               0 :                                         (*str)[*len - l_added] = '?';
    1039                 :                                 }
    1040                 :                         }
    1041               0 :                         break;
    1042                 :                 }
    1043                 :                 case IS_UNICODE: {
    1044                 :                         int l_added;
    1045                 : 
    1046                 :                         /*
    1047                 :                          * We do not want to apply current error mode here, since
    1048                 :                          * zend_make_printable_zval() uses output encoding converter.
    1049                 :                          * Temporarily set output encoding converter to escape offending
    1050                 :                          * chars with \uXXXX notation.
    1051                 :                          */
    1052               0 :                         zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, ZEND_CONV_ERROR_ESCAPE_JAVA);
    1053               0 :                         TRACE_APPEND_CHR('\'');
    1054               0 :                         if (Z_USTRLEN_PP(arg) > 15) {
    1055               0 :                                 TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), 15);
    1056               0 :                                 TRACE_APPEND_STR("...', ");
    1057               0 :                                 l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
    1058                 :                         } else {
    1059               0 :                                 l_added = Z_USTRLEN_PP(arg);
    1060               0 :                                 TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), l_added);
    1061               0 :                                 TRACE_APPEND_STR("', ");
    1062               0 :                                 l_added += 3 + 1;
    1063                 :                         }
    1064                 :                         /*
    1065                 :                          * Reset output encoding converter error mode.
    1066                 :                          */
    1067               0 :                         zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, UG(from_error_mode));
    1068               0 :                         while (--l_added) {
    1069               0 :                                 if ((unsigned char)(*str)[*len - l_added] < 32) {
    1070               0 :                                         (*str)[*len - l_added] = '?';
    1071                 :                                 }
    1072                 :                         }
    1073               0 :                         break;
    1074                 :                 }
    1075                 :                 case IS_BOOL:
    1076               0 :                         if (Z_LVAL_PP(arg)) {
    1077               0 :                                 TRACE_APPEND_STR("true, ");
    1078                 :                         } else {
    1079               0 :                                 TRACE_APPEND_STR("false, ");
    1080                 :                         }
    1081               0 :                         break;
    1082                 :                 case IS_RESOURCE:
    1083               0 :                         TRACE_APPEND_STR("Resource id #");
    1084                 :                         /* break; */
    1085                 :                 case IS_LONG: {
    1086               0 :                         long lval = Z_LVAL_PP(arg);
    1087                 :                         char s_tmp[MAX_LENGTH_OF_LONG + 1];
    1088               0 :                         int l_tmp = zend_sprintf(s_tmp, "%ld", lval);  /* SAFE */
    1089               0 :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
    1090               0 :                         TRACE_APPEND_STR(", ");
    1091               0 :                         break;
    1092                 :                 }
    1093                 :                 case IS_DOUBLE: {
    1094               0 :                         double dval = Z_DVAL_PP(arg);
    1095                 :                         char *s_tmp;
    1096                 :                         int l_tmp;
    1097                 : 
    1098               0 :                         s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
    1099               0 :                         l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval);  /* SAFE */
    1100               0 :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
    1101                 :                         /* %G already handles removing trailing zeros from the fractional part, yay */
    1102               0 :                         efree(s_tmp);
    1103               0 :                         TRACE_APPEND_STR(", ");
    1104               0 :                         break;
    1105                 :                 }
    1106                 :                 case IS_ARRAY:
    1107               0 :                         TRACE_APPEND_STR("Array, ");
    1108               0 :                         break;
    1109                 :                 case IS_OBJECT: {
    1110                 :                         zval tmp;
    1111                 :                         zstr class_name;
    1112                 :                         zend_uint class_name_len;
    1113                 :                         int dup;
    1114                 : 
    1115               0 :                         TRACE_APPEND_STR("Object(");
    1116                 : 
    1117               0 :                         dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
    1118                 : 
    1119               0 :                         ZVAL_UNICODEL(&tmp, class_name.u, class_name_len, 1);
    1120               0 :                         convert_to_string_with_converter(&tmp, ZEND_U_CONVERTER(UG(output_encoding_conv)));
    1121               0 :                         TRACE_APPEND_STRL(Z_STRVAL(tmp), Z_STRLEN(tmp));
    1122               0 :                         zval_dtor(&tmp);
    1123                 : 
    1124               0 :                         if(!dup) {
    1125               0 :                                 efree(class_name.v);
    1126                 :                         }
    1127                 : 
    1128               0 :                         TRACE_APPEND_STR("), ");
    1129                 :                         break;
    1130                 :                 }
    1131                 :                 default:
    1132                 :                         break;
    1133                 :         }
    1134               0 :         return ZEND_HASH_APPLY_KEEP;
    1135                 : }
    1136                 : /* }}} */
    1137                 : 
    1138                 : 
    1139                 : static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
    1140               0 : {
    1141                 :         char *s_tmp, **str;
    1142                 :         int *len, *num;
    1143                 :         long line;
    1144               0 :         HashTable *ht = Z_ARRVAL_PP(frame);
    1145                 :         zval **file, **tmp;
    1146                 : 
    1147               0 :         str = va_arg(args, char**);
    1148               0 :         len = va_arg(args, int*);
    1149               0 :         num = va_arg(args, int*);
    1150                 : 
    1151               0 :         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
    1152               0 :         sprintf(s_tmp, "#%d ", (*num)++);
    1153               0 :         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
    1154               0 :         efree(s_tmp);
    1155               0 :         if (zend_ascii_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
    1156               0 :                 if (zend_ascii_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
    1157               0 :                         line = Z_LVAL_PP(tmp);
    1158                 :                 } else {
    1159               0 :                         line = 0;
    1160                 :                 }
    1161               0 :                 TRACE_APPEND_ZVAL(*file);
    1162               0 :                 s_tmp = emalloc(MAX_LENGTH_OF_LONG + 2 + 1);
    1163               0 :                 sprintf(s_tmp, "(%ld): ", line);
    1164               0 :                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
    1165               0 :                 efree(s_tmp);
    1166                 :         } else {
    1167               0 :                 TRACE_APPEND_STR("[internal function]: ");
    1168                 :         }
    1169               0 :         TRACE_APPEND_KEY("class");
    1170               0 :         TRACE_APPEND_KEY("type");
    1171               0 :         TRACE_APPEND_KEY("function");
    1172               0 :         TRACE_APPEND_CHR('(');
    1173               0 :         if (zend_ascii_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
    1174               0 :                 int last_len = *len;
    1175               0 :                 zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
    1176               0 :                 if (last_len != *len) {
    1177               0 :                         *len -= 2; /* remove last ', ' */
    1178                 :                 }
    1179                 :         }
    1180               0 :         TRACE_APPEND_STR(")\n");
    1181               0 :         return ZEND_HASH_APPLY_KEEP;
    1182                 : }
    1183                 : /* }}} */
    1184                 : 
    1185                 : 
    1186                 : #else /* PHP 5*/
    1187                 : 
    1188                 : 
    1189                 : /* {{{ gettraceasstring() macros */
    1190                 : #define TRACE_APPEND_CHR(chr)                                            \
    1191                 :         *str = (char*)erealloc(*str, *len + 1 + 1);                          \
    1192                 :         (*str)[(*len)++] = chr
    1193                 : 
    1194                 : #define TRACE_APPEND_STRL(val, vallen)                                   \
    1195                 :         {                                                                    \
    1196                 :                 int l = vallen;                                                  \
    1197                 :                 *str = (char*)erealloc(*str, *len + l + 1);                      \
    1198                 :                 memcpy((*str) + *len, val, l);                                   \
    1199                 :                 *len += l;                                                       \
    1200                 :         }
    1201                 : 
    1202                 : #define TRACE_APPEND_STR(val)                                            \
    1203                 :         TRACE_APPEND_STRL(val, sizeof(val)-1)
    1204                 : 
    1205                 : #define TRACE_APPEND_KEY(key)                                            \
    1206                 :         if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
    1207                 :             TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \
    1208                 :         }
    1209                 : 
    1210                 : /* }}} */
    1211                 : 
    1212                 : 
    1213                 : static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
    1214                 : {
    1215                 :         char **str;
    1216                 :         int *len;
    1217                 : 
    1218                 :         str = va_arg(args, char**);
    1219                 :         len = va_arg(args, int*);
    1220                 : 
    1221                 :         /* the trivial way would be to do:
    1222                 :          * conver_to_string_ex(arg);
    1223                 :          * append it and kill the now tmp arg.
    1224                 :          * but that could cause some E_NOTICE and also damn long lines.
    1225                 :          */
    1226                 : 
    1227                 :         switch (Z_TYPE_PP(arg)) {
    1228                 :                 case IS_NULL:
    1229                 :                         TRACE_APPEND_STR("NULL, ");
    1230                 :                         break;
    1231                 :                 case IS_STRING: {
    1232                 :                         int l_added;
    1233                 :                         TRACE_APPEND_CHR('\'');
    1234                 :                         if (Z_STRLEN_PP(arg) > 15) {
    1235                 :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
    1236                 :                                 TRACE_APPEND_STR("...', ");
    1237                 :                                 l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
    1238                 :                         } else {
    1239                 :                                 l_added = Z_STRLEN_PP(arg);
    1240                 :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
    1241                 :                                 TRACE_APPEND_STR("', ");
    1242                 :                                 l_added += 3 + 1;
    1243                 :                         }
    1244                 :                         while (--l_added) {
    1245                 :                                 if ((*str)[*len - l_added] < 32) {
    1246                 :                                         (*str)[*len - l_added] = '?';
    1247                 :                                 }
    1248                 :                         }
    1249                 :                         break;
    1250                 :                 }
    1251                 :                 case IS_BOOL:
    1252                 :                         if (Z_LVAL_PP(arg)) {
    1253                 :                                 TRACE_APPEND_STR("true, ");
    1254                 :                         } else {
    1255                 :                                 TRACE_APPEND_STR("false, ");
    1256                 :                         }
    1257                 :                         break;
    1258                 :                 case IS_RESOURCE:
    1259                 :                         TRACE_APPEND_STR("Resource id #");
    1260                 :                         /* break; */
    1261                 :                 case IS_LONG: {
    1262                 :                         long lval = Z_LVAL_PP(arg);
    1263                 :                         char s_tmp[MAX_LENGTH_OF_LONG + 1];
    1264                 :                         int l_tmp = zend_sprintf(s_tmp, "%ld", lval);  /* SAFE */
    1265                 :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
    1266                 :                         TRACE_APPEND_STR(", ");
    1267                 :                         break;
    1268                 :                 }
    1269                 :                 case IS_DOUBLE: {
    1270                 :                         double dval = Z_DVAL_PP(arg);
    1271                 :                         char *s_tmp;
    1272                 :                         int l_tmp;
    1273                 : 
    1274                 :                         s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
    1275                 :                         l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval);  /* SAFE */
    1276                 :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
    1277                 :                         /* %G already handles removing trailing zeros from the fractional part, yay */
    1278                 :                         efree(s_tmp);
    1279                 :                         TRACE_APPEND_STR(", ");
    1280                 :                         break;
    1281                 :                 }
    1282                 :                 case IS_ARRAY:
    1283                 :                         TRACE_APPEND_STR("Array, ");
    1284                 :                         break;
    1285                 :                 case IS_OBJECT: {
    1286                 :                         char *class_name;
    1287                 :                         zend_uint class_name_len;
    1288                 :                         int dup;
    1289                 : 
    1290                 :                         TRACE_APPEND_STR("Object(");
    1291                 : 
    1292                 :                         dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
    1293                 : 
    1294                 :                         TRACE_APPEND_STRL(class_name, class_name_len);
    1295                 :                         if(!dup) {
    1296                 :                                 efree(class_name);
    1297                 :                         }
    1298                 : 
    1299                 :                         TRACE_APPEND_STR("), ");
    1300                 :                         break;
    1301                 :                 }
    1302                 :                 default:
    1303                 :                         break;
    1304                 :         }
    1305                 :         return ZEND_HASH_APPLY_KEEP;
    1306                 : }
    1307                 : /* }}} */
    1308                 : 
    1309                 : static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
    1310                 : {
    1311                 :         char *s_tmp, **str;
    1312                 :         int *len, *num;
    1313                 :         long line;
    1314                 :         HashTable *ht = Z_ARRVAL_PP(frame);
    1315                 :         zval **file, **tmp;
    1316                 : 
    1317                 :         str = va_arg(args, char**);
    1318                 :         len = va_arg(args, int*);
    1319                 :         num = va_arg(args, int*);
    1320                 : 
    1321                 :         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
    1322                 :         sprintf(s_tmp, "#%d ", (*num)++);
    1323                 :         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
    1324                 :         efree(s_tmp);
    1325                 :         if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
    1326                 :                 if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
    1327                 :                         line = Z_LVAL_PP(tmp);
    1328                 :                 } else {
    1329                 :                         line = 0;
    1330                 :                 }
    1331                 :                 s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
    1332                 :                 sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
    1333                 :                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
    1334                 :                 efree(s_tmp);
    1335                 :         } else {
    1336                 :                 TRACE_APPEND_STR("[internal function]: ");
    1337                 :         }
    1338                 :         TRACE_APPEND_KEY("class");
    1339                 :         TRACE_APPEND_KEY("type");
    1340                 :         TRACE_APPEND_KEY("function");
    1341                 :         TRACE_APPEND_CHR('(');
    1342                 :         if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
    1343                 :                 int last_len = *len;
    1344                 :                 zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
    1345                 :                 if (last_len != *len) {
    1346                 :                         *len -= 2; /* remove last ', ' */
    1347                 :                 }
    1348                 :         }
    1349                 :         TRACE_APPEND_STR(")\n");
    1350                 :         return ZEND_HASH_APPLY_KEEP;
    1351                 : }
    1352                 : /* }}} */
    1353                 : #endif
    1354                 : 
    1355                 : 
    1356                 : char * mysqlnd_get_backtrace(TSRMLS_D)
    1357               0 : {
    1358                 :         zval *trace;
    1359               0 :         char *res = estrdup(""), **str = &res, *s_tmp;
    1360               0 :         int res_len = 0, *len = &res_len, num = 0;
    1361                 : 
    1362               0 :         MAKE_STD_ZVAL(trace);
    1363               0 :         zend_fetch_debug_backtrace(trace, 0, 0 TSRMLS_CC);
    1364                 : 
    1365               0 :         zend_hash_apply_with_arguments(Z_ARRVAL_P(trace) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_string, 3, str, len, &num);
    1366               0 :         zval_ptr_dtor(&trace);
    1367                 : 
    1368               0 :         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
    1369               0 :         sprintf(s_tmp, "#%d {main}", num);
    1370               0 :         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
    1371               0 :         efree(s_tmp);
    1372                 : 
    1373               0 :         res[res_len] = '\0';
    1374                 : 
    1375               0 :         return res;
    1376                 : }
    1377                 : 
    1378                 : /*
    1379                 :  * Local variables:
    1380                 :  * tab-width: 4
    1381                 :  * c-basic-offset: 4
    1382                 :  * End:
    1383                 :  * vim600: noet sw=4 ts=4 fdm=marker
    1384                 :  * vim<600: noet sw=4 ts=4
    1385                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:32 +0000 (36 hours ago)

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