gwenhywfar 5.10.1
debug.c
Go to the documentation of this file.
1/***************************************************************************
2 $RCSfile$
3 -------------------
4 cvs : $Id$
5 begin : Sun Dec 04 2004
6 copyright : (C) 2004 by Martin Preuss
7 email : martin@libchipcard.de
8
9 ***************************************************************************
10 * *
11 * This library is free software; you can redistribute it and/or *
12 * modify it under the terms of the GNU Lesser General Public *
13 * License as published by the Free Software Foundation; either *
14 * version 2.1 of the License, or (at your option) any later version. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19 * Lesser General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU Lesser General Public *
22 * License along with this library; if not, write to the Free Software *
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
24 * MA 02111-1307 USA *
25 * *
26 ***************************************************************************/
27
28
29#ifdef HAVE_CONFIG_H
30# include <config.h>
31#endif
32
33#include "debug_p.h"
34
35#include <stdarg.h>
36#include <assert.h>
37#include <stdio.h>
38#ifdef HAVE_STRINGS_H
39# include <strings.h>
40#endif
41#include <gwenhywfar/misc.h>
42
43
44
46
47
48
49uint32_t GWEN_Debug_PrintDec(char *buffer,
50 uint32_t size,
51 uint32_t num,
52 int leadingZero,
53 uint32_t length)
54{
55 uint32_t i;
56 uint32_t j;
57 uint32_t k;
58 char numbuf[16];
59 int numOr;
60
61 /* first convert number */
62 numOr=0;
63 i=0;
64 j=1000000000;
65
66 while (j) {
67 k=num/j;
68 numOr|=k;
69 if (numOr || leadingZero || j==1) {
70 numbuf[i]=k+'0';
71 i++;
72 }
73 num-=(k*j);
74 j/=10;
75 } /* while j */
76
77 j=0;
78 if (length) {
79 if (i>length)
80 i=length;
81
82 /* fill left up to length-(sizeof number) */
83 k=length-i;
84 while (k) {
85 if (j<size) {
86 if (leadingZero)
87 buffer[j]='0';
88 else
89 buffer[j]=' ';
90 }
91 j++;
92 k--;
93 } /* while k */
94 } /* if length */
95
96 /* copy number */
97 for (k=0; k<i; k++) {
98 if (j<size)
99 buffer[j]=numbuf[k];
100 j++;
101 } /* while i */
102
103 /* append trailing 0 */
104 if (j<size)
105 buffer[j]=0;
106 j++;
107 /* return length (or possible length) */
108 return j;
109}
110
111
112
113uint32_t GWEN_Debug_PrintHex(char *buffer,
114 uint32_t size,
115 uint32_t num,
116 int leadingZero,
117 int up,
118 uint32_t length)
119{
120 uint32_t i;
121 uint32_t j;
122 uint32_t k;
123 char numbuf[16];
124 int numOr;
125
126 /* first convert number */
127 numOr=0;
128 i=0;
129 j=8;
130
131 while (j) {
132 k=(num>>((j-1)*4))&0xf;
133 numOr|=k;
134 if (numOr || leadingZero || j==1) {
135 if (k>9) {
136 if (up)
137 numbuf[i]=k+'0'+7;
138 else
139 numbuf[i]=k+'0'+7+32;
140 }
141 else
142 numbuf[i]=k+'0';
143 i++;
144 }
145 j--;
146 } /* while j */
147
148 j=0;
149 if (length) {
150 if (i>length)
151 i=length;
152
153 /* fill left up to length-(sizeof number) */
154 k=length-i;
155 while (k) {
156 if (j<size) {
157 if (leadingZero)
158 buffer[j]='0';
159 else
160 buffer[j]=' ';
161 }
162 j++;
163 k--;
164 } /* while k */
165 } /* if length */
166
167 /* copy number */
168 for (k=0; k<i; k++) {
169 if (j<size)
170 buffer[j]=numbuf[k];
171 j++;
172 } /* while i */
173
174 /* append trailing 0 */
175 if (j<size)
176 buffer[j]=0;
177 j++;
178 /* return length (or possible length) */
179 return j;
180}
181
182
183
184
185
186uint32_t GWEN_Debug_Snprintf(char *buffer,
187 uint32_t size,
188 const char *fmt, ...)
189{
190 va_list arguments;
191 uint32_t i;
192
193 i=0;
194 va_start(arguments, fmt);
195 while (*fmt) {
196 if (*fmt=='%') {
197 fmt++;
198 if (*fmt=='%') {
199 /* write character '%' */
200 if (i<size)
201 buffer[i]='%';
202 i++;
203 }
204 else {
205 uint32_t length;
206 int leadingZero;
207
208 leadingZero=0;
209 length=0;
210
211 /* read length */
212 if ((*fmt)>='0' && (*fmt)<='9') {
213 /* read number */
214 if (*fmt=='0') {
215 leadingZero=1;
216 }
217 while ((*fmt)>='0' && (*fmt)<='9') {
218 length*=10;
219 length+=*fmt-'0';
220 fmt++;
221 } /* while */
222 }
223
224 /* read type */
225 switch (*fmt) {
226 /* decimal integer */
227 case 'c':
228 case 'd': {
229 int p;
230
231 p=va_arg(arguments, int);
232 if (p<0) {
233 if (i<size)
234 buffer[i]='-';
235 i++;
236 p=-p;
237 }
238 i+=GWEN_Debug_PrintDec(buffer+i,
239 size-i,
240 p,
241 leadingZero,
242 length)-1;
243 break;
244 }
245
246 /* hexadecimal integer */
247 case 'x': {
248 unsigned int p;
249
250 p=va_arg(arguments, unsigned int);
251 i+=GWEN_Debug_PrintHex(buffer+i,
252 size-i,
253 p,
254 leadingZero,
255 0,
256 length)-1;
257 break;
258 }
259
260 /* hexadecimal integer */
261 case 'X': {
262 unsigned int p;
263
264 p=va_arg(arguments, unsigned int);
265 i+=GWEN_Debug_PrintHex(buffer+i,
266 size-i,
267 p,
268 leadingZero,
269 1,
270 length)-1;
271 break;
272 }
273
274 case 's': {
275 const char *p;
276
277 p=va_arg(arguments, const char *);
278 if (!p)
279 p="(null)";
280 while (*p) {
281 if (i<size)
282 buffer[i]=*p;
283 i++;
284 p++;
285 } /* while */
286 break;
287 }
288
289 default:
290 break;
291 } /* switch */
292 }
293 }
294 else {
295 if (i<size)
296 buffer[i]=*fmt;
297 i++;
298 }
299 fmt++;
300 } /* while */
301
302 /* add trailing 0 */
303 if (i<size)
304 buffer[i]=0;
305 i++;
306 va_end(arguments);
307 return i;
308}
309
310
311
312
313#ifdef NO_VARIADIC_MACROS
314void DBG_ERROR(const char *dbg_logger, const char *format, ...)
315{
316 va_list args;
317 char dbg_buffer[256];
318 va_start(args, format);
319 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
320 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
321 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelError, dbg_buffer);
322 va_end(args);
323}
324
325void DBG_WARN(const char *dbg_logger, const char *format, ...)
326{
327 va_list args;
328 char dbg_buffer[256];
329 va_start(args, format);
330 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
331 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
332 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelWarning, dbg_buffer);
333 va_end(args);
334}
335
336void DBG_NOTICE(const char *dbg_logger, const char *format, ...)
337{
338 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelNotice) {
339 va_list args;
340 char dbg_buffer[256];
341 va_start(args, format);
342 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
343 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
344 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelNotice, dbg_buffer);
345 va_end(args);
346 }
347}
348
349void DBG_INFO(const char *dbg_logger, const char *format, ...)
350{
351 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelInfo) {
352 va_list args;
353 char dbg_buffer[256];
354 va_start(args, format);
355 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
356 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
357 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelInfo, dbg_buffer);
358 va_end(args);
359 }
360}
361
362void DBG_DEBUG(const char *dbg_logger, const char *format, ...)
363{
364# ifndef DISABLE_DEBUGLOG
365 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelDebug) {
366 va_list args;
367 char dbg_buffer[256];
368 va_start(args, format);
369 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
370 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
371 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelDebug, dbg_buffer);
372 va_end(args);
373 }
374# endif /* DISABLE_DEBUGLOG */
375}
376
377void DBG_VERBOUS(const char *dbg_logger, const char *format, ...)
378{
379# ifndef DISABLE_DEBUGLOG
380 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelVerbous) {
381 va_list args;
382 char dbg_buffer[256];
383 va_start(args, format);
384 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
385 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
386 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelVerbous, dbg_buffer);
387 va_end(args);
388 }
389# endif /* DISABLE_DEBUGLOG */
390}
391
392#endif /* NO_VARIADIC_MACROS */
393
394
395
396
397
398
399
400GWEN_MEMORY_DEBUG_ENTRY *GWEN_MemoryDebugEntry_new(GWEN_MEMORY_DEBUG_ENTRY_TYPE t,
401 const char *wFile,
402 int wLine)
403{
404 GWEN_MEMORY_DEBUG_ENTRY *e;
405
406 assert(wFile);
407 assert(wLine);
408 GWEN_NEW_OBJECT(GWEN_MEMORY_DEBUG_ENTRY, e);
409 e->file=strdup(wFile);
410 e->line=wLine;
411 e->type=t;
412 return e;
413}
414
415
416
417void GWEN_MemoryDebugEntry_free(GWEN_MEMORY_DEBUG_ENTRY *e)
418{
419 if (e) {
420 free(e->file);
422 }
423}
424
425
426
427
429{
431
432 assert(name);
434 o->name=strdup(name);
435 return o;
436}
437
438
439
441{
442 if (o) {
443 GWEN_MEMORY_DEBUG_ENTRY *e;
444
445 e=o->entries;
446 while (e) {
447 GWEN_MEMORY_DEBUG_ENTRY *next;
448
449 next=e->next;
451 e=next;
452 }
453 free(o->name);
455 }
456}
457
458
459
461{
463
465 while (o) {
466 assert(o->name);
467 if (strcasecmp(o->name, name)==0)
468 break;
469 if (o->next==o) {
470 DBG_ERROR(GWEN_LOGDOMAIN, "What ?? Pointing to myself ??");
471 abort();
472 }
473 o=o->next;
474 }
475
476 return o;
477}
478
479
480
481void GWEN_MemoryDebug_Increment(const char *name,
482 const char *wFile,
483 int wLine,
484 int attach)
485{
487 GWEN_MEMORY_DEBUG_ENTRY *e;
488
489 assert(name);
490 assert(wFile);
491 assert(wLine);
493 if (!o) {
496 e=GWEN_MemoryDebugEntry_new(attach?GWEN_MemoryDebugEntryTypeAttach:
497 GWEN_MemoryDebugEntryTypeCreate,
498 wFile, wLine);
499 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
500 o->count++;
501 }
502 else {
503 e=GWEN_MemoryDebugEntry_new(attach?GWEN_MemoryDebugEntryTypeAttach:
504 GWEN_MemoryDebugEntryTypeCreate,
505 wFile, wLine);
506 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
507 o->count++;
508 }
509}
510
511
512
513void GWEN_MemoryDebug_Decrement(const char *name,
514 const char *wFile,
515 int wLine)
516{
518 GWEN_MEMORY_DEBUG_ENTRY *e;
519
520 assert(name);
521 assert(wFile);
522 assert(wLine);
524 if (!o) {
526 "Object to be freed not found (%s at %s:%d)",
527 name, wFile, wLine);
530 e=GWEN_MemoryDebugEntry_new(GWEN_MemoryDebugEntryTypeFree,
531 wFile, wLine);
532 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
533 o->count--;
534 }
535 else {
536 e=GWEN_MemoryDebugEntry_new(GWEN_MemoryDebugEntryTypeFree,
537 wFile, wLine);
538 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
539 o->count--;
540 }
541}
542
543
544
546 uint32_t mode)
547{
548
549 DBG_ERROR(0, "Object \"%s\" (count=%ld)",
550 o->name, o->count);
551 if (o->count!=0 || mode==GWEN_MEMORY_DEBUG_MODE_DETAILED) {
552 GWEN_MEMORY_DEBUG_ENTRY *e;
553
555 e=o->entries;
556 while (e) {
557 const char *s;
558
559 fprintf(stderr, " ");
560 switch (e->type) {
561 case GWEN_MemoryDebugEntryTypeCreate:
562 s="created";
563 break;
564 case GWEN_MemoryDebugEntryTypeAttach:
565 s="attached";
566 break;
567 case GWEN_MemoryDebugEntryTypeFree:
568 s="freed";
569 break;
570 case GWEN_MemoryDebugEntryTypeUnknown:
571 default:
572 s="<unknown action>";
573 break;
574 }
575 DBG_ERROR(0, " %s at %s:%d", s, e->file, e->line);
576 e=e->next;
577 } /* while e */
578 }
579 }
580}
581
582
583
584void GWEN_MemoryDebug_DumpObject(const char *name,
585 uint32_t mode)
586{
588
589 assert(name);
591 if (!o) {
592 DBG_ERROR(GWEN_LOGDOMAIN, "Object \"%s\" not found", name);
593 }
594 else
596}
597
598
599
600long int GWEN_MemoryDebug_GetObjectCount(const char *name)
601{
603
604 assert(name);
606 if (!o) {
607 DBG_ERROR(GWEN_LOGDOMAIN, "Object \"%s\" not found", name);
608 return 0;
609 }
610 else
611 return o->count;
612}
613
614
615
616void GWEN_MemoryDebug_Dump(uint32_t mode)
617{
619
620 DBG_ERROR(0, "Gwenhywfar Memory Debugger Statistics:");
621 DBG_ERROR(0, "====================================== begin\n");
623 while (o) {
625 o=o->next;
626 }
627 DBG_ERROR(0, "====================================== end\n");
628}
629
630
631
633{
635
637 while (o) {
639
640 next=o->next;
642 o=next;
643 }
645}
646
647
648
649
GWENHYWFAR_API const char * fmt
Definition: buffer.h:283
GWEN_MEMORY_DEBUG_OBJECT * GWEN_MemoryDebugObject_new(const char *name)
Definition: debug.c:428
GWEN_MEMORY_DEBUG_OBJECT * GWEN_MemoryDebug__FindObject(const char *name)
Definition: debug.c:460
void GWEN_MemoryDebug_Dump(uint32_t mode)
Definition: debug.c:616
long int GWEN_MemoryDebug_GetObjectCount(const char *name)
Definition: debug.c:600
void GWEN_MemoryDebug_Decrement(const char *name, const char *wFile, int wLine)
Definition: debug.c:513
void GWEN_MemoryDebug_Increment(const char *name, const char *wFile, int wLine, int attach)
Definition: debug.c:481
void GWEN_MemoryDebug_DumpObject(const char *name, uint32_t mode)
Definition: debug.c:584
void GWEN_MemoryDebugObject_free(GWEN_MEMORY_DEBUG_OBJECT *o)
Definition: debug.c:440
void GWEN_MemoryDebugEntry_free(GWEN_MEMORY_DEBUG_ENTRY *e)
Definition: debug.c:417
GWEN_MEMORY_DEBUG_ENTRY * GWEN_MemoryDebugEntry_new(GWEN_MEMORY_DEBUG_ENTRY_TYPE t, const char *wFile, int wLine)
Definition: debug.c:400
uint32_t GWEN_Debug_PrintHex(char *buffer, uint32_t size, uint32_t num, int leadingZero, int up, uint32_t length)
Definition: debug.c:113
void GWEN_MemoryDebug__DumpObject(GWEN_MEMORY_DEBUG_OBJECT *o, uint32_t mode)
Definition: debug.c:545
uint32_t GWEN_Debug_Snprintf(char *buffer, uint32_t size, const char *fmt,...)
Definition: debug.c:186
static GWEN_MEMORY_DEBUG_OBJECT * gwen_debug__memobjects
Definition: debug.c:45
uint32_t GWEN_Debug_PrintDec(char *buffer, uint32_t size, uint32_t num, int leadingZero, uint32_t length)
Definition: debug.c:49
void GWEN_MemoryDebug_CleanUp(void)
Definition: debug.c:632
struct GWEN_MEMORY_DEBUG_OBJECT GWEN_MEMORY_DEBUG_OBJECT
Definition: debug.h:55
#define GWEN_MEMORY_DEBUG_MODE_SHORT
Definition: debug.h:53
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:214
#define GWEN_MEMORY_DEBUG_MODE_DETAILED
Definition: debug.h:52
#define DBG_WARN(dbg_logger, format, args...)
Definition: debug.h:125
#define DBG_NOTICE(dbg_logger, format, args...)
Definition: debug.h:152
#define DBG_VERBOUS(dbg_logger, format, args...)
Definition: debug.h:224
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
void GWEN_Logger_Log(const char *logDomain, GWEN_LOGGER_LEVEL priority, const char *s)
Definition: logger.c:553
int GWEN_Logger_GetLevel(const char *logDomain)
Definition: logger.c:638
#define GWEN_LOGDOMAIN
Definition: logger.h:35
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
#define GWEN_LIST_ADD(typ, sr, head)
Definition: misc.h:82