gwenhywfar
4.3.1
|
00001 /*************************************************************************** 00002 $RCSfile$ 00003 ------------------- 00004 cvs : $Id$ 00005 begin : Sun Dec 04 2004 00006 copyright : (C) 2004 by Martin Preuss 00007 email : martin@libchipcard.de 00008 00009 *************************************************************************** 00010 * * 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU Lesser General Public * 00013 * License as published by the Free Software Foundation; either * 00014 * version 2.1 of the License, or (at your option) any later version. * 00015 * * 00016 * This library is distributed in the hope that it will be useful, * 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00019 * Lesser General Public License for more details. * 00020 * * 00021 * You should have received a copy of the GNU Lesser General Public * 00022 * License along with this library; if not, write to the Free Software * 00023 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 00024 * MA 02111-1307 USA * 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 /* first convert number */ 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 } /* while j */ 00075 00076 j=0; 00077 if (length) { 00078 if (i>length) 00079 i=length; 00080 00081 /* fill left up to length-(sizeof number) */ 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 } /* while k */ 00093 } /* if length */ 00094 00095 /* copy number */ 00096 for (k=0; k<i; k++) { 00097 if (j<size) 00098 buffer[j]=numbuf[k]; 00099 j++; 00100 } /* while i */ 00101 00102 /* append trailing 0 */ 00103 if (j<size) 00104 buffer[j]=0; 00105 j++; 00106 /* return length (or possible length) */ 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 /* first convert number */ 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 } /* while j */ 00145 00146 j=0; 00147 if (length) { 00148 if (i>length) 00149 i=length; 00150 00151 /* fill left up to length-(sizeof number) */ 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 } /* while k */ 00163 } /* if length */ 00164 00165 /* copy number */ 00166 for (k=0; k<i; k++) { 00167 if (j<size) 00168 buffer[j]=numbuf[k]; 00169 j++; 00170 } /* while i */ 00171 00172 /* append trailing 0 */ 00173 if (j<size) 00174 buffer[j]=0; 00175 j++; 00176 /* return length (or possible length) */ 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 /* write character '%' */ 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 /* read length */ 00209 if ((*fmt)>='0' && (*fmt)<='9') { 00210 /* read number */ 00211 if (*fmt=='0') { 00212 leadingZero=1; 00213 } 00214 while ((*fmt)>='0' && (*fmt)<='9') { 00215 length*=10; 00216 length+=*fmt-'0'; 00217 fmt++; 00218 } /* while */ 00219 } 00220 00221 /* read type */ 00222 switch(*fmt) { 00223 /* decimal integer */ 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 /* hexadecimal integer */ 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 /* hexadecimal integer */ 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 } /* while */ 00283 break; 00284 } 00285 00286 default: 00287 break; 00288 } /* switch */ 00289 } 00290 } 00291 else { 00292 if (i<size) 00293 buffer[i]=*fmt; 00294 i++; 00295 } 00296 fmt++; 00297 } /* while */ 00298 00299 /* add trailing 0 */ 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 /* DISABLE_DEBUGLOG */ 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 /* DISABLE_DEBUGLOG */ 00381 } 00382 00383 #endif /* NO_VARIADIC_MACROS */ 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 } /* while e */ 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(void){ 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