| 1 | // ==================================================================== // |
|---|
| 2 | // // |
|---|
| 3 | // File : bugex.h // |
|---|
| 4 | // Purpose : Debugging code // |
|---|
| 5 | // // |
|---|
| 6 | // // |
|---|
| 7 | // Coded by Ralf Westram (coder@reallysoft.de) in April 2003 // |
|---|
| 8 | // Copyright Department of Microbiology (Technical University Munich) // |
|---|
| 9 | // // |
|---|
| 10 | // Visit our web site at: http://www.arb-home.de/ // |
|---|
| 11 | // // |
|---|
| 12 | // // |
|---|
| 13 | // ==================================================================== // |
|---|
| 14 | |
|---|
| 15 | // Description : |
|---|
| 16 | // |
|---|
| 17 | // when using the macros XXX_DUMP_VAL and XXX_DUMP_STR the program prints |
|---|
| 18 | // out information about the specified variables. |
|---|
| 19 | // |
|---|
| 20 | // This information is prefixed by 'FILE:LINENO: ' |
|---|
| 21 | // |
|---|
| 22 | // The intention is to use the program as compile-command in emacs and follow |
|---|
| 23 | // the program flow with next-error / previous-error |
|---|
| 24 | // |
|---|
| 25 | // Note : When finished with debugging you should remove the #include "bugex.h" |
|---|
| 26 | // because it adds unneeded code to EVERY object file! |
|---|
| 27 | |
|---|
| 28 | // -------------------------------------------------------------------------------- |
|---|
| 29 | // This section is used by Ralf |
|---|
| 30 | // If you want to use the DUMP-Macros copy this section and personalize it! |
|---|
| 31 | |
|---|
| 32 | #if defined(DEVEL_RALF) |
|---|
| 33 | |
|---|
| 34 | #define BUGEX_DUMPS |
|---|
| 35 | #define BUGEX_MAX_STRING_PRINT 40 |
|---|
| 36 | #define RALF_DUMP_VAL(var) ALL_DUMP_VAL(var) |
|---|
| 37 | #define RALF_DUMP_STR(var) ALL_DUMP_STR(var) |
|---|
| 38 | #define RALF_DUMP_PTR(var) ALL_DUMP_PTR(var) |
|---|
| 39 | #define RALF_DUMP_MARK() ALL_DUMP_MARK() |
|---|
| 40 | |
|---|
| 41 | #else |
|---|
| 42 | |
|---|
| 43 | #define RALF_DUMP_VAL(var) |
|---|
| 44 | #define RALF_DUMP_STR(var) |
|---|
| 45 | #define RALF_DUMP_MARK() |
|---|
| 46 | |
|---|
| 47 | #endif |
|---|
| 48 | |
|---|
| 49 | // -------------------------------------------------------------------------------- |
|---|
| 50 | // This section is used by Yadhu |
|---|
| 51 | |
|---|
| 52 | #if defined(DEVEL_YADHU) |
|---|
| 53 | |
|---|
| 54 | #define BUGEX_DUMPS |
|---|
| 55 | #define BUGEX_MAX_STRING_PRINT 40 |
|---|
| 56 | #define YADHU_DUMP_VAL(var) ALL_DUMP_VAL(var) |
|---|
| 57 | #define YADHU_DUMP_STR(var) ALL_DUMP_STR(var) |
|---|
| 58 | #define YADHU_DUMP_PTR(var) ALL_DUMP_PTR(var) |
|---|
| 59 | #define YADHU_DUMP_MARK() ALL_DUMP_MARK() |
|---|
| 60 | |
|---|
| 61 | #else |
|---|
| 62 | |
|---|
| 63 | #define YADHU_DUMP_VAL(var) |
|---|
| 64 | #define YADHU_DUMP_STR(var) |
|---|
| 65 | #define YADHU_DUMP_MARK() |
|---|
| 66 | |
|---|
| 67 | #endif |
|---|
| 68 | |
|---|
| 69 | // -------------------------------------------------------------------------------- |
|---|
| 70 | // Definition of needed macros/functions : |
|---|
| 71 | |
|---|
| 72 | #if defined(BUGEX_DUMPS) |
|---|
| 73 | |
|---|
| 74 | #ifndef _CTYPE_H |
|---|
| 75 | #include <ctype.h> |
|---|
| 76 | #endif |
|---|
| 77 | |
|---|
| 78 | // Do NOT use the following macros!!! |
|---|
| 79 | #define ALL_DUMP_VAL(var) bugex_dump_value(&var, #var, sizeof(var), __FILE__, __LINE__) |
|---|
| 80 | #define ALL_DUMP_STR(var) bugex_dump_string(&var, #var, __FILE__, __LINE__) |
|---|
| 81 | #define ALL_DUMP_PTR(var) bugex_dump_pointer(&var, #var, __FILE__, __LINE__) |
|---|
| 82 | #define ALL_DUMP_MARK() bugex_dump_mark(__FILE__, __LINE__) |
|---|
| 83 | |
|---|
| 84 | static void bugex_dump_mark(const char *file, size_t lineno) { |
|---|
| 85 | fprintf(stderr, "%s:%u: ------------------------------ MARK\n", file, lineno); |
|---|
| 86 | fflush(stderr); |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | static void bugex_printString(const char *str, size_t len) { |
|---|
| 90 | while (len--) { |
|---|
| 91 | unsigned char c = (unsigned char)*str++; |
|---|
| 92 | if (isprint(c)) { |
|---|
| 93 | fputc(c, stderr); |
|---|
| 94 | } |
|---|
| 95 | else { |
|---|
| 96 | switch (c) { |
|---|
| 97 | case '\n': fputs("\\n", stderr); break; |
|---|
| 98 | case '\t': fputs("\\t", stderr); break; |
|---|
| 99 | default : fprintf(stderr, "\\%i", (int)c); break; |
|---|
| 100 | } |
|---|
| 101 | } |
|---|
| 102 | } |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | static void bugex_dump_pointer(void *somePtr, const char *someName, const char *file, size_t lineno) { |
|---|
| 106 | fprintf(stderr, "%s:%u: %s: %p -> %p\n", file, lineno, someName, somePtr, *(void**)somePtr); |
|---|
| 107 | fflush(stderr); |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | static void bugex_dump_string(void *strPtr, const char *strName, const char *file, size_t lineno) { |
|---|
| 111 | const char *s = *((const char **)strPtr); |
|---|
| 112 | |
|---|
| 113 | fprintf(stderr, "%s:%u: ", file, lineno); |
|---|
| 114 | |
|---|
| 115 | if (s == 0) { // NULL pointer |
|---|
| 116 | fprintf(stderr, "%s is NULL (&=%p)\n", strName, strPtr); |
|---|
| 117 | } |
|---|
| 118 | else { |
|---|
| 119 | size_t len = strlen(s); |
|---|
| 120 | |
|---|
| 121 | fprintf(stderr, "%s = \"", strName); |
|---|
| 122 | if (len <= BUGEX_MAX_STRING_PRINT) { // short strings |
|---|
| 123 | bugex_printString(s, len); |
|---|
| 124 | } |
|---|
| 125 | else { |
|---|
| 126 | bugex_printString(s, BUGEX_MAX_STRING_PRINT/2); |
|---|
| 127 | fprintf(stderr, "\" .. \""); |
|---|
| 128 | bugex_printString(s+len-BUGEX_MAX_STRING_PRINT/2, BUGEX_MAX_STRING_PRINT/2); |
|---|
| 129 | } |
|---|
| 130 | fprintf(stderr, "\" (len=%u, &=%p -> %p)\n", len, strPtr, s); |
|---|
| 131 | } |
|---|
| 132 | fflush(stderr); |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | |
|---|
| 136 | #define BUGEX_VALSIZES 4 |
|---|
| 137 | static unsigned short bugex_valsize[] = { sizeof(char), sizeof(short), sizeof(int), sizeof(long), 0 }; |
|---|
| 138 | enum bugex_valtype { BUGEX_CHAR, BUGEX_SHORT, BUGEX_INT, BUGEX_LONG, BUGEX_UNKNOWN }; |
|---|
| 139 | |
|---|
| 140 | static void bugex_dump_value(void *valuePtr, const char *valueName, size_t size, const char *file, size_t lineno) { |
|---|
| 141 | int vs; |
|---|
| 142 | enum bugex_valtype type = BUGEX_UNKNOWN; |
|---|
| 143 | |
|---|
| 144 | if (size == bugex_valsize[BUGEX_INT]) { |
|---|
| 145 | type = BUGEX_INT; // prefer int |
|---|
| 146 | } |
|---|
| 147 | else { |
|---|
| 148 | for (vs = 0; vs < BUGEX_VALSIZES; ++vs) { |
|---|
| 149 | if (size == bugex_valsize[vs]) { |
|---|
| 150 | type = (enum bugex_valtype)vs; |
|---|
| 151 | } |
|---|
| 152 | } |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | fprintf(stderr, "%s:%u: ", file, lineno); |
|---|
| 156 | |
|---|
| 157 | switch (type) { |
|---|
| 158 | case BUGEX_CHAR: { |
|---|
| 159 | unsigned char c = *(unsigned char*)valuePtr; |
|---|
| 160 | int i = (int)(signed char)c; |
|---|
| 161 | |
|---|
| 162 | if (i<0) { |
|---|
| 163 | fprintf(stderr, "(char) %s = '%c' = %i = %u (&=%p)", valueName, c, i, (unsigned int)c, valuePtr); |
|---|
| 164 | } |
|---|
| 165 | else { |
|---|
| 166 | fprintf(stderr, "(char) %s = '%c' = %i (&=%p)", valueName, c, i, valuePtr); |
|---|
| 167 | } |
|---|
| 168 | break; |
|---|
| 169 | } |
|---|
| 170 | case BUGEX_SHORT: { |
|---|
| 171 | unsigned short s = *(unsigned short *)valuePtr; |
|---|
| 172 | signed short ss = (signed short)s; |
|---|
| 173 | if (ss<0) { |
|---|
| 174 | fprintf(stderr, "(short) %s = %i = %u (&=%p)", valueName, (int)ss, (unsigned)s, valuePtr); |
|---|
| 175 | } |
|---|
| 176 | else { |
|---|
| 177 | fprintf(stderr, "(short) %s = %i (&=%p)", valueName, (int)ss, valuePtr); |
|---|
| 178 | } |
|---|
| 179 | break; |
|---|
| 180 | } |
|---|
| 181 | case BUGEX_INT: { |
|---|
| 182 | unsigned int u = *(unsigned int *)valuePtr; |
|---|
| 183 | int i = (int)u; |
|---|
| 184 | |
|---|
| 185 | if (i<0) { |
|---|
| 186 | fprintf(stderr, "(int) %s = %i = %u (&=%p)", valueName, i, u, valuePtr); |
|---|
| 187 | } |
|---|
| 188 | else { |
|---|
| 189 | fprintf(stderr, "(int) %s = %i (&=%p)", valueName, i, valuePtr); |
|---|
| 190 | } |
|---|
| 191 | break; |
|---|
| 192 | } |
|---|
| 193 | case BUGEX_LONG: { |
|---|
| 194 | unsigned long l = *(unsigned long *)valuePtr; |
|---|
| 195 | fprintf(stderr, "(long) %s = %li = %lu (&=%p)", valueName, (signed long)l, (unsigned long)l, valuePtr); |
|---|
| 196 | break; |
|---|
| 197 | } |
|---|
| 198 | default : { |
|---|
| 199 | fprintf(stderr, "value '%s' has unknown size (use cast operator!)", valueName); |
|---|
| 200 | break; |
|---|
| 201 | } |
|---|
| 202 | } |
|---|
| 203 | fprintf(stderr, "\n"); |
|---|
| 204 | fflush(stderr); |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | #endif // BUGEX_DUMPS |
|---|