aboutsummaryrefslogtreecommitdiff
path: root/src/debug.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug.h')
-rw-r--r--src/debug.h176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/debug.h b/src/debug.h
new file mode 100644
index 000000000..014456c0a
--- /dev/null
+++ b/src/debug.h
@@ -0,0 +1,176 @@
+/*
+(c) 2010 Perttu Ahola <celeron55@gmail.com>
+*/
+
+/*
+ Debug stack and assertion
+*/
+
+#ifndef DEBUG_HEADER
+#define DEBUG_HEADER
+
+#include <stdio.h>
+#include <jmutex.h>
+#include <jmutexautolock.h>
+#include <iostream>
+#include "common_irrlicht.h"
+
+/*
+ Compatibility stuff
+*/
+
+#if (defined(WIN32) || defined(_WIN32_WCE))
+typedef DWORD threadid_t;
+#define __NORETURN __declspec(noreturn)
+#define __FUNCTION_NAME __FUNCTION__
+#else
+typedef pthread_t threadid_t;
+#define __NORETURN __attribute__ ((__noreturn__))
+#define __FUNCTION_NAME __PRETTY_FUNCTION__
+#endif
+
+inline threadid_t get_current_thread_id()
+{
+#if (defined(WIN32) || defined(_WIN32_WCE))
+ return GetCurrentThreadId();
+#else
+ return pthread_self();
+#endif
+}
+
+/*
+ Debug output
+*/
+
+#define DEBUGSTREAM_COUNT 2
+
+extern FILE *g_debugstreams[DEBUGSTREAM_COUNT];
+
+extern void debugstreams_init(bool disable_stderr, const char *filename);
+extern void debugstreams_deinit();
+
+#define DEBUGPRINT(...)\
+{\
+ for(int i=0; i<DEBUGSTREAM_COUNT; i++)\
+ {\
+ if(g_debugstreams[i] != NULL){\
+ fprintf(g_debugstreams[i], __VA_ARGS__);\
+ fflush(g_debugstreams[i]);\
+ }\
+ }\
+}
+
+class Debugbuf : public std::streambuf
+{
+public:
+ Debugbuf(bool disable_stderr)
+ {
+ m_disable_stderr = disable_stderr;
+ }
+
+ int overflow(int c)
+ {
+ for(int i=0; i<DEBUGSTREAM_COUNT; i++)
+ {
+ if(g_debugstreams[i] == stderr && m_disable_stderr)
+ continue;
+ if(g_debugstreams[i] != NULL)
+ fwrite(&c, 1, 1, g_debugstreams[i]);
+ //TODO: Is this slow?
+ fflush(g_debugstreams[i]);
+ }
+
+ return c;
+ }
+ int xsputn(const char *s, int n)
+ {
+ for(int i=0; i<DEBUGSTREAM_COUNT; i++)
+ {
+ if(g_debugstreams[i] == stderr && m_disable_stderr)
+ continue;
+ if(g_debugstreams[i] != NULL)
+ fwrite(s, 1, n, g_debugstreams[i]);
+ //TODO: Is this slow?
+ fflush(g_debugstreams[i]);
+ }
+
+ return n;
+ }
+
+private:
+ bool m_disable_stderr;
+};
+
+// This is used to redirect output to /dev/null
+class Nullstream : public std::ostream {
+public:
+ Nullstream():
+ std::ostream(0)
+ {
+ }
+private:
+};
+
+extern Debugbuf debugbuf;
+extern std::ostream dstream;
+extern std::ostream dstream_no_stderr;
+extern Nullstream dummyout;
+
+/*
+ Assert
+*/
+
+__NORETURN extern void assert_fail(
+ const char *assertion, const char *file,
+ unsigned int line, const char *function);
+
+#define ASSERT(expr)\
+ ((expr)\
+ ? (void)(0)\
+ : assert_fail(#expr, __FILE__, __LINE__, __FUNCTION_NAME))
+
+#define assert(expr) ASSERT(expr)
+
+/*
+ DebugStack
+*/
+
+#define DEBUG_STACK_SIZE 50
+#define DEBUG_STACK_TEXT_SIZE 300
+
+struct DebugStack
+{
+ DebugStack(threadid_t id);
+ void print(FILE *file, bool everything);
+
+ threadid_t threadid;
+ char stack[DEBUG_STACK_SIZE][DEBUG_STACK_TEXT_SIZE];
+ int stack_i; // Points to the lowest empty position
+ int stack_max_i; // Highest i that was seen
+};
+
+extern core::map<threadid_t, DebugStack*> g_debug_stacks;
+extern JMutex g_debug_stacks_mutex;
+
+extern void debug_stacks_init();
+extern void debug_stacks_print();
+
+class DebugStacker
+{
+public:
+ DebugStacker(const char *text);
+ ~DebugStacker();
+
+private:
+ DebugStack *m_stack;
+ bool m_overflowed;
+};
+
+#define DSTACK(...)\
+ char __buf[DEBUG_STACK_TEXT_SIZE];\
+ snprintf(__buf,\
+ DEBUG_STACK_TEXT_SIZE, __VA_ARGS__);\
+ DebugStacker __debug_stacker(__buf);
+
+#endif
+