1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
|
/*
* debug.c: a generic debugging facility for unix programs.
*
* The calling program is required to call debug_setlevel(lvl) to set
* which messages will be displayed. The level is a two part value
* where the least significant (decimal) digit is a level as described
* below. The most significant digits are a class code. For a message
* to be displayed the class code must either be zero or match the
* class code of the debug(...) message.
*
* The 'debug(lvl, fmt, ...)' function displays debugging messages
* complete with source and line number. The function can be used
* as a normal one in if() smt else smt constructs. It returns the
* actual number of bytes printed so it's return value can be used
* inside an if(debug(...)) to enable more debugging code. This code
* will be removed by the compiler (as dead code) if debugging is
* not enabled.
*
* The level on the debug() statment also consists of a level and class
* code where the class code must be zero or match the setlevel's class
* code for the message to be displayed.
*
* Level 0
* Always displayed if the debugging is enabled.
* You probably shouldn't use this.
*
* Level 1
* Important state changes and errors that cause a significant change
* in program flow.
*
* Level 2
* Rare things that cause a minor program flow adjustment.
*
* Level 3
* Errors and useful messages that are slightly too verbose or common
* for 0-2 or don't quite fit in the classifications.
*
* Level 4
* All remote responses or major results. (Trace results)
*
* Level 5
* All remote commands or major tasks. (Trace jobs)
*
* Level 6
* General information that will not be too verbose but is normally a
* little less important. (Trace state)
*
* Level 7
* Similar to level 3 but verbose or not as useful.
*
* Level 8
* Very verbose information that'll probably be useful sometime.
*
* Level 9
* Anything and everything else, debugs that probably won't be useful
* ever again. (unclassified)
*
* Notes:
* If the programmer doesn't set the debug level this is not an important
* debug message or is only important right now.
* => default debug level == 9
*
* If something fits in one of the lower levels but is very verbose
* it should nevertheless be moved upto level 3 or levels 7-9.
* (Possibly leaving a single line 'oops' at the lower level)
*
* The general idea is that debug levels 0-3 should not scroll too fast
* to read and nothing below level 7 should be much more verbose than
* levels 4 or 5.
*
*****************************************************************************
*
* 2004-06-20: Added __STDC__ to debug.h so it can be called from non-ansi
* compiler. This file still needs ansi or unproto.
*
* 2004-06-20: Added check of DEBUG environment variable if setlevel isn't
* called before a debug().
*
* 2004-06-20: Added #define VARARG_MACROS so the preprocessor can remove
* all the debugging 'stuff'.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "debug.h"
#define USE_DBPRINTF
#ifndef DEBUG
static char ident[] =
"$Id: debug.c: (c) 1995-2004 Robert de Bath. Debugging disabled. $";
#else
static char ident[] =
"$Id: debug.c: (c) 1995-2004 Robert de Bath. Debugging enabled. $";
static char * db_file = 0;
static int db_lineno = 0;
static int disp_state = 0;
static int disp_pos(void);
static void debug_envvar(void);
int debug_level = -1;
void debug_do_setlevel(char * fname, int lineno, int level)
{
if(level || !debug_level)
debug_level = level;
debug_pos(fname, lineno);
debug_msg(1, "Debug level now %d", level);
debug_level = level;
}
int debug_pos(char * file, int lineno)
{
db_file = file;
db_lineno = lineno;
disp_state |= 1;
return disp_pos();
}
int debug_msg(int level, char * fmt, ...)
{
va_list ap;
int rv = 0;
int disp = 0;
if (debug_level == -1) debug_envvar();
if (level == -1) {
level = 0;
disp_state |= 1;
db_lineno = -1;
}
disp_state |= 2;
if (level>9 || debug_level>9) {
disp = (level%10 <= debug_level%10);
if (disp && level>9 && debug_level>9 && level/10 != debug_level/10)
disp = 0;
} else disp = (level <= debug_level);
if (disp)
{
disp_state |= 4;
va_start(ap, fmt);
#ifdef USE_DBPRINTF
rv = vdbprintf(fmt, ap);
#else
rv = vfprintf(stderr, fmt, ap);
#endif
va_end(ap);
}
return rv + disp_pos();
}
int
disp_pos()
{
int rv = 0;
if (disp_state == 7 && db_lineno != -1)
#ifdef USE_DBPRINTF
rv = dbprintf(" at %s:%d\n", db_file, db_lineno);
#else
rv = fprintf(stderr, " at %s:%d\n", db_file, db_lineno);
#endif
if ((disp_state&3) == 3) {
db_file = 0;
db_lineno = disp_state = 0;
}
return rv;
}
/* If setlevel isn't called check the environment */
static void debug_envvar(void)
{
char * p = getenv("DEBUG");
if (!p || !*p)
debug_level = 0;
else
debug_level = atoi(p);
if (debug_level)
#ifdef USE_DBPRINTF
dbprintf("Debug level now %d from environment.\n", debug_level);
#else
fprintf(stderr, "Debug level now %d from environment.\n", debug_level);
#endif
}
#endif
#ifndef VARARG_MACROS
/*
* This function should never be called.
*
* If ident sees the message in a binary then your compiler is wasting
* space by allocating it for unused strings.
*
* We know GNU-C is ok, but it complains.
*/
int debug_never(int level, char * name, ...)
{
#ifndef __GNUC__
1?0:debug_never(0, "$Warning: Debugging strings exist in non-debug binary $");
#endif
return 0;
}
#endif
|