00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifdef HAVE_CONFIG_H
00030 # include <config.h>
00031 #endif
00032
00033 #include "debug_p.h"
00034
00035 #include <stdarg.h>
00036 #include <assert.h>
00037 #include <stdio.h>
00038 #ifdef HAVE_STRINGS_H
00039 # include <strings.h>
00040 #endif
00041 #include <gwenhywfar/misc.h>
00042
00043
00044
00045 static GWEN_MEMORY_DEBUG_OBJECT *gwen_debug__memobjects=0;
00046
00047
00048
00049 uint32_t GWEN_Debug_PrintDec(char *buffer,
00050 uint32_t size,
00051 uint32_t num,
00052 int leadingZero,
00053 uint32_t length) {
00054 uint32_t i;
00055 uint32_t j;
00056 uint32_t k;
00057 char numbuf[16];
00058 int numOr;
00059
00060
00061 numOr=0;
00062 i=0;
00063 j=1000000000;
00064
00065 while(j) {
00066 k=num/j;
00067 numOr|=k;
00068 if (numOr || leadingZero || j==1) {
00069 numbuf[i]=k+'0';
00070 i++;
00071 }
00072 num-=(k*j);
00073 j/=10;
00074 }
00075
00076 j=0;
00077 if (length) {
00078 if (i>length)
00079 i=length;
00080
00081
00082 k=length-i;
00083 while(k) {
00084 if (j<size) {
00085 if (leadingZero)
00086 buffer[j]='0';
00087 else
00088 buffer[j]=' ';
00089 }
00090 j++;
00091 k--;
00092 }
00093 }
00094
00095
00096 for (k=0; k<i; k++) {
00097 if (j<size)
00098 buffer[j]=numbuf[k];
00099 j++;
00100 }
00101
00102
00103 if (j<size)
00104 buffer[j]=0;
00105 j++;
00106
00107 return j;
00108 }
00109
00110
00111
00112 uint32_t GWEN_Debug_PrintHex(char *buffer,
00113 uint32_t size,
00114 uint32_t num,
00115 int leadingZero,
00116 int up,
00117 uint32_t length) {
00118 uint32_t i;
00119 uint32_t j;
00120 uint32_t k;
00121 char numbuf[16];
00122 int numOr;
00123
00124
00125 numOr=0;
00126 i=0;
00127 j=8;
00128
00129 while(j) {
00130 k=(num>>((j-1)*4))&0xf;
00131 numOr|=k;
00132 if (numOr || leadingZero || j==1) {
00133 if (k>9) {
00134 if (up)
00135 numbuf[i]=k+'0'+7;
00136 else
00137 numbuf[i]=k+'0'+7+32;
00138 }
00139 else
00140 numbuf[i]=k+'0';
00141 i++;
00142 }
00143 j--;
00144 }
00145
00146 j=0;
00147 if (length) {
00148 if (i>length)
00149 i=length;
00150
00151
00152 k=length-i;
00153 while(k) {
00154 if (j<size) {
00155 if (leadingZero)
00156 buffer[j]='0';
00157 else
00158 buffer[j]=' ';
00159 }
00160 j++;
00161 k--;
00162 }
00163 }
00164
00165
00166 for (k=0; k<i; k++) {
00167 if (j<size)
00168 buffer[j]=numbuf[k];
00169 j++;
00170 }
00171
00172
00173 if (j<size)
00174 buffer[j]=0;
00175 j++;
00176
00177 return j;
00178 }
00179
00180
00181
00182
00183
00184 uint32_t GWEN_Debug_Snprintf(char *buffer,
00185 uint32_t size,
00186 const char *fmt, ...) {
00187 va_list arguments;
00188 uint32_t i;
00189
00190 i=0;
00191 va_start(arguments, fmt);
00192 while(*fmt) {
00193 if (*fmt=='%') {
00194 fmt++;
00195 if (*fmt=='%') {
00196
00197 if (i<size)
00198 buffer[i]='%';
00199 i++;
00200 }
00201 else {
00202 uint32_t length;
00203 int leadingZero;
00204
00205 leadingZero=0;
00206 length=0;
00207
00208
00209 if ((*fmt)>='0' && (*fmt)<='9') {
00210
00211 if (*fmt=='0') {
00212 leadingZero=1;
00213 }
00214 while ((*fmt)>='0' && (*fmt)<='9') {
00215 length*=10;
00216 length+=*fmt-'0';
00217 fmt++;
00218 }
00219 }
00220
00221
00222 switch(*fmt) {
00223
00224 case 'c':
00225 case 'd': {
00226 int p;
00227
00228 p=va_arg(arguments, int);
00229 if (p<0) {
00230 if (i<size)
00231 buffer[i]='-';
00232 i++;
00233 p=-p;
00234 }
00235 i+=GWEN_Debug_PrintDec(buffer+i,
00236 size-i,
00237 p,
00238 leadingZero,
00239 length)-1;
00240 break;
00241 }
00242
00243
00244 case 'x': {
00245 unsigned int p;
00246
00247 p=va_arg(arguments, unsigned int);
00248 i+=GWEN_Debug_PrintHex(buffer+i,
00249 size-i,
00250 p,
00251 leadingZero,
00252 0,
00253 length)-1;
00254 break;
00255 }
00256
00257
00258 case 'X': {
00259 unsigned int p;
00260
00261 p=va_arg(arguments, unsigned int);
00262 i+=GWEN_Debug_PrintHex(buffer+i,
00263 size-i,
00264 p,
00265 leadingZero,
00266 1,
00267 length)-1;
00268 break;
00269 }
00270
00271 case 's': {
00272 const char *p;
00273
00274 p=va_arg(arguments, const char*);
00275 if (!p)
00276 p="(null)";
00277 while(*p) {
00278 if (i<size)
00279 buffer[i]=*p;
00280 i++;
00281 p++;
00282 }
00283 break;
00284 }
00285
00286 default:
00287 break;
00288 }
00289 }
00290 }
00291 else {
00292 if (i<size)
00293 buffer[i]=*fmt;
00294 i++;
00295 }
00296 fmt++;
00297 }
00298
00299
00300 if (i<size)
00301 buffer[i]=0;
00302 i++;
00303 va_end(arguments);
00304 return i;
00305 }
00306
00307
00308
00309
00310 #ifdef NO_VARIADIC_MACROS
00311 void DBG_ERROR(const char *dbg_logger, const char *format, ...) {
00312 va_list args;
00313 char dbg_buffer[256];
00314 va_start(args, format);
00315 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
00316 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
00317 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelError, dbg_buffer);
00318 va_end(args);
00319 }
00320
00321 void DBG_WARN(const char *dbg_logger, const char *format, ...) {
00322 va_list args;
00323 char dbg_buffer[256];
00324 va_start(args, format);
00325 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
00326 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
00327 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelWarning, dbg_buffer);
00328 va_end(args);
00329 }
00330
00331 void DBG_NOTICE(const char *dbg_logger, const char *format, ...) {
00332 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelNotice) {
00333 va_list args;
00334 char dbg_buffer[256];
00335 va_start(args, format);
00336 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
00337 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
00338 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelNotice, dbg_buffer);
00339 va_end(args);
00340 }
00341 }
00342
00343 void DBG_INFO(const char *dbg_logger, const char *format, ...) {
00344 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelInfo) {
00345 va_list args;
00346 char dbg_buffer[256];
00347 va_start(args, format);
00348 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
00349 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
00350 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelInfo, dbg_buffer);
00351 va_end(args);
00352 }
00353 }
00354
00355 void DBG_DEBUG(const char *dbg_logger, const char *format, ...) {
00356 # ifndef DISABLE_DEBUGLOG
00357 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelDebug) {
00358 va_list args;
00359 char dbg_buffer[256];
00360 va_start(args, format);
00361 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
00362 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
00363 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelDebug, dbg_buffer);
00364 va_end(args);
00365 }
00366 # endif
00367 }
00368
00369 void DBG_VERBOUS(const char *dbg_logger, const char *format, ...) {
00370 # ifndef DISABLE_DEBUGLOG
00371 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelVerbous) {
00372 va_list args;
00373 char dbg_buffer[256];
00374 va_start(args, format);
00375 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
00376 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
00377 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelVerbous, dbg_buffer);
00378 va_end(args);
00379 }
00380 # endif
00381 }
00382
00383 #endif
00384
00385
00386
00387
00388
00389
00390
00391 GWEN_MEMORY_DEBUG_ENTRY*
00392 GWEN_MemoryDebugEntry_new(GWEN_MEMORY_DEBUG_ENTRY_TYPE t,
00393 const char *wFile,
00394 int wLine){
00395 GWEN_MEMORY_DEBUG_ENTRY *e;
00396
00397 assert(wFile);
00398 assert(wLine);
00399 GWEN_NEW_OBJECT(GWEN_MEMORY_DEBUG_ENTRY, e);
00400 e->file=strdup(wFile);
00401 e->line=wLine;
00402 e->type=t;
00403 return e;
00404 }
00405
00406
00407
00408 void GWEN_MemoryDebugEntry_free(GWEN_MEMORY_DEBUG_ENTRY *e){
00409 if (e) {
00410 free(e->file);
00411 GWEN_FREE_OBJECT(e);
00412 }
00413 }
00414
00415
00416
00417
00418 GWEN_MEMORY_DEBUG_OBJECT *GWEN_MemoryDebugObject_new(const char *name){
00419 GWEN_MEMORY_DEBUG_OBJECT *o;
00420
00421 assert(name);
00422 GWEN_NEW_OBJECT(GWEN_MEMORY_DEBUG_OBJECT, o);
00423 o->name=strdup(name);
00424 return o;
00425 }
00426
00427
00428
00429 void GWEN_MemoryDebugObject_free(GWEN_MEMORY_DEBUG_OBJECT *o) {
00430 if (o) {
00431 GWEN_MEMORY_DEBUG_ENTRY *e;
00432
00433 e=o->entries;
00434 while(e) {
00435 GWEN_MEMORY_DEBUG_ENTRY *next;
00436
00437 next=e->next;
00438 GWEN_MemoryDebugEntry_free(e);
00439 e=next;
00440 }
00441 free(o->name);
00442 GWEN_FREE_OBJECT(o);
00443 }
00444 }
00445
00446
00447
00448 GWEN_MEMORY_DEBUG_OBJECT *GWEN_MemoryDebug__FindObject(const char *name){
00449 GWEN_MEMORY_DEBUG_OBJECT *o;
00450
00451 o=gwen_debug__memobjects;
00452 while(o) {
00453 assert(o->name);
00454 if (strcasecmp(o->name, name)==0)
00455 break;
00456 if (o->next==o) {
00457 DBG_ERROR(GWEN_LOGDOMAIN, "What ?? Pointing to myself ??");
00458 abort();
00459 }
00460 o=o->next;
00461 }
00462
00463 return o;
00464 }
00465
00466
00467
00468 void GWEN_MemoryDebug_Increment(const char *name,
00469 const char *wFile,
00470 int wLine,
00471 int attach){
00472 GWEN_MEMORY_DEBUG_OBJECT *o;
00473 GWEN_MEMORY_DEBUG_ENTRY *e;
00474
00475 assert(name);
00476 assert(wFile);
00477 assert(wLine);
00478 o=GWEN_MemoryDebug__FindObject(name);
00479 if (!o) {
00480 o=GWEN_MemoryDebugObject_new(name);
00481 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_OBJECT, o, &gwen_debug__memobjects);
00482 e=GWEN_MemoryDebugEntry_new(attach?GWEN_MemoryDebugEntryTypeAttach:
00483 GWEN_MemoryDebugEntryTypeCreate,
00484 wFile, wLine);
00485 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
00486 o->count++;
00487 }
00488 else {
00489 e=GWEN_MemoryDebugEntry_new(attach?GWEN_MemoryDebugEntryTypeAttach:
00490 GWEN_MemoryDebugEntryTypeCreate,
00491 wFile, wLine);
00492 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
00493 o->count++;
00494 }
00495 }
00496
00497
00498
00499 void GWEN_MemoryDebug_Decrement(const char *name,
00500 const char *wFile,
00501 int wLine){
00502 GWEN_MEMORY_DEBUG_OBJECT *o;
00503 GWEN_MEMORY_DEBUG_ENTRY *e;
00504
00505 assert(name);
00506 assert(wFile);
00507 assert(wLine);
00508 o=GWEN_MemoryDebug__FindObject(name);
00509 if (!o) {
00510 DBG_ERROR(GWEN_LOGDOMAIN,
00511 "Object to be freed not found (%s at %s:%d)",
00512 name, wFile, wLine);
00513 o=GWEN_MemoryDebugObject_new(name);
00514 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_OBJECT, o, &gwen_debug__memobjects);
00515 e=GWEN_MemoryDebugEntry_new(GWEN_MemoryDebugEntryTypeFree,
00516 wFile, wLine);
00517 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
00518 o->count--;
00519 }
00520 else {
00521 e=GWEN_MemoryDebugEntry_new(GWEN_MemoryDebugEntryTypeFree,
00522 wFile, wLine);
00523 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
00524 o->count--;
00525 }
00526 }
00527
00528
00529
00530 void GWEN_MemoryDebug__DumpObject(GWEN_MEMORY_DEBUG_OBJECT *o,
00531 uint32_t mode){
00532
00533 DBG_ERROR(0, "Object \"%s\" (count=%ld)",
00534 o->name, o->count);
00535 if (o->count!=0 || mode==GWEN_MEMORY_DEBUG_MODE_DETAILED) {
00536 GWEN_MEMORY_DEBUG_ENTRY *e;
00537
00538 if (mode!=GWEN_MEMORY_DEBUG_MODE_SHORT) {
00539 e=o->entries;
00540 while(e) {
00541 const char *s;
00542
00543 fprintf(stderr, " ");
00544 switch(e->type) {
00545 case GWEN_MemoryDebugEntryTypeCreate:
00546 s="created";
00547 break;
00548 case GWEN_MemoryDebugEntryTypeAttach:
00549 s="attached";
00550 break;
00551 case GWEN_MemoryDebugEntryTypeFree:
00552 s="freed";
00553 break;
00554 default:
00555 s="<unknown action>";
00556 break;
00557 }
00558 DBG_ERROR(0, " %s at %s:%d", s, e->file, e->line);
00559 e=e->next;
00560 }
00561 }
00562 }
00563 }
00564
00565
00566
00567 void GWEN_MemoryDebug_DumpObject(const char *name,
00568 uint32_t mode){
00569 GWEN_MEMORY_DEBUG_OBJECT *o;
00570
00571 assert(name);
00572 o=GWEN_MemoryDebug__FindObject(name);
00573 if (!o) {
00574 DBG_ERROR(GWEN_LOGDOMAIN, "Object \"%s\" not found", name);
00575 }
00576 else
00577 GWEN_MemoryDebug__DumpObject(o, mode);
00578 }
00579
00580
00581
00582 long int GWEN_MemoryDebug_GetObjectCount(const char *name){
00583 GWEN_MEMORY_DEBUG_OBJECT *o;
00584
00585 assert(name);
00586 o=GWEN_MemoryDebug__FindObject(name);
00587 if (!o) {
00588 DBG_ERROR(GWEN_LOGDOMAIN, "Object \"%s\" not found", name);
00589 return 0;
00590 }
00591 else
00592 return o->count;
00593 }
00594
00595
00596
00597 void GWEN_MemoryDebug_Dump(uint32_t mode){
00598 GWEN_MEMORY_DEBUG_OBJECT *o;
00599
00600 DBG_ERROR(0, "Gwenhywfar Memory Debugger Statistics:");
00601 DBG_ERROR(0, "====================================== begin\n");
00602 o=gwen_debug__memobjects;
00603 while(o) {
00604 GWEN_MemoryDebug__DumpObject(o, mode);
00605 o=o->next;
00606 }
00607 DBG_ERROR(0, "====================================== end\n");
00608 }
00609
00610
00611
00612 void GWEN_MemoryDebug_CleanUp(){
00613 GWEN_MEMORY_DEBUG_OBJECT *o;
00614
00615 o=gwen_debug__memobjects;
00616 while(o) {
00617 GWEN_MEMORY_DEBUG_OBJECT *next;
00618
00619 next=o->next;
00620 GWEN_MemoryDebugObject_free(o);
00621 o=next;
00622 }
00623 gwen_debug__memobjects=0;
00624 }
00625
00626
00627
00628