Diff for /embedaddon/php/ext/mysqlnd/mysqlnd_debug.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 23:47:58 version 1.1.1.2, 2012/05/29 12:34:41
Line 24 Line 24
 #include "mysqlnd.h"  #include "mysqlnd.h"
 #include "mysqlnd_priv.h"  #include "mysqlnd_priv.h"
 #include "mysqlnd_debug.h"  #include "mysqlnd_debug.h"
 #include "mysqlnd_wireprotocol.h"  
 #include "mysqlnd_statistics.h"  
 #include "zend_builtin_functions.h"  
   
 static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace";  static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace";
   
Line 36  static const char * const mysqlnd_debug_default_trace_ Line 33  static const char * const mysqlnd_debug_default_trace_
 #define MYSQLND_ZTS(self)  #define MYSQLND_ZTS(self)
 #endif  #endif
   
 static const char mysqlnd_emalloc_name[]        = "_mysqlnd_emalloc";  
 static const char mysqlnd_pemalloc_name[]       = "_mysqlnd_pemalloc";  
 static const char mysqlnd_ecalloc_name[]        = "_mysqlnd_ecalloc";  
 static const char mysqlnd_pecalloc_name[]       = "_mysqlnd_pecalloc";  
 static const char mysqlnd_erealloc_name[]       = "_mysqlnd_erealloc";  
 static const char mysqlnd_perealloc_name[]      = "_mysqlnd_perealloc";  
 static const char mysqlnd_efree_name[]          = "_mysqlnd_efree";  
 static const char mysqlnd_pefree_name[]         = "_mysqlnd_pefree";  
 static const char mysqlnd_malloc_name[]         = "_mysqlnd_malloc";  
 static const char mysqlnd_calloc_name[]         = "_mysqlnd_calloc";  
 static const char mysqlnd_realloc_name[]        = "_mysqlnd_realloc";  
 static const char mysqlnd_free_name[]           = "_mysqlnd_free";  
 static const char mysqlnd_pestrndup_name[]      = "_mysqlnd_pestrndup";  
 static const char mysqlnd_pestrdup_name[]       = "_mysqlnd_pestrdup";  
   
 const char * mysqlnd_debug_std_no_trace_funcs[] =  
 {  
         mysqlnd_emalloc_name,  
         mysqlnd_ecalloc_name,  
         mysqlnd_efree_name,  
         mysqlnd_erealloc_name,  
         mysqlnd_pemalloc_name,  
         mysqlnd_pecalloc_name,  
         mysqlnd_pefree_name,  
         mysqlnd_perealloc_name,  
         mysqlnd_malloc_name,  
         mysqlnd_calloc_name,  
         mysqlnd_realloc_name,  
         mysqlnd_free_name,  
         mysqlnd_pestrndup_name,  
         mysqlnd_read_header_name,  
         mysqlnd_read_body_name,  
         NULL /* must be always last */  
 };  
   
   
 /* {{{ mysqlnd_debug::open */  /* {{{ mysqlnd_debug::open */
 static enum_func_status  static enum_func_status
 MYSQLND_METHOD(mysqlnd_debug, open)(MYSQLND_DEBUG * self, zend_bool reopen)  MYSQLND_METHOD(mysqlnd_debug, open)(MYSQLND_DEBUG * self, zend_bool reopen)
Line 167  MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * sel Line 129  MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * sel
                 level_buffer[sizeof(level_buffer) - 1 ] = '\0';                  level_buffer[sizeof(level_buffer) - 1 ] = '\0';
         }          }
   
        message_line_len = spprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",        message_line_len = mnd_sprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
                                                                 flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",                                                                  flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
                                                                 flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",                                                                  flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
                                                                 flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",                                                                  flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",
