Merging NList 0.111 into main branch.
[AROS-Contrib.git] / mui / classes / nlist / nlist_mcc / Debug.c
blob26cb30e1061a9b004c7d3c449063ab1c5ae74133
1 /***************************************************************************
3 NList.mcc - New List MUI Custom Class
4 Registered MUI class, Serial Number: 1d51 0x9d510030 to 0x9d5100A0
5 0x9d5100C0 to 0x9d5100FF
7 Copyright (C) 1996-2001 by Gilles Masson
8 Copyright (C) 2001-2005 by NList Open Source Team
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2.1 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 NList classes Support Site: http://www.sf.net/projects/nlist-classes
22 $Id$
24 ***************************************************************************/
26 #ifdef DEBUG
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <stdio.h>
33 #include <proto/exec.h>
34 #include <proto/dos.h>
35 #include <proto/intuition.h>
36 #include <proto/timer.h>
37 #include <proto/utility.h>
39 #include <SDI/SDI_compiler.h>
40 #include "Debug.h"
41 #include "version.h"
42 #include "timeval.h"
44 // special flagging macros
45 #define isFlagSet(v,f) (((v) & (f)) == (f)) // return TRUE if the flag is set
46 #define hasFlag(v,f) (((v) & (f)) != 0) // return TRUE if one of the flags in f is set in v
47 #define isFlagClear(v,f) (((v) & (f)) == 0) // return TRUE if flag f is not set in v
48 #define SET_FLAG(v,f) ((v) |= (f)) // set the flag f in v
49 #define CLEAR_FLAG(v,f) ((v) &= ~(f)) // clear the flag f in v
50 #define MASK_FLAG(v,f) ((v) &= (f)) // mask the variable v with flag f bitwise
52 // our static variables with default values
53 static int indent_level = 0;
54 static BOOL ansi_output = FALSE;
55 static ULONG debug_flags = DBF_ALWAYS | DBF_STARTUP; // default debug flags
56 static ULONG debug_classes = DBC_ERROR | DBC_DEBUG | DBC_WARNING | DBC_ASSERT | DBC_REPORT; // default debug classes
57 #define NUMCLOCKS 8
58 static int timer_level = -1;
59 static struct TimeVal startTimes[NUMCLOCKS];
61 /****************************************************************************/
63 void SetupDebug(void)
65 char var[256];
67 kprintf("** NList.mcc v" LIB_REV_STRING " startup ***********************\n");
68 kprintf("Initializing runtime debugging:\n");
70 if(GetVar("nlist.mcc.debug", var, sizeof(var), 0) > 0)
72 char *tok;
73 char *debug = var;
75 // static list of our debugging classes tokens.
76 // in the yamdebug variable these classes always start with a @
77 static struct { const char *token; unsigned long flag; } dbclasses[] =
79 { "ctrace", DBC_CTRACE },
80 { "report", DBC_REPORT },
81 { "assert", DBC_ASSERT },
82 { "timeval", DBC_TIMEVAL },
83 { "debug", DBC_DEBUG },
84 { "error", DBC_ERROR },
85 { "warning", DBC_WARNING },
86 { "all", DBC_ALL },
87 { NULL, 0 }
90 static struct { const char *token; unsigned long flag; } dbflags[] =
92 { "always", DBF_ALWAYS },
93 { "startup", DBF_STARTUP },
94 { "select", DBF_SELECT },
95 { "input", DBF_INPUT },
96 { "clipboard", DBF_CLIPBOARD },
97 { "draw", DBF_DRAW },
98 { "all", DBF_ALL },
99 { NULL, 0 }
102 // we parse the env variable token-wise
103 while((tok = strtok(debug, ", ;")))
105 ULONG i;
107 // check if the token is class definition or
108 // just a flag definition
109 if(tok[0] == '@')
111 // check if this call is a negation or not
112 if(tok[1] == '!')
114 // search for the token and clear the flag
115 for(i=0; dbclasses[i].token; i++)
117 if(stricmp(tok+2, dbclasses[i].token) == 0)
119 kprintf("clear '%s' debug class flag.\n", dbclasses[i].token);
120 CLEAR_FLAG(debug_classes, dbclasses[i].flag);
124 else
126 // search for the token and set the flag
127 for(i=0; dbclasses[i].token; i++)
129 if(stricmp(tok+1, dbclasses[i].token) == 0)
131 kprintf("set '%s' debug class flag\n", dbclasses[i].token);
132 SET_FLAG(debug_classes, dbclasses[i].flag);
137 else
139 // check if this call is a negation or not
140 if(tok[0] == '!')
142 for(i=0; dbflags[i].token; i++)
144 if(stricmp(tok+1, dbflags[i].token) == 0)
146 kprintf("clear '%s' debug flag\n", dbflags[i].token);
147 CLEAR_FLAG(debug_flags, dbflags[i].flag);
151 else
153 // check if the token was "ansi" and if so enable the ANSI color
154 // output
155 if(stricmp(tok, "ansi") == 0)
157 kprintf("ansi output enabled\n");
158 ansi_output = TRUE;
160 else
162 for(i=0; dbflags[i].token; i++)
164 if(stricmp(tok, dbflags[i].token) == 0)
166 kprintf("set '%s' debug flag\n", dbflags[i].token);
167 SET_FLAG(debug_flags, dbflags[i].flag);
174 debug = NULL;
178 kprintf("set debug classes/flags (env:nlist.mcc.debug): %08lx/%08lx\n", debug_classes, debug_flags);
179 kprintf("** Normal processing follows ***************************************\n");
182 /****************************************************************************/
184 void CleanupDebug(void)
186 kprintf("** Cleaned up debugging ********************************************\n");
189 /****************************************************************************/
191 // define variables for using ANSI colors in our debugging scheme
192 #define ANSI_ESC_CLR "\033[0m"
193 #define ANSI_ESC_BOLD "\033[1m"
194 #define ANSI_ESC_UNDERLINE "\033[4m"
195 #define ANSI_ESC_BLINK "\033[5m"
196 #define ANSI_ESC_REVERSE "\033[7m"
197 #define ANSI_ESC_INVISIBLE "\033[8m"
198 #define ANSI_ESC_FG_BLACK "\033[0;30m"
199 #define ANSI_ESC_FG_RED "\033[0;31m"
200 #define ANSI_ESC_FG_GREEN "\033[0;32m"
201 #define ANSI_ESC_FG_BROWN "\033[0;33m"
202 #define ANSI_ESC_FG_BLUE "\033[0;34m"
203 #define ANSI_ESC_FG_PURPLE "\033[0;35m"
204 #define ANSI_ESC_FG_CYAN "\033[0;36m"
205 #define ANSI_ESC_FG_LGRAY "\033[0;37m"
206 #define ANSI_ESC_FG_DGRAY "\033[1;30m"
207 #define ANSI_ESC_FG_LRED "\033[1;31m"
208 #define ANSI_ESC_FG_LGREEN "\033[1;32m"
209 #define ANSI_ESC_FG_YELLOW "\033[1;33m"
210 #define ANSI_ESC_FG_LBLUE "\033[1;34m"
211 #define ANSI_ESC_FG_LPURPLE "\033[1;35m"
212 #define ANSI_ESC_FG_LCYAN "\033[1;36m"
213 #define ANSI_ESC_FG_WHITE "\033[1;37m"
214 #define ANSI_ESC_BG "\033[0;4" // background esc-squ start with 4x
215 #define ANSI_ESC_BG_BLACK "\033[0;40m"
216 #define ANSI_ESC_BG_RED "\033[0;41m"
217 #define ANSI_ESC_BG_GREEN "\033[0;42m"
218 #define ANSI_ESC_BG_BROWN "\033[0;43m"
219 #define ANSI_ESC_BG_BLUE "\033[0;44m"
220 #define ANSI_ESC_BG_PURPLE "\033[0;45m"
221 #define ANSI_ESC_BG_CYAN "\033[0;46m"
222 #define ANSI_ESC_BG_LGRAY "\033[0;47m"
224 /****************************************************************************/
226 INLINE void _INDENT(void)
228 int i;
229 for(i=0; i < indent_level; i++)
230 kprintf(" ");
233 /****************************************************************************/
235 void _ENTER(unsigned long dclass, const char *file, int line, const char *function)
237 if(isFlagSet(debug_classes, dclass))
239 _INDENT();
240 if(ansi_output)
241 kprintf("%s%s:%ld:Entering %s%s\n", ANSI_ESC_FG_BROWN, file, line, function, ANSI_ESC_CLR);
242 else
243 kprintf("%s:%ld:Entering %s\n", file, line, function);
246 indent_level++;
249 void _LEAVE(unsigned long dclass, const char *file, int line, const char *function)
251 indent_level--;
253 if(isFlagSet(debug_classes, dclass))
255 _INDENT();
256 if(ansi_output)
257 kprintf("%s%s:%ld:Leaving %s%s\n", ANSI_ESC_FG_BROWN, file, line, function, ANSI_ESC_CLR);
258 else
259 kprintf("%s:%ld:Leaving %s\n", file, line, function);
263 void _RETURN(unsigned long dclass, const char *file, int line, const char *function, unsigned long result)
265 indent_level--;
267 if(isFlagSet(debug_classes, dclass))
269 _INDENT();
270 if(ansi_output)
271 kprintf("%s%s:%ld:Leaving %s (result 0x%08lx, %ld)%s\n", ANSI_ESC_FG_BROWN, file, line, function, result, result, ANSI_ESC_CLR);
272 else
273 kprintf("%s:%ld:Leaving %s (result 0x%08lx, %ld)\n", file, line, function, result, result);
277 /****************************************************************************/
279 void _SHOWVALUE(unsigned long dclass, unsigned long dflags, unsigned long value, int size, const char *name, const char *file, int line)
281 if(isFlagSet(debug_classes, dclass) &&
282 isFlagSet(debug_flags, dflags))
284 const char *fmt;
286 switch(size)
288 case 1:
289 fmt = "%s:%ld:%s = %ld, 0x%02lx";
290 break;
292 case 2:
293 fmt = "%s:%ld:%s = %ld, 0x%04lx";
294 break;
296 default:
297 fmt = "%s:%ld:%s = %ld, 0x%08lx";
298 break;
301 _INDENT();
303 if(ansi_output)
304 kprintf(ANSI_ESC_FG_GREEN);
306 kprintf(fmt, file, line, name, value, value);
308 if(size == 1 && value < 256)
310 if(value < ' ' || (value >= 127 && value < 160))
311 kprintf(", '\\x%02lx'", value);
312 else
313 kprintf(", '%lc'", value);
316 if(ansi_output)
317 kprintf("%s\n", ANSI_ESC_CLR);
318 else
319 kprintf("\n");
323 /****************************************************************************/
325 void _SHOWPOINTER(unsigned long dclass, unsigned long dflags, const void *p, const char *name, const char *file, int line)
327 if(isFlagSet(debug_classes, dclass) &&
328 isFlagSet(debug_flags, dflags))
330 const char *fmt;
332 _INDENT();
334 if(p != NULL)
335 fmt = "%s:%ld:%s = 0x%08lx\n";
336 else
337 fmt = "%s:%ld:%s = NULL\n";
339 if(ansi_output)
341 kprintf(ANSI_ESC_FG_GREEN);
342 kprintf(fmt, file, line, name, p);
343 kprintf(ANSI_ESC_CLR);
345 else
346 kprintf(fmt, file, line, name, p);
350 /****************************************************************************/
352 void _SHOWSTRING(unsigned long dclass, unsigned long dflags, const char *string, const char *name, const char *file, int line)
354 if(isFlagSet(debug_classes, dclass) &&
355 isFlagSet(debug_flags, dflags))
357 _INDENT();
359 if(ansi_output)
360 kprintf("%s%s:%ld:%s = 0x%08lx \"%s\"%s\n", ANSI_ESC_FG_GREEN, file, line, name, string, string, ANSI_ESC_CLR);
361 else
362 kprintf("%s:%ld:%s = 0x%08lx \"%s\"\n", file, line, name, string, string);
366 /****************************************************************************/
368 void _SHOWMSG(unsigned long dclass, unsigned long dflags, const char *msg, const char *file, int line)
370 if(isFlagSet(debug_classes, dclass) &&
371 isFlagSet(debug_flags, dflags))
373 _INDENT();
375 if(ansi_output)
376 kprintf("%s%s:%ld:%s%s\n", ANSI_ESC_FG_GREEN, file, line, msg, ANSI_ESC_CLR);
377 else
378 kprintf("%s:%ld:%s\n", file, line, msg);
382 /****************************************************************************/
384 void _DPRINTF(unsigned long dclass, unsigned long dflags, const char *file, int line, const char *format, ...)
386 if((isFlagSet(debug_classes, dclass) && isFlagSet(debug_flags, dflags)) ||
387 (isFlagSet(dclass, DBC_ERROR) || isFlagSet(dclass, DBC_WARNING)))
389 va_list args;
390 static char buf[1024];
392 _INDENT();
394 va_start(args, format);
395 vsnprintf(buf, 1024, format, args);
396 va_end(args);
398 if(ansi_output)
400 const char *highlight = ANSI_ESC_FG_GREEN;
402 switch(dclass)
404 case DBC_CTRACE: highlight = ANSI_ESC_FG_BROWN; break;
405 case DBC_REPORT: highlight = ANSI_ESC_FG_GREEN; break;
406 case DBC_ASSERT: highlight = ANSI_ESC_FG_RED; break;
407 case DBC_TIMEVAL: highlight = ANSI_ESC_FG_GREEN; break;
408 case DBC_DEBUG: highlight = ANSI_ESC_FG_GREEN; break;
409 case DBC_ERROR: highlight = ANSI_ESC_FG_RED; break;
410 case DBC_WARNING: highlight = ANSI_ESC_FG_PURPLE;break;
413 kprintf("%s%s:%ld:%s%s\n", highlight, file, line, buf, ANSI_ESC_CLR);
415 else
416 kprintf("%s:%ld:%s\n", file, line, buf);
420 /****************************************************************************/
422 void _STARTCLOCK(unsigned long dclass, unsigned long dflags, const char *file, const unsigned long line)
424 if(isFlagSet(debug_classes, dclass) &&
425 isFlagSet(debug_flags, dflags))
427 if(timer_level + 1 < NUMCLOCKS)
429 timer_level++;
430 GetSysTime(TIMEVAL(&startTimes[timer_level]));
432 else
433 kprintf("%s:%ld: already %ld clocks in use\n", file, line, NUMCLOCKS);
437 /****************************************************************************/
439 void _STOPCLOCK(unsigned long dclass, unsigned long dflags, const char *file, const unsigned long line, const char *msg)
441 if(isFlagSet(debug_classes, dclass) &&
442 isFlagSet(debug_flags, dflags))
444 if(timer_level >= 0)
446 struct TimeVal stopTime;
448 GetSysTime(TIMEVAL(&stopTime));
449 SubTime(TIMEVAL(&stopTime), TIMEVAL(&startTimes[timer_level]));
450 kprintf("%s:%ld: operation '%s' took %ld.%06ld seconds\n", file, line, msg, stopTime.Seconds, stopTime.Microseconds);
451 timer_level--;
453 else
454 kprintf("%s:%ld: no clocks in use\n", file, line);
458 /****************************************************************************/
460 #endif