Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / compiler / arossupport / include / debug.h
blobd009409d183750bf844b7aea143c2097427ad087
1 /*
2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
3 $Id$
5 Debugging macros.
6 This include file can be included several times!
7 */
9 #ifndef CLIB_AROSSUPPORT_PROTOS_H
10 # include <proto/arossupport.h>
11 #endif
12 #ifndef PROTO_EXEC_H
13 # include <proto/exec.h> /* For FindTask() */
14 #endif
15 #ifndef EXEC_TASKS_H
16 # include <exec/tasks.h>
17 #endif
18 #ifndef EXEC_ALERTS_H
19 # include <exec/alerts.h>
20 #endif
22 #include <string.h>
24 #ifndef DEBUG
25 # define DEBUG 0
26 #endif
27 #ifndef SDEBUG
28 # define SDEBUG 0
29 #endif
30 #ifndef ADEBUG
31 # define ADEBUG 0
32 #endif
33 #ifndef MDEBUG
34 # define MDEBUG 0
35 #endif
38 /* Remove all macros. They get new values each time this file is
39 included */
40 #undef D
41 #undef DB2
42 #undef ReturnVoid
43 #undef ReturnPtr
44 #undef ReturnStr
45 #undef ReturnInt
46 #undef ReturnXInt
47 #undef ReturnFloat
48 #undef ReturnSpecial
49 #undef ReturnBool
52 /* Macros for "stair debugging" */
53 #undef SDInit
54 #undef EnterFunc
55 #undef Indent
56 #undef ExitFunc
58 /* StegerG */
59 #undef SDEBUG
60 #define SDEBUG 0
62 #if SDEBUG
64 # ifndef SDEBUG_INDENT
65 # define SDEBUG_INDENT 2
66 # endif
68 /* This is some new macros for making debug output more readable,
69 ** by indenting for each functioncall made.
70 ** Usage: Call the SDInit() macro before anything else in your main().
71 ** Start the functions you want to debug with EnterFunc(bug("something"))
72 ** and ALWAYS match these with a Returnxxxx type macro
73 ** at the end of the func.
74 ** Inside the func you can use the normal D(bug()) macro.
76 ** To enable the macros, just add a #define SDEBUG 1
79 /* User macro */
80 #define EnterFunc(x) do { \
81 struct Task *sd_task = FindTask(NULL); \
82 int sd_spaceswritten; \
83 for (sd_spaceswritten = 0; sd_spaceswritten < (ULONG)sd_task->tc_UserData; sd_spaceswritten ++) kprintf(" "); \
84 ((ULONG)sd_task->tc_UserData) += SDEBUG_INDENT; } while(0); \
88 /* User macro. Add into start of your main() routine */
89 # define SDInit() \
90 do { FindTask(NULL)->tc_UserData = NULL; } while(0)
93 /* Internal */
94 # define Indent do { \
95 struct Task *sd_task = FindTask(NULL); \
96 int sd_spaceswritten; \
97 for (sd_spaceswritten = 0; sd_spaceswritten < (ULONG)sd_task->tc_UserData; sd_spaceswritten ++) kprintf(" "); } while(0)
99 /* Internal */
100 #define ExitFunc do { \
101 struct Task *sd_task = FindTask(NULL); \
102 int sd_spaceswritten; \
103 ((ULONG)sd_task->tc_UserData) -= SDEBUG_INDENT; \
104 for (sd_spaceswritten = 0; sd_spaceswritten < (ULONG)sd_task->tc_UserData; sd_spaceswritten ++) kprintf(" "); } while(0)
106 #else
108 # define SDInit()
109 # define Indent
110 # define EnterFunc(x...) D(x)
111 # define ExitFunc
113 #endif /* SDEBUG */
117 /* Sanity check macros
119 * ASSERT(x)
120 * Do nothing if the expression <x> evalutates to a
121 * non-zero value, output a debug message otherwise.
123 * ASSERT_VALID_PTR(x)
124 * Checks that the expression <x> points to a valid memory location, and
125 * outputs a debug message otherwise. A NULL pointer is considered INVALID.
127 * ASSERT_VALID_PTR_OR_NULL(x)
128 * Checks that the expression <x> points to a valid memory location or that
129 * it is NULL, and outputs a debug message otherwise. A NULL pointer is
130 * considered VALID.
132 * ASSERT_VALID_TASK(t)
133 * Checks that the pointer <t> points to a valid Task
134 * structure and outputs a debug message otherwise.
136 * ASSERT_VALID_PROCESS(p)
137 * Checks that the pointer <p> points to a valid Process
138 * structure and outputs a debug message otherwise.
140 * KASSERT(x)
141 * Do nothing if the expression <x> evalutates to a
142 * non-zero value, output a debug message, and cause an
143 * Alert() otherwise. This should only be used in kernel code.
146 #undef DBPRINTF
147 #undef THIS_FILE
148 #undef ASSERT
149 #undef ASSERT_VALID_PTR
150 #undef ASSERT_VALID_PTR_OR_NULL
151 #undef ASSERT_VALID_TASK
152 #undef ASSERT_VALID_PROCESS
154 #if ADEBUG
156 #define DBPRINTF kprintf
158 /* The trick with THIS_FILE allows us to reuse the same static string
159 * instead of allocating a new copy for each invocation of these macros.
161 #define THIS_FILE __FILE__
163 #define ASSERT(x) do { \
164 (x) ? 0 : \
165 ( DBPRINTF("\x07%s:%ld: assertion failed: %s\n", \
166 THIS_FILE, __LINE__, #x) ); \
167 } while(0)
169 #define ASSERT_VALID_PTR(x) do { \
170 (((IPTR)(x) > 1024) && \
171 TypeOfMem((APTR)(x))) ? 0 : \
172 ( DBPRINTF("\x07%s, %ld: bad pointer: %s = $%lx\n", \
173 THIS_FILE, __LINE__, #x, (APTR)(x)) ); \
174 } while(0)
176 #define ASSERT_VALID_PTR_OR_NULL(x) do { \
177 ((((APTR)(x)) == NULL) || \
178 (((IPTR)(x) > 1024) && TypeOfMem((APTR)(x)))) ? 0 : \
179 ( DBPRINTF("\x07%s:%ld: bad pointer: %s = $%lx\n", \
180 THIS_FILE, __LINE__, #x, (APTR)(x)) ); \
181 } while(0)
183 #define ASSERT_VALID_TASK(t) do { \
184 ASSERT_VALID_PTR(t); \
185 ASSERT((((t)->tc_Node.ln_Type == NT_TASK) || \
186 (t)->tc_Node.ln_Type == NT_PROCESS)); \
187 } while(0)
189 #define ASSERT_VALID_PROCESS(p) do { \
190 ASSERT_VALID_PTR(p); \
191 ASSERT((p)->pr_Task.tc_Node.ln_Type == NT_PROCESS); \
192 } while(0)
194 #define KASSERT(x) do { \
195 (x) ? 0 : \
196 ( DBPRINTF("\x07%s:%ld: assertion failed: %s\n", \
197 THIS_FILE, __LINE__, #x), Alert(AG_BadParm) ); \
198 } while(0)
200 #else /* !ADEBUG */
202 # define ASSERT(x)
203 # define ASSERT_VALID_PTR(x)
204 # define ASSERT_VALID_PTR_OR_NULL(x)
205 # define ASSERT_VALID_TASK(t)
206 # define ASSERT_VALID_PROCESS(p)
207 # define KASSERT(x)
209 #endif /* ADEBUG */
212 /* Memory munging macros
215 /* MUNGWALL_SIZE must be a multiple of MEMCHUNK_TOTAL, otherwise for example
216 rom/exec/allocate complains, because the return value (memory pointer) of
217 AllocMem would not be a multiple of MEMCHUNK_TOTAL anymore.
219 See rom/exec/allocmem and rom/exec/freemem for more info.
221 The "32 *" probably makes sure that you get a multiple of MEMCHUNK_TOTAL on
222 every machine, because on 32 bit machines MEMCHUNK_TOTAL will be 8 and
223 on 64 bit machines it will be 16, and it would even work on 128 bit machines
224 because I guess there MEMCHUNK_TOTAL will be 32 */
226 #define MUNGWALL_SIZE (32 * 1)
228 #define MUNGWALLHEADER_SIZE 32
230 #if AROS_SIZEOFULONG == 4
231 # define MEMFILL_FREE 0xDEADBEEFL
232 # define MEMFILL_ALLOC 0xC0DEDBADL
233 # define MEMFILL_WALL 0xABADC0DEL
234 #elif AROS_SIZEOFULONG == 8
235 # define MEMFILL_FREE 0xDEADBEEFDEADBEEFL
236 # define MEMFILL_ALLOC 0xC0DEDBADC0DEDBADL
237 # define MEMFILL_WALL 0xABADC0DEABADC0DEL
238 #else
239 # error sizeof ULONG is neither 4 nor 8 in this architecture
240 #endif
242 #undef MUNGE_BLOCK
244 #if MDEBUG
245 /* Fill the memory block pointed by <ptr> of size <size> with <fill>
247 # define MUNGE_BLOCK(ptr, fill, size) do { \
248 ULONG *__p = (ULONG *)(ptr); \
249 ULONG __s = (size) / sizeof(ULONG); \
250 while (__s--) *__p++ = (fill); \
251 } while(0)
253 /* Build a wall over the memory block <ptr> of size <size> with <fill> bricks.
255 # define BUILD_WALL(ptr, fill, size) do { \
256 memset((ptr), (fill), (size)); \
257 } while(0)
259 /* Check the integrity of the wall <ptr> of size <size> bytes containing <fill>.
261 # define CHECK_WALL(ptr, fill, size) do { \
262 UBYTE *__p = (UBYTE *)(ptr); \
263 size_t __s = (size); \
264 while (__s--) \
266 if(*__p != (fill)) \
268 struct Task *__t = FindTask(NULL); \
269 kprintf("\x07" "Broken wall detected at %s:%d at 0x%x, " \
270 "Task: 0x%x, Name: %s\n", \
271 __FUNCTION__, __LINE__, \
272 __p, __t, __t->tc_Node.ln_Name);\
274 __p++; \
276 } while(0)
278 # define MungWallCheck() AvailMem(MEMF_CLEAR)
279 #else
281 # define MUNGE_BLOCK(ptr, size, fill)
282 # define CHECK_WALL(ptr, fill, size)
283 # define MungWallCheck()
285 #endif /* MDEBUG */
288 #if DEBUG
289 # define D(x...) Indent x
291 # if DEBUG > 1
292 # define DB2(x...) x
293 # else
294 # define DB2(x...) /* eps */
295 # endif
297 /* return-macros. NOTE: I make a copy of the value in __aros_val, because
298 the return-value might have side effects (like return x++;). */
299 # define ReturnVoid(name) { ExitFunc kprintf ("Exit " name "()\n"); return; }
300 # define ReturnPtr(name,type,val) { type __aros_val = (type)val; \
301 ExitFunc kprintf ("Exit " name "=%08lx\n", \
302 (ULONG)__aros_val); return __aros_val; }
303 # define ReturnStr(name,type,val) { type __aros_val = (type)val; \
304 ExitFunc kprintf ("Exit " name "=\"%s\"\n", \
305 __aros_val); return __aros_val; }
306 # define ReturnInt(name,type,val) { type __aros_val = (type)val; \
307 ExitFunc kprintf ("Exit " name "=%ld\n", \
308 (ULONG)__aros_val); return __aros_val; }
309 # define ReturnXInt(name,type,val) { type __aros_val = (type)val; \
310 ExitFunc kprintf ("Exit " name "=%lx\n", \
311 (ULONG)__aros_val); return __aros_val; }
312 # define ReturnFloat(name,type,val) { type __aros_val = (type)val; \
313 ExitFunc kprintf ("Exit " name "=%g\n", \
314 (ULONG)__aros_val); return __aros_val; }
315 # define ReturnSpecial(name,type,val,fmt) { type __aros_val = (type)val; \
316 ExitFunc kprintf ("Exit " name "=" fmt "\n", \
317 (ULONG)__aros_val); return __aros_val; }
318 # define ReturnBool(name,val) { BOOL __aros_val = (val != 0); \
319 ExitFunc kprintf ("Exit " name "=%s\n", \
320 __aros_val ? "TRUE" : "FALSE"); \
321 return __aros_val; }
322 #else /* !DEBUG */
323 # define D(x...) /* eps */
324 # define DB2(x...) /* eps */
326 # define ReturnVoid(name) return
327 # define ReturnPtr(name,type,val) return val
328 # define ReturnStr(name,type,val) return val
329 # define ReturnInt(name,type,val) return val
330 # define ReturnXInt(name,type,val) return val
331 # define ReturnFloat(name,type,val) return val
332 # define ReturnSpecial(name,type,val,fmt) return val
333 # define ReturnBool(name,val) return val
334 #endif /* DEBUG */
336 #undef CHECK_STACK
337 #if AROS_STACK_DEBUG
339 I don't want to care about word length here because ULONG is a part of IPTR and
340 ULONG test will do here on 64-bit machines too.
342 TODO: This doesn't work for 'Reversed' stack (growing upwards). If someone will ever
343 work on such an architecture (SPARC ???) he'll have to fix it.
345 #define CHECK_STACK \
347 struct Task *me = FindTask(NULL); \
349 ULONG *stktop = me->tc_SPLower; \
351 if (stktop && (*stktop != 0xE1E1E1E1)) \
352 bug("STACK OVERFLOW in %s, line %d\n", __FILE__, __LINE__); \
354 #else
355 #define CHECK_STACK
356 #endif
358 #ifndef AROS_DEBUG_H
359 #define AROS_DEBUG_H
361 #define bug kprintf
362 #define rbug(main,sub,lvl,fmt,args...) \
363 rkprintf (DBG_MAINSYSTEM_ ## main, \
364 DBG_ ## main ## _SUBSYSTEM_ ## sub, \
365 lvl, fmt, ##args)
367 /* Debugging constants. These should be defined outside and this
368 part should be generated. */
369 #define DBG_MAINSYSTEM_INTUITION "intuition"
370 #define DBG_INTUITION_SUBSYSTEM_INPUTHANDLER "inputhandler"
372 #define AROS_FUNCTION_NOT_IMPLEMENTED(library) \
373 kprintf("The function %s/%s() is not implemented.\n", (library), __FUNCTION__)
375 #define AROS_METHOD_NOT_IMPLEMENTED(CLASS, name) \
376 kprintf("The method %s::%s() is not implemented.\n", (CLASS), (name))
378 #define aros_print_not_implemented(name) \
379 kprintf("The function %s() is not implemented.\n", (name))
381 #define ALIVE kprintf("%s - %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
383 #endif /* AROS_DEBUG_H */