Line 176  MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * sel Line 138  MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * sel
                                                                 pipe_buffer, type? type:"", message);                                                                  pipe_buffer, type? type:"", message);
   
         ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;          ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
        efree(message_line); /* allocated by spprintf */        mnd_sprintf_free(message_line);
         if (flags & MYSQLND_DEBUG_FLUSH) {          if (flags & MYSQLND_DEBUG_FLUSH) {
                 self->m->close(self);                  self->m->close(self);
                 self->m->open(self, TRUE);                  self->m->open(self, TRUE);
Line 265  MYSQLND_METHOD(mysqlnd_debug, log_va)(MYSQLND_DEBUG *s Line 227  MYSQLND_METHOD(mysqlnd_debug, log_va)(MYSQLND_DEBUG *s
                 level_buffer[sizeof(level_buffer) - 1 ] = '\0';                  level_buffer[sizeof(level_buffer) - 1 ] = '\0';
         }          }
   
   
         va_start(args, format);          va_start(args, format);
        vspprintf(&buffer, 0, format, args);        mnd_vsprintf(&buffer, 0, format, args);
         va_end(args);          va_end(args);
   
        message_line_len = spprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",        message_line_len = mnd_sprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
                                                                 flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",                                                                  flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
                                                                 flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",                                                                  flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
                                                                 flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",                                                                  flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",
                                                                 flags & MYSQLND_DEBUG_DUMP_LINE? line_buffer:"",                                                                  flags & MYSQLND_DEBUG_DUMP_LINE? line_buffer:"",
                                                                 flags & MYSQLND_DEBUG_DUMP_LEVEL? level_buffer:"",                                                                  flags & MYSQLND_DEBUG_DUMP_LEVEL? level_buffer:"",
                                                                 pipe_buffer, type? type:"", buffer);                                                                  pipe_buffer, type? type:"", buffer);
        efree(buffer);        mnd_sprintf_free(buffer);
         ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;          ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
        efree(message_line); /* allocated by spprintf */        mnd_sprintf_free(message_line);
   
         if (flags & MYSQLND_DEBUG_FLUSH) {          if (flags & MYSQLND_DEBUG_FLUSH) {
                 self->m->close(self);                  self->m->close(self);
Line 538  MYSQLND_METHOD(mysqlnd_debug, free)(MYSQLND_DEBUG * se Line 499  MYSQLND_METHOD(mysqlnd_debug, free)(MYSQLND_DEBUG * se
         zend_stack_destroy(&self->call_time_stack);          zend_stack_destroy(&self->call_time_stack);
         zend_hash_destroy(&self->not_filtered_functions);          zend_hash_destroy(&self->not_filtered_functions);
         zend_hash_destroy(&self->function_profiles);          zend_hash_destroy(&self->function_profiles);
        efree(self);        free(self);
         return PASS;          return PASS;
 }  }
 /* }}} */  /* }}} */
Line 761  MYSQLND_CLASS_METHODS_END; Line 722  MYSQLND_CLASS_METHODS_END;
 PHPAPI MYSQLND_DEBUG *  PHPAPI MYSQLND_DEBUG *
 mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC)  mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC)
 {  {
        MYSQLND_DEBUG *ret = ecalloc(1, sizeof(MYSQLND_DEBUG));        MYSQLND_DEBUG *ret = calloc(1, sizeof(MYSQLND_DEBUG));
 #ifdef ZTS  #ifdef ZTS
         ret->TSRMLS_C = TSRMLS_C;          ret->TSRMLS_C = TSRMLS_C;
 #endif  #endif
Line 783  mysqlnd_debug_init(const char * skip_functions[] TSRML Line 744  mysqlnd_debug_init(const char * skip_functions[] TSRML
 /* {{{ _mysqlnd_debug */  /* {{{ _mysqlnd_debug */
 PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC)  PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC)
 {  {
#ifdef PHP_DEBUG#if PHP_DEBUG
         MYSQLND_DEBUG *dbg = MYSQLND_G(dbg);          MYSQLND_DEBUG *dbg = MYSQLND_G(dbg);
         if (!dbg) {          if (!dbg) {
                 MYSQLND_G(dbg) = dbg = mysqlnd_debug_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);                  MYSQLND_G(dbg) = dbg = mysqlnd_debug_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);
Line 805  PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC Line 766  PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC
 /* }}} */  /* }}} */
   
   
#if ZEND_DEBUGstatic struct st_mysqlnd_plugin_trace_log mysqlnd_plugin_trace_log_plugin =
#else 
#define __zend_filename "/unknown/unknown" 
#define __zend_lineno   0 
#endif 
 
#define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s)) 
#define REAL_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) - sizeof(size_t)) : (p)) 
#define FAKE_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) + sizeof(size_t)) : (p)) 
 
/* {{{ _mysqlnd_emalloc */ 
void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D) 
 {  {
         void *ret;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         long * threshold = &MYSQLND_G(debug_emalloc_fail_threshold);  
         DBG_ENTER(mysqlnd_emalloc_name);  
   
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
   
 #ifdef PHP_DEBUG  
         /* -1 is also "true" */  
         if (*threshold) {  
 #endif  
                 ret = emalloc(REAL_SIZE(size));  
 #ifdef PHP_DEBUG  
                 --*threshold;  
         } else if (*threshold == 0) {  
                 ret = NULL;  
         }  
 #endif  
   
         DBG_INF_FMT("size=%lu ptr=%p", size, ret);  
   
         if (ret && collect_memory_statistics) {  
                 *(size_t *) ret = size;  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);  
         }  
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_pemalloc */  
 void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)  
 {  
         void *ret;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         long * threshold = persistent? &MYSQLND_G(debug_malloc_fail_threshold):&MYSQLND_G(debug_emalloc_fail_threshold);  
         DBG_ENTER(mysqlnd_pemalloc_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
   
 #ifdef PHP_DEBUG  
         /* -1 is also "true" */  
         if (*threshold) {  
 #endif  
                 ret = pemalloc(REAL_SIZE(size), persistent);  
 #ifdef PHP_DEBUG  
                 --*threshold;  
         } else if (*threshold == 0) {  
                 ret = NULL;  
         }  
 #endif  
   
         DBG_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent);  
   
         if (ret && collect_memory_statistics) {  
                 enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT;  
                 enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_MALLOC_AMOUNT:STAT_MEM_EMALLOC_AMOUNT;  
                 *(size_t *) ret = size;  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);  
         }  
   
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_ecalloc */  
 void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)  
 {  
         void *ret;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         long * threshold = &MYSQLND_G(debug_ecalloc_fail_threshold);  
         DBG_ENTER(mysqlnd_ecalloc_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
         DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));  
   
 #ifdef PHP_DEBUG  
         /* -1 is also "true" */  
         if (*threshold) {  
 #endif  
                 ret = ecalloc(nmemb, REAL_SIZE(size));  
 #ifdef PHP_DEBUG  
                 --*threshold;  
         } else if (*threshold == 0) {  
                 ret = NULL;  
         }  
 #endif  
   
         DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));  
         DBG_INF_FMT("size=%lu ptr=%p", size, ret);  
         if (ret && collect_memory_statistics) {  
                 *(size_t *) ret = size;  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMOUNT, size);  
         }  
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_pecalloc */  
 void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)  
 {  
         void *ret;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         long * threshold = persistent? &MYSQLND_G(debug_calloc_fail_threshold):&MYSQLND_G(debug_ecalloc_fail_threshold);  
         DBG_ENTER(mysqlnd_pecalloc_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
   
 #ifdef PHP_DEBUG  
         /* -1 is also "true" */  
         if (*threshold) {  
 #endif  
                 ret = pecalloc(nmemb, REAL_SIZE(size), persistent);  
 #ifdef PHP_DEBUG  
                 --*threshold;  
         } else if (*threshold == 0) {  
                 ret = NULL;  
         }  
 #endif  
   
         DBG_INF_FMT("size=%lu ptr=%p", size, ret);  
   
         if (ret && collect_memory_statistics) {  
                 enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT;  
                 enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_CALLOC_AMOUNT:STAT_MEM_ECALLOC_AMOUNT;  
                 *(size_t *) ret = size;  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);  
         }  
   
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_erealloc */  
 void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)  
 {  
         void *ret;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;  
         long * threshold = &MYSQLND_G(debug_erealloc_fail_threshold);  
         DBG_ENTER(mysqlnd_erealloc_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
         DBG_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size);   
   
 #ifdef PHP_DEBUG  
         /* -1 is also "true" */  
         if (*threshold) {  
 #endif  
                 ret = erealloc(REAL_PTR(ptr), REAL_SIZE(new_size));  
 #ifdef PHP_DEBUG  
                 --*threshold;  
         } else if (*threshold == 0) {  
                 ret = NULL;  
         }  
 #endif  
   
         DBG_INF_FMT("new_ptr=%p", (char*)ret);  
         if (ret && collect_memory_statistics) {  
                 *(size_t *) ret = new_size;  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMOUNT, new_size);  
         }  
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_perealloc */  
 void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)  
 {  
         void *ret;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;  
         long * threshold = persistent? &MYSQLND_G(debug_realloc_fail_threshold):&MYSQLND_G(debug_erealloc_fail_threshold);  
         DBG_ENTER(mysqlnd_perealloc_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
         DBG_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent);   
   
 #ifdef PHP_DEBUG  
         /* -1 is also "true" */  
         if (*threshold) {  
 #endif  
                 ret = perealloc(REAL_PTR(ptr), REAL_SIZE(new_size), persistent);  
 #ifdef PHP_DEBUG  
                 --*threshold;  
         } else if (*threshold == 0) {  
                 ret = NULL;  
         }  
 #endif  
   
         DBG_INF_FMT("new_ptr=%p", (char*)ret);  
   
         if (ret && collect_memory_statistics) {  
                 enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;  
                 enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_REALLOC_AMOUNT:STAT_MEM_EREALLOC_AMOUNT;  
                 *(size_t *) ret = new_size;  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size);  
         }  
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_efree */  
 void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)  
 {  
         size_t free_amount = 0;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         DBG_ENTER(mysqlnd_efree_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
         DBG_INF_FMT("ptr=%p", ptr);   
   
         if (ptr) {  
                 if (collect_memory_statistics) {  
                         free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));  
                         DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);  
                 }  
                 efree(REAL_PTR(ptr));  
         }  
   
         if (collect_memory_statistics) {  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EFREE_COUNT, 1, STAT_MEM_EFREE_AMOUNT, free_amount);  
         }  
         DBG_VOID_RETURN;  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_pefree */  
 void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D)  
 {  
         size_t free_amount = 0;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         DBG_ENTER(mysqlnd_pefree_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
         DBG_INF_FMT("ptr=%p persistent=%u", ptr, persistent);   
   
         if (ptr) {  
                 if (collect_memory_statistics) {  
                         free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));  
                         DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);  
                 }  
                 pefree(REAL_PTR(ptr), persistent);  
         }  
   
         if (collect_memory_statistics) {  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT, 1,  
                                                                                           persistent? STAT_MEM_FREE_AMOUNT:STAT_MEM_EFREE_AMOUNT, free_amount);  
         }  
         DBG_VOID_RETURN;  
 }  
   
   
 /* {{{ _mysqlnd_malloc */  
 void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)  
 {  
         void *ret;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         long * threshold = &MYSQLND_G(debug_malloc_fail_threshold);  
         DBG_ENTER(mysqlnd_malloc_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
   
 #ifdef PHP_DEBUG  
         /* -1 is also "true" */  
         if (*threshold) {  
 #endif  
                 ret = malloc(REAL_SIZE(size));  
 #ifdef PHP_DEBUG  
                 --*threshold;  
         } else if (*threshold == 0) {  
                 ret = NULL;  
         }  
 #endif  
   
         DBG_INF_FMT("size=%lu ptr=%p", size, ret);  
         if (ret && collect_memory_statistics) {  
                 *(size_t *) ret = size;  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMOUNT, size);  
         }  
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_calloc */  
 void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)  
 {  
         void *ret;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         long * threshold = &MYSQLND_G(debug_calloc_fail_threshold);  
         DBG_ENTER(mysqlnd_calloc_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
   
 #ifdef PHP_DEBUG  
         /* -1 is also "true" */  
         if (*threshold) {  
 #endif  
                 ret = calloc(nmemb, REAL_SIZE(size));  
 #ifdef PHP_DEBUG  
                 --*threshold;  
         } else if (*threshold == 0) {  
                 ret = NULL;  
         }  
 #endif  
   
         DBG_INF_FMT("size=%lu ptr=%p", size, ret);  
         if (ret && collect_memory_statistics) {  
                 *(size_t *) ret = size;  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMOUNT, size);  
         }  
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_realloc */  
 void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)  
 {  
         void *ret;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         long * threshold = &MYSQLND_G(debug_realloc_fail_threshold);  
         DBG_ENTER(mysqlnd_realloc_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
         DBG_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr);   
         DBG_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC));  
   
 #ifdef PHP_DEBUG  
         /* -1 is also "true" */  
         if (*threshold) {  
 #endif  
                 ret = realloc(REAL_PTR(ptr), REAL_SIZE(new_size));  
 #ifdef PHP_DEBUG  
                 --*threshold;  
         } else if (*threshold == 0) {  
                 ret = NULL;  
         }  
 #endif  
   
         DBG_INF_FMT("new_ptr=%p", (char*)ret);  
   
         if (ret && collect_memory_statistics) {  
                 *(size_t *) ret = new_size;  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMOUNT, new_size);  
         }  
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_free */  
 void _mysqlnd_free(void *ptr MYSQLND_MEM_D)  
 {  
         size_t free_amount = 0;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         DBG_ENTER(mysqlnd_free_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
         DBG_INF_FMT("ptr=%p", ptr);   
   
         if (ptr) {  
                 if (collect_memory_statistics) {  
                         free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));  
                         DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);  
                 }  
                 free(REAL_PTR(ptr));  
         }  
   
         if (collect_memory_statistics) {  
                 MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_FREE_COUNT, 1, STAT_MEM_FREE_AMOUNT, free_amount);  
         }  
         DBG_VOID_RETURN;  
 }  
 /* }}} */  
   
 #define SMART_STR_START_SIZE 2048  
 #define SMART_STR_PREALLOC 512  
 #include "ext/standard/php_smart_str.h"  
   
   
 /* {{{ _mysqlnd_pestrndup */  
 char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)  
 {  
         char * ret;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         DBG_ENTER(mysqlnd_pestrndup_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
         DBG_INF_FMT("ptr=%p", ptr);   
   
         ret = pemalloc(REAL_SIZE(length) + 1, persistent);  
         {          {
                size_t l = length;                MYSQLND_PLUGIN_API_VERSION,
                char * p = (char *) ptr;                "debug_trace",
                char * dest = (char *) FAKE_PTR(ret);                MYSQLND_VERSION_ID,
                while (*p && l--) {                MYSQLND_VERSION,
                        *dest++ = *p++;                "PHP License 3.01",
                 "Andrey Hristov <andrey@mysql.com>,  Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
                 {
                         NULL, /* no statistics , will be filled later if there are some */
                         NULL, /* no statistics */
                 },
                 {
                         NULL /* plugin shutdown */
                 }                  }
                *dest = '\0';        },
         {/* methods */
                 mysqlnd_debug_init,
                 mysqlnd_get_backtrace
         }          }
   
         if (collect_memory_statistics) {  
                 *(size_t *) ret = length;  
                 MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRNDUP_COUNT : STAT_MEM_ESTRNDUP_COUNT);  
         }  
   
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
   
 /* {{{ _mysqlnd_pestrdup */  
 char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)  
 {  
         char * ret;  
         smart_str tmp_str = {0, 0, 0};  
         const char * p = ptr;  
         zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);  
         DBG_ENTER(mysqlnd_pestrdup_name);  
         DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);  
         DBG_INF_FMT("ptr=%p", ptr);  
         do {  
                 smart_str_appendc(&tmp_str, *p);  
         } while (*p++);  
   
         ret = pemalloc(tmp_str.len + sizeof(size_t), persistent);  
         memcpy(FAKE_PTR(ret), tmp_str.c, tmp_str.len);  
   
         if (ret && collect_memory_statistics) {  
                 *(size_t *) ret = tmp_str.len;  
                 MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRDUP_COUNT : STAT_MEM_ESTRDUP_COUNT);  
         }  
         smart_str_free(&tmp_str);  
   
         DBG_RETURN(FAKE_PTR(ret));  
 }  
 /* }}} */  
   
 #define MYSQLND_DEBUG_MEMORY 1  
   
 #if MYSQLND_DEBUG_MEMORY == 0  
   
 /* {{{ mysqlnd_zend_mm_emalloc */  
 static void * mysqlnd_zend_mm_emalloc(size_t size MYSQLND_MEM_D)  
 {  
         return emalloc(size);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_pemalloc */  
 static void * mysqlnd_zend_mm_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)  
 {  
         return pemalloc(size, persistent);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_ecalloc */  
 static void * mysqlnd_zend_mm_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)  
 {  
         return ecalloc(nmemb, size);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_pecalloc */  
 static void * mysqlnd_zend_mm_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)  
 {  
         return pecalloc(nmemb, size, persistent);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_erealloc */  
 static void * mysqlnd_zend_mm_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)  
 {  
         return erealloc(ptr, new_size);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_perealloc */  
 static void * mysqlnd_zend_mm_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)  
 {  
         return perealloc(ptr, new_size, persistent);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_efree */  
 static void mysqlnd_zend_mm_efree(void * ptr MYSQLND_MEM_D)  
 {  
         efree(ptr);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_pefree */  
 static void mysqlnd_zend_mm_pefree(void * ptr, zend_bool persistent MYSQLND_MEM_D)  
 {  
         pefree(ptr, persistent);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_malloc */  
 static void * mysqlnd_zend_mm_malloc(size_t size MYSQLND_MEM_D)  
 {  
         return malloc(size);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_calloc */  
 static void * mysqlnd_zend_mm_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)  
 {  
         return calloc(nmemb, size);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_realloc */  
 static void * mysqlnd_zend_mm_realloc(void * ptr, size_t new_size MYSQLND_MEM_D)  
 {  
         return realloc(ptr, new_size);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_free */  
 static void mysqlnd_zend_mm_free(void * ptr MYSQLND_MEM_D)  
 {  
         free(ptr);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_pestrndup */  
 static char * mysqlnd_zend_mm_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)  
 {  
         return pestrndup(ptr, length, persistent);  
 }  
 /* }}} */  
   
   
 /* {{{ mysqlnd_zend_mm_pestrdup */  
 static char * mysqlnd_zend_mm_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)  
 {  
         return pestrdup(ptr, persistent);  
 }  
 /* }}} */  
   
 #endif  
   
   
 PHPAPI struct st_mysqlnd_allocator_methods mysqlnd_allocator =   
 {  
 #if MYSQLND_DEBUG_MEMORY  
         _mysqlnd_emalloc,  
         _mysqlnd_pemalloc,  
         _mysqlnd_ecalloc,  
         _mysqlnd_pecalloc,  
         _mysqlnd_erealloc,  
         _mysqlnd_perealloc,  
         _mysqlnd_efree,  
         _mysqlnd_pefree,  
         _mysqlnd_malloc,  
         _mysqlnd_calloc,  
         _mysqlnd_realloc,  
         _mysqlnd_free,  
         _mysqlnd_pestrndup,  
         _mysqlnd_pestrdup  
 #else  
         mysqlnd_zend_mm_emalloc,  
         mysqlnd_zend_mm_pemalloc,  
         mysqlnd_zend_mm_ecalloc,  
         mysqlnd_zend_mm_pecalloc,  
         mysqlnd_zend_mm_erealloc,  
         mysqlnd_zend_mm_perealloc,  
         mysqlnd_zend_mm_efree,  
         mysqlnd_zend_mm_pefree,  
         mysqlnd_zend_mm_malloc,  
         mysqlnd_zend_mm_calloc,  
         mysqlnd_zend_mm_realloc,  
         mysqlnd_zend_mm_free,  
         mysqlnd_zend_mm_pestrndup,  
         mysqlnd_zend_mm_pestrdup  
 #endif  
 };  };
   
   
/* {{{ mysqlnd_debug_trace_plugin_register */
/* Follows code borrowed from zend_builtin_functions.c because the functions there are static */void
mysqlnd_debug_trace_plugin_register(TSRMLS_D)
#if MYSQLND_UNICODE 
/* {{{ gettraceasstring() macros */ 
#define TRACE_APPEND_CHR(chr)                                            \ 
        *str = (char*)erealloc(*str, *len + 1 + 1);                          \ 
        (*str)[(*len)++] = chr 
 
#define TRACE_APPEND_STRL(val, vallen)                                   \ 
        {                                                                    \ 
                int l = vallen;                                                  \ 
                *str = (char*)erealloc(*str, *len + l + 1);                      \ 
                memcpy((*str) + *len, val, l);                                   \ 
                *len += l;                                                       \ 
        } 
 
#define TRACE_APPEND_USTRL(val, vallen) \ 
        { \ 
                zval tmp, copy; \ 
                int use_copy; \ 
                ZVAL_UNICODEL(&tmp, val, vallen, 1); \ 
                zend_make_printable_zval(&tmp, &copy, &use_copy); \ 
                TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \ 
                zval_dtor(&copy); \ 
                zval_dtor(&tmp); \ 
        } 
 
#define TRACE_APPEND_ZVAL(zv) \ 
        if (Z_TYPE_P((zv)) == IS_UNICODE) { \ 
                zval copy; \ 
                int use_copy; \ 
                zend_make_printable_zval((zv), &copy, &use_copy); \ 
                TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \ 
                zval_dtor(&copy); \ 
        } else { \ 
                TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \ 
        } 
 
#define TRACE_APPEND_STR(val)                                            \ 
        TRACE_APPEND_STRL(val, sizeof(val)-1) 
 
#define TRACE_APPEND_KEY(key)                                            \ 
        if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \ 
                if (Z_TYPE_PP(tmp) == IS_UNICODE) { \ 
                        zval copy; \ 
                        int use_copy; \ 
                        zend_make_printable_zval(*tmp, &copy, &use_copy); \ 
                        TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \ 
                        zval_dtor(&copy); \ 
                } else { \ 
                TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \ 
                } \ 
        } 
/* }}} */ 
 
/* {{{ mysqlnd_build_trace_args */ 
static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) 
 {  {
        char **str;        mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_plugin_trace_log_plugin TSRMLS_CC);
        int *len; 
 
        str = va_arg(args, char**); 
        len = va_arg(args, int*); 
 
        /* the trivial way would be to do: 
         * conver_to_string_ex(arg); 
         * append it and kill the now tmp arg. 
         * but that could cause some E_NOTICE and also damn long lines. 
         */ 
 
        switch (Z_TYPE_PP(arg)) { 
                case IS_NULL: 
                        TRACE_APPEND_STR("NULL, "); 
                        break; 
                case IS_STRING: { 
                        int l_added; 
                        TRACE_APPEND_CHR('\''); 
                        if (Z_STRLEN_PP(arg) > 15) { 
                                TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15); 
                                TRACE_APPEND_STR("...', "); 
                                l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */ 
                        } else { 
                                l_added = Z_STRLEN_PP(arg); 
                                TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added); 
                                TRACE_APPEND_STR("', "); 
                                l_added += 3 + 1; 
                        } 
                        while (--l_added) { 
                                if ((unsigned char)(*str)[*len - l_added] < 32) { 
                                        (*str)[*len - l_added] = '?'; 
                                } 
                        } 
                        break; 
                } 
                case IS_UNICODE: { 
                        int l_added; 
 
                        /* 
                         * We do not want to apply current error mode here, since 
                         * zend_make_printable_zval() uses output encoding converter. 
                         * Temporarily set output encoding converter to escape offending 
                         * chars with \uXXXX notation. 
                         */ 
                        zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, ZEND_CONV_ERROR_ESCAPE_JAVA); 
                        TRACE_APPEND_CHR('\''); 
                        if (Z_USTRLEN_PP(arg) > 15) { 
                                TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), 15); 
                                TRACE_APPEND_STR("...', "); 
                                l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */ 
                        } else { 
                                l_added = Z_USTRLEN_PP(arg); 
                                TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), l_added); 
                                TRACE_APPEND_STR("', "); 
                                l_added += 3 + 1; 
                        } 
                        /* 
                         * Reset output encoding converter error mode. 
                         */ 
                        zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, UG(from_error_mode)); 
                        while (--l_added) { 
                                if ((unsigned char)(*str)[*len - l_added] < 32) { 
                                        (*str)[*len - l_added] = '?'; 
                                } 
                        } 
                        break; 
                } 
                case IS_BOOL: 
                        if (Z_LVAL_PP(arg)) { 
                                TRACE_APPEND_STR("true, "); 
                        } else { 
                                TRACE_APPEND_STR("false, "); 
                        } 
                        break; 
                case IS_RESOURCE: 
                        TRACE_APPEND_STR("Resource id #"); 
                        /* break; */ 
                case IS_LONG: { 
                        long lval = Z_LVAL_PP(arg); 
                        char s_tmp[MAX_LENGTH_OF_LONG + 1]; 
                        int l_tmp = zend_sprintf(s_tmp, "%ld", lval);  /* SAFE */ 
                        TRACE_APPEND_STRL(s_tmp, l_tmp); 
                        TRACE_APPEND_STR(", "); 
                        break; 
                } 
                case IS_DOUBLE: { 
                        double dval = Z_DVAL_PP(arg); 
                        char *s_tmp; 
                        int l_tmp; 
 
                        s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1); 
                        l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval);  /* SAFE */ 
                        TRACE_APPEND_STRL(s_tmp, l_tmp); 
                        /* %G already handles removing trailing zeros from the fractional part, yay */ 
                        efree(s_tmp); 
                        TRACE_APPEND_STR(", "); 
                        break; 
                } 
                case IS_ARRAY: 
                        TRACE_APPEND_STR("Array, "); 
                        break; 
                case IS_OBJECT: { 
                        zval tmp; 
                        zstr class_name; 
                        zend_uint class_name_len; 
                        int dup; 
 
                        TRACE_APPEND_STR("Object("); 
 
                        dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC); 
 
                        ZVAL_UNICODEL(&tmp, class_name.u, class_name_len, 1); 
                        convert_to_string_with_converter(&tmp, ZEND_U_CONVERTER(UG(output_encoding_conv))); 
                        TRACE_APPEND_STRL(Z_STRVAL(tmp), Z_STRLEN(tmp)); 
                        zval_dtor(&tmp); 
 
                        if(!dup) { 
                                efree(class_name.v); 
                        } 
 
                        TRACE_APPEND_STR("), "); 
                        break; 
                } 
                default: 
                        break; 
        } 
        return ZEND_HASH_APPLY_KEEP; 
 }  }
 /* }}} */  /* }}} */
   
   
 static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */  
 {  
         char *s_tmp, **str;  
         int *len, *num;  
         long line;  
         HashTable *ht = Z_ARRVAL_PP(frame);  
         zval **file, **tmp;  
         uint * level;  
   
         level = va_arg(args, uint *);  
         str = va_arg(args, char**);  
         len = va_arg(args, int*);  
         num = va_arg(args, int*);  
   
         if (!*level) {  
                 return ZEND_HASH_APPLY_KEEP;  
         }  
         --*level;  
   
         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);  
         sprintf(s_tmp, "#%d ", (*num)++);  
         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));  
         efree(s_tmp);  
         if (zend_ascii_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {  
                 if (zend_ascii_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {  
                         line = Z_LVAL_PP(tmp);  
                 } else {  
                         line = 0;  
                 }  
                 TRACE_APPEND_ZVAL(*file);  
                 s_tmp = emalloc(MAX_LENGTH_OF_LONG + 2 + 1);  
                 sprintf(s_tmp, "(%ld): ", line);  
                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));  
                 efree(s_tmp);  
         } else {  
                 TRACE_APPEND_STR("[internal function]: ");  
         }  
         TRACE_APPEND_KEY("class");  
         TRACE_APPEND_KEY("type");  
         TRACE_APPEND_KEY("function");  
         TRACE_APPEND_CHR('(');  
         if (zend_ascii_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {  
                 int last_len = *len;  
                 zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);  
                 if (last_len != *len) {  
                         *len -= 2; /* remove last ', ' */  
                 }  
         }  
         TRACE_APPEND_STR(")\n");  
         return ZEND_HASH_APPLY_KEEP;  
 }  
 /* }}} */  
   
   
 #else /* PHP 5*/  
   
   
 /* {{{ gettraceasstring() macros */  
 #define TRACE_APPEND_CHR(chr)                                            \  
         *str = (char*)erealloc(*str, *len + 1 + 1);                          \  
         (*str)[(*len)++] = chr  
   
 #define TRACE_APPEND_STRL(val, vallen)                                   \  
         {                                                                    \  
                 int l = vallen;                                                  \  
                 *str = (char*)erealloc(*str, *len + l + 1);                      \  
                 memcpy((*str) + *len, val, l);                                   \  
                 *len += l;                                                       \  
         }  
   
 #define TRACE_APPEND_STR(val)                                            \  
         TRACE_APPEND_STRL(val, sizeof(val)-1)  
   
 #define TRACE_APPEND_KEY(key)                                            \  
         if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \  
             TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \  
         }  
   
 /* }}} */  
   
   
 static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */  
 {  
         char **str;  
         int *len;  
   
         str = va_arg(args, char**);  
         len = va_arg(args, int*);  
   
         /* the trivial way would be to do:  
          * conver_to_string_ex(arg);  
          * append it and kill the now tmp arg.  
          * but that could cause some E_NOTICE and also damn long lines.  
          */  
   
         switch (Z_TYPE_PP(arg)) {  
                 case IS_NULL:  
                         TRACE_APPEND_STR("NULL, ");  
                         break;  
                 case IS_STRING: {  
                         int l_added;  
                         TRACE_APPEND_CHR('\'');  
                         if (Z_STRLEN_PP(arg) > 15) {  
                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);  
                                 TRACE_APPEND_STR("...', ");  
                                 l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */  
                         } else {  
                                 l_added = Z_STRLEN_PP(arg);  
                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);  
                                 TRACE_APPEND_STR("', ");  
                                 l_added += 3 + 1;  
                         }  
                         while (--l_added) {  
                                 if ((*str)[*len - l_added] < 32) {  
                                         (*str)[*len - l_added] = '?';  
                                 }  
                         }  
                         break;  
                 }  
                 case IS_BOOL:  
                         if (Z_LVAL_PP(arg)) {  
                                 TRACE_APPEND_STR("true, ");  
                         } else {  
                                 TRACE_APPEND_STR("false, ");  
                         }  
                         break;  
                 case IS_RESOURCE:  
                         TRACE_APPEND_STR("Resource id #");  
                         /* break; */  
                 case IS_LONG: {  
                         long lval = Z_LVAL_PP(arg);  
                         char s_tmp[MAX_LENGTH_OF_LONG + 1];  
                         int l_tmp = zend_sprintf(s_tmp, "%ld", lval);  /* SAFE */  
                         TRACE_APPEND_STRL(s_tmp, l_tmp);  
                         TRACE_APPEND_STR(", ");  
                         break;  
                 }  
                 case IS_DOUBLE: {  
                         double dval = Z_DVAL_PP(arg);  
                         char *s_tmp;  
                         int l_tmp;  
   
                         s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);  
                         l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval);  /* SAFE */  
                         TRACE_APPEND_STRL(s_tmp, l_tmp);  
                         /* %G already handles removing trailing zeros from the fractional part, yay */  
                         efree(s_tmp);  
                         TRACE_APPEND_STR(", ");  
                         break;  
                 }  
                 case IS_ARRAY:  
                         TRACE_APPEND_STR("Array, ");  
                         break;  
                 case IS_OBJECT: {  
                         char *class_name;  
                         zend_uint class_name_len;  
                         int dupl;  
   
                         TRACE_APPEND_STR("Object(");  
   
                         dupl = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);  
   
                         TRACE_APPEND_STRL(class_name, class_name_len);  
                         if (!dupl) {  
                                 efree(class_name);  
                         }  
   
                         TRACE_APPEND_STR("), ");  
                         break;  
                 }  
                 default:  
                         break;  
         }  
         return ZEND_HASH_APPLY_KEEP;  
 }  
 /* }}} */  
   
 static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */  
 {  
         char *s_tmp, **str;  
         int *len, *num;  
         long line;  
         HashTable *ht = Z_ARRVAL_PP(frame);  
         zval **file, **tmp;  
         uint * level;  
   
         level = va_arg(args, uint *);  
         str = va_arg(args, char**);  
         len = va_arg(args, int*);  
         num = va_arg(args, int*);  
   
         if (!*level) {  
                 return ZEND_HASH_APPLY_KEEP;  
         }  
         --*level;  
   
         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);  
         sprintf(s_tmp, "#%d ", (*num)++);  
         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));  
         efree(s_tmp);  
         if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {  
                 if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {  
                         line = Z_LVAL_PP(tmp);  
                 } else {  
                         line = 0;  
                 }  
                 s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);  
                 sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);  
                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));  
                 efree(s_tmp);  
         } else {  
                 TRACE_APPEND_STR("[internal function]: ");  
         }  
         TRACE_APPEND_KEY("class");  
         TRACE_APPEND_KEY("type");  
         TRACE_APPEND_KEY("function");  
         TRACE_APPEND_CHR('(');  
         if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {  
                 int last_len = *len;  
                 zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);  
                 if (last_len != *len) {  
                         *len -= 2; /* remove last ', ' */  
                 }  
         }  
         TRACE_APPEND_STR(")\n");  
         return ZEND_HASH_APPLY_KEEP;  
 }  
 /* }}} */  
 #endif  
   
   
 PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC)  
 {  
         zval *trace;  
         char *res = estrdup(""), **str = &res, *s_tmp;  
         int res_len = 0, *len = &res_len, num = 0;  
         if (max_levels == 0) {  
                 max_levels = 99999;  
         }  
   
         MAKE_STD_ZVAL(trace);  
         zend_fetch_debug_backtrace(trace, 0, 0 TSRMLS_CC);  
   
         zend_hash_apply_with_arguments(Z_ARRVAL_P(trace) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_string, 4, &max_levels, str, len, &num);  
         zval_ptr_dtor(&trace);  
   
         if (max_levels) {  
                 s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);  
                 sprintf(s_tmp, "#%d {main}", num);  
                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));  
                 efree(s_tmp);  
         }  
   
         res[res_len] = '\0';  
         *length = res_len;  
   
         return res;  
 }  
   
 /*  /*
  * Local variables:   * Local variables:

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>