| 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 | |
|---|
| 37 | #define RALF_DUMP_EXPR(type,var) ALL_DUMP_EXPR(type,var) |
|---|
| 38 | #define RALF_DUMP_VAL(var) ALL_DUMP_VAL(var) |
|---|
| 39 | #define RALF_DUMP_STR(var) ALL_DUMP_STR(var) |
|---|
| 40 | #define RALF_DUMP_PTR(var) ALL_DUMP_PTR(var) |
|---|
| 41 | #define RALF_DUMP_MARK() ALL_DUMP_MARK() |
|---|
| 42 | |
|---|
| 43 | #else |
|---|
| 44 | |
|---|
| 45 | #define RALF_DUMP_VAL(var) |
|---|
| 46 | #define RALF_DUMP_STR(var) |
|---|
| 47 | #define RALF_DUMP_MARK() |
|---|
| 48 | |
|---|
| 49 | #endif |
|---|
| 50 | |
|---|
| 51 | // -------------------------------------------------------------------------------- |
|---|
| 52 | // This section is used by Yadhu |
|---|
| 53 | |
|---|
| 54 | #if defined(DEVEL_YADHU) |
|---|
| 55 | |
|---|
| 56 | #define BUGEX_DUMPS |
|---|
| 57 | #define BUGEX_MAX_STRING_PRINT 40 |
|---|
| 58 | #define YADHU_DUMP_VAL(var) ALL_DUMP_VAL(var) |
|---|
| 59 | #define YADHU_DUMP_STR(var) ALL_DUMP_STR(var) |
|---|
| 60 | #define YADHU_DUMP_PTR(var) ALL_DUMP_PTR(var) |
|---|
| 61 | #define YADHU_DUMP_MARK() ALL_DUMP_MARK() |
|---|
| 62 | |
|---|
| 63 | #else |
|---|
| 64 | |
|---|
| 65 | #define YADHU_DUMP_VAL(var) |
|---|
| 66 | #define YADHU_DUMP_STR(var) |
|---|
| 67 | #define YADHU_DUMP_MARK() |
|---|
| 68 | |
|---|
| 69 | #endif |
|---|
| 70 | |
|---|
| 71 | // -------------------------------------------------------------------------------- |
|---|
| 72 | // Definition of needed macros/functions : |
|---|
| 73 | |
|---|
| 74 | #if defined(BUGEX_DUMPS) |
|---|
| 75 | |
|---|
| 76 | #ifndef _GLIBCXX_CCTYPE |
|---|
| 77 | #include <cctype> |
|---|
| 78 | #endif |
|---|
| 79 | |
|---|
| 80 | // Do NOT use the following macros!!! |
|---|
| 81 | |
|---|
| 82 | #define ALL_DUMP_EXPR(type,expr) \ |
|---|
| 83 | do { \ |
|---|
| 84 | type tmp_var = (expr); \ |
|---|
| 85 | bugex_dump_value(&tmp_var, "[" #expr "]", sizeof(tmp_var), __FILE__, __LINE__); \ |
|---|
| 86 | } while (0) |
|---|
| 87 | |
|---|
| 88 | #define ALL_DUMP_VAL(var) bugex_dump_value(&var, #var, sizeof(var), __FILE__, __LINE__) |
|---|
| 89 | #define ALL_DUMP_STR(var) bugex_dump_string(&var, #var, __FILE__, __LINE__) |
|---|
| 90 | #define ALL_DUMP_PTR(var) bugex_dump_pointer(&var, #var, __FILE__, __LINE__) |
|---|
| 91 | #define ALL_DUMP_MARK() bugex_dump_mark(__FILE__, __LINE__) |
|---|
| 92 | |
|---|
| 93 | static void bugex_dump_mark(const char *file, size_t lineno) { |
|---|
| 94 | fprintf(stderr, "%s:%zu: ------------------------------ MARK\n", file, lineno); |
|---|
| 95 | fflush(stderr); |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | static void bugex_printString(const char *str, size_t len) { |
|---|
| 99 | while (len--) { |
|---|
| 100 | unsigned char c = (unsigned char)*str++; |
|---|
| 101 | if (isprint(c)) { |
|---|
| 102 | fputc(c, stderr); |
|---|
| 103 | } |
|---|
| 104 | else { |
|---|
| 105 | switch (c) { |
|---|
| 106 | case '\n': fputs("\\n", stderr); break; |
|---|
| 107 | case '\t': fputs("\\t", stderr); break; |
|---|
| 108 | default: fprintf(stderr, "\\%i", (int)c); break; |
|---|
| 109 | } |
|---|
| 110 | } |
|---|
| 111 | } |
|---|
| 112 | } |
|---|
| 113 | |
|---|
| 114 | static void bugex_dump_pointer(void *somePtr, const char *someName, const char *file, size_t lineno) { |
|---|
| 115 | fprintf(stderr, "%s:%zu: %s: %p -> %p\n", file, lineno, someName, somePtr, *(void**)somePtr); |
|---|
| 116 | fflush(stderr); |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | static void bugex_dump_string(void *strPtr, const char *strName, const char *file, size_t lineno) { |
|---|
| 120 | const char *s = *((const char **)strPtr); |
|---|
| 121 | |
|---|
| 122 | fprintf(stderr, "%s:%zu: ", file, lineno); |
|---|
| 123 | |
|---|
| 124 | if (s == 0) { // NULL pointer |
|---|
| 125 | fprintf(stderr, "%s is NULL (&=%p)\n", strName, strPtr); |
|---|
| 126 | } |
|---|
| 127 | else { |
|---|
| 128 | size_t len = strlen(s); |
|---|
| 129 | |
|---|
| 130 | fprintf(stderr, "%s = \"", strName); |
|---|
| 131 | if (len <= BUGEX_MAX_STRING_PRINT) { // short strings |
|---|
| 132 | bugex_printString(s, len); |
|---|
| 133 | } |
|---|
| 134 | else { |
|---|
| 135 | bugex_printString(s, BUGEX_MAX_STRING_PRINT/2); |
|---|
| 136 | fprintf(stderr, "\" .. \""); |
|---|
| 137 | bugex_printString(s+len-BUGEX_MAX_STRING_PRINT/2, BUGEX_MAX_STRING_PRINT/2); |
|---|
| 138 | } |
|---|
| 139 | fprintf(stderr, "\" (len=%zu, &=%p -> %p)\n", len, strPtr, s); |
|---|
| 140 | } |
|---|
| 141 | fflush(stderr); |
|---|
| 142 | } |
|---|
| 143 | |
|---|
| 144 | |
|---|
| 145 | #define BUGEX_VALSIZES 4 |
|---|
| 146 | static unsigned short bugex_valsize[] = { sizeof(char), sizeof(short), sizeof(int), sizeof(long), 0 }; |
|---|
| 147 | enum bugex_valtype { BUGEX_CHAR, BUGEX_SHORT, BUGEX_INT, BUGEX_LONG, BUGEX_UNKNOWN }; |
|---|
| 148 | |
|---|
| 149 | static void bugex_dump_value(void *valuePtr, const char *valueName, size_t size, const char *file, size_t lineno) { |
|---|
| 150 | int vs; |
|---|
| 151 | enum bugex_valtype type = BUGEX_UNKNOWN; |
|---|
| 152 | |
|---|
| 153 | if (size == bugex_valsize[BUGEX_INT]) { |
|---|
| 154 | type = BUGEX_INT; // prefer int |
|---|
| 155 | } |
|---|
| 156 | else { |
|---|
| 157 | for (vs = 0; vs < BUGEX_VALSIZES; ++vs) { |
|---|
| 158 | if (size == bugex_valsize[vs]) { |
|---|
| 159 | type = (enum bugex_valtype)vs; |
|---|
| 160 | } |
|---|
| 161 | } |
|---|
| 162 | } |
|---|
| 163 | |
|---|
| 164 | fprintf(stderr, "%s:%zu: ", file, lineno); |
|---|
| 165 | |
|---|
| 166 | switch (type) { |
|---|
| 167 | case BUGEX_CHAR: { |
|---|
| 168 | unsigned char c = *(unsigned char*)valuePtr; |
|---|
| 169 | int i = (int)(signed char)c; |
|---|
| 170 | |
|---|
| 171 | fprintf(stderr, "(char) %s = '%c' = %i", valueName, c, i); |
|---|
| 172 | if (i<0) fprintf(stderr, " = %u", (unsigned int)c); |
|---|
| 173 | fprintf(stderr, " (&=%p)", valuePtr); |
|---|
| 174 | break; |
|---|
| 175 | } |
|---|
| 176 | case BUGEX_SHORT: { |
|---|
| 177 | unsigned short s = *(unsigned short *)valuePtr; |
|---|
| 178 | signed short ss = (signed short)s; |
|---|
| 179 | |
|---|
| 180 | fprintf(stderr, "(short) %s = %hi", valueName, (int)ss); |
|---|
| 181 | if (ss<0) fprintf(stderr, " = %hu", s); |
|---|
| 182 | fprintf(stderr, " = 0x%hx (&=%p)", s, valuePtr); |
|---|
| 183 | break; |
|---|
| 184 | } |
|---|
| 185 | case BUGEX_INT: { |
|---|
| 186 | unsigned int u = *(unsigned int *)valuePtr; |
|---|
| 187 | int i = (int)u; |
|---|
| 188 | |
|---|
| 189 | fprintf(stderr, "(int) %s = %i", valueName, i); |
|---|
| 190 | if (i<0) fprintf(stderr, " = %u", u); |
|---|
| 191 | fprintf(stderr, " = 0x%x (&=%p)", u, valuePtr); |
|---|
| 192 | break; |
|---|
| 193 | } |
|---|
| 194 | case BUGEX_LONG: { |
|---|
| 195 | unsigned long l = *(unsigned long *)valuePtr; |
|---|
| 196 | fprintf(stderr, "(long) %s = %li = %lu = 0x%lx (&=%p)", valueName, (signed long)l, (unsigned long)l, (unsigned long)l, valuePtr); |
|---|
| 197 | break; |
|---|
| 198 | } |
|---|
| 199 | default: { |
|---|
| 200 | fprintf(stderr, "value '%s' has unknown size (use cast operator!)", valueName); |
|---|
| 201 | break; |
|---|
| 202 | } |
|---|
| 203 | } |
|---|
| 204 | fprintf(stderr, "\n"); |
|---|
| 205 | fflush(stderr); |
|---|
| 206 | } |
|---|
| 207 | |
|---|
| 208 | #endif // BUGEX_DUMPS |
|---|