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