diff --git a/source/lib/config.h b/source/lib/config.h index 938f3f9a06..c2af33d43b 100755 --- a/source/lib/config.h +++ b/source/lib/config.h @@ -1,98 +1,136 @@ +#ifndef CONFIG_H_INCLUDED +#define CONFIG_H_INCLUDED + + +//----------------------------------------------------------------------------- +// user-specified configuration choices +//----------------------------------------------------------------------------- + +#undef CONFIG_DISABLE_EXCEPTIONS + +#undef CONFIG_USE_MMGR + + +//----------------------------------------------------------------------------- +// auto-detect OS and platform via predefined macros +//----------------------------------------------------------------------------- + +// get compiler versions with consistent names + format: +// (major*100 + minor), or 0 if not present. note that more than +// one *_VERSION may be non-zero due to interoperability (e.g. ICC with MSC). +// .. ICC +#if defined(__INTEL_COMPILER) +# define ICC_VERSION __INTEL_COMPILER +#else +# define ICC_VERSION 0 +#endif +// .. VC +#ifdef _MSC_VER +# define MSC_VERSION _MSC_VER +#else +# define MSC_VERSION 0 +#endif +// .. GCC +#ifdef __GNUC__ +# define GCC_VERSION (__GNUC__*100 + __GNUC_MINOR__) +#else +# define GCC_VERSION 0 +#endif -// // OS -// - -// Windows +// .. Windows #if defined(_WIN32) || defined(WIN32) # define OS_WIN -# define XP_WIN -// Linux +// .. Linux #elif defined(linux) || defined(__linux) || defined(__linux__) # define OS_LINUX # define OS_UNIX -# ifndef XP_UNIX -# define XP_UNIX -# endif -// Mac OS X +// .. Mac OS X #elif defined(MAC_OS_X # define OS_MACOSX # define OS_UNIX -# define XP_UNIX -// Mac OS 9 or below -#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) -# define OS_MACOS -# define XP_MAC -// BSD +// .. BSD #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) # define OS_BSD -// Solaris +# define OS_UNIX +// .. Solaris #elif defined(SOLARIS) # define OS_SOLARIS -// BeOS +# define OS_UNIX +// .. BeOS #elif defined(__BEOS__) # define OS_BEOS -# define XP_BEOS -// Amiga +// .. Mac OS 9 or below +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +# define OS_MAC +// .. Amiga #elif defined(__amigaos__) # define OS_AMIGA -// Unix-based +// .. Unix-based #elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) # define OS_UNIX -# define XP_UNIX +// .. unknown #else # error "unknown OS - add define here" #endif -#undef HAVE_C99 // compiler advertises support for C99 - -#undef HAVE_ASM - -#undef HAVE_GETTIMEOFDAY -#undef HAVE_X - -#undef HAVE_PCH - -#undef HAVE_DEBUGALLOC - -#undef CONFIG_DISABLE_EXCEPTIONS - +//----------------------------------------------------------------------------- +// auto-detect platform features, given the above information +//----------------------------------------------------------------------------- +// compiler support for C99 +// (this is more convenient than testing __STDC_VERSION__ directly) +#undef HAVE_C99 #ifdef __STDC_VERSION__ // nested #if to avoid ICC warning if not defined # if __STDC_VERSION__ >= 199901L # define HAVE_C99 # endif #endif -#ifdef _MSC_VER -# define HAVE_ASM -# define HAVE_PCH -#endif - -#if defined(_MSC_VER) && defined(HAVE_PCH) && !( defined(NDEBUG) || defined(TESTING) ) -# ifdef SCED -# define HAVE_DEBUGALLOC -# else -# ifndef USE_MMGR -# define HAVE_DEBUGALLOC -# endif -# endif -#endif - +// gettimeofday() +#undef HAVE_GETTIMEOFDAY #ifdef OS_UNIX # define HAVE_GETTIMEOFDAY #endif +// X server +#undef HAVE_X #ifdef OS_LINUX # define HAVE_X #endif - - -// HACK: (please remove when this is no longer necessary) -// The ICC 9.0.006 beta seems to generate buggy code when we redefine new, -// so don't redefine new: -#if defined(__INTEL_COMPILER) && __INTEL_COMPILER == 900 -# undef HAVE_DEBUGALLOC +// __asm{} blocks (Intel syntax) +#undef HAVE_ASM +#if (MSC_VERSION != 0) +# define HAVE_ASM #endif + +// precompiled headers (affects what precompiled.h pulls in; see there) +#undef HAVE_PCH +#if (MSC_VERSION != 0) || (GCC_VERSION > 304) +# define HAVE_PCH +#endif + +// VC debug memory allocator / leak detector +#undef HAVE_VC_DEBUG_ALLOC +#if (MSC_VERSION != 0) +# define HAVE_VC_DEBUG_ALLOC +#endif +// .. only in full-debug mode; +#if defined(NDEBUG) || defined(TESTING) +# undef HAVE_VC_DEBUG_ALLOC +#endif +// .. require PCH, because it makes sure system headers are included before +// redefining new (otherwise, tons of errors result); +#if !defined(HAVE_PCH) +# undef HAVE_VC_DEBUG_ALLOC +#endif +// .. disable on ICC9, because the ICC 9.0.006 beta appears to generate +// incorrect code when we redefine new. +// TODO: remove when no longer necessary +#if ICC_VERSION == 900 +# undef HAVE_VC_DEBUG_ALLOC +#endif + +#endif // #ifndef CONFIG_H_INCLUDED diff --git a/source/lib/debug.cpp b/source/lib/debug.cpp index b518bc0404..7abcc08780 100644 --- a/source/lib/debug.cpp +++ b/source/lib/debug.cpp @@ -21,7 +21,7 @@ #include #include "lib.h" -#include "sysdep/debug.h" +#include "debug.h" #include "nommgr.h" // some functions here are called from within mmgr; disable its hooks // so that our allocations don't cause infinite recursion. @@ -507,8 +507,8 @@ ErrorReaction display_error(const wchar_t* description, int flags, { // disable memory-leak reporting to avoid a flood of warnings // (lots of stuff will leak since we exit abnormally). - debug_disable_leak_reporting(); -#ifdef HAVE_MMGR + debug_heap_enable(DEBUG_HEAP_NONE); +#ifdef CONFIG_USE_MMGR mmgr_set_options(0); #endif diff --git a/source/lib/sysdep/debug.h b/source/lib/debug.h old mode 100755 new mode 100644 similarity index 72% rename from source/lib/sysdep/debug.h rename to source/lib/debug.h index b667721d1e..648bc42d8f --- a/source/lib/sysdep/debug.h +++ b/source/lib/debug.h @@ -1,142 +1,155 @@ -// platform-independent debug interface -// Copyright (c) 2002-2005 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#ifndef DEBUG_H_INCLUDED -#define DEBUG_H_INCLUDED - -#include "sysdep.h" // ErrorReaction -#ifdef _WIN32 -# include "win/wdbg.h" -#else -# include "unix/udbg.h" -#endif - - -// check heap integrity (independently of mmgr). -// errors are reported by the CRT, e.g. via assert. -extern void debug_check_heap(void); - -extern void debug_disable_leak_reporting(); - - -////////////////////////////////////////////////////////////////////////////// -// -// assert -// - -// notify the user that an assertion failed; displays a -// stack trace with local variables. -// returns one of UserErrorReaction. -extern enum ErrorReaction debug_assert_failed(const char* source_file, int line, const char* assert_expr); - -// recommended use: assert2(expr && "descriptive string") -#define assert2(expr)\ -STMT(\ - static unsigned char suppress__ = 0x55;\ - if(suppress__ == 0x55 && !(expr))\ - switch(debug_assert_failed(__FILE__, __LINE__, #expr))\ - {\ - case ER_SUPPRESS:\ - suppress__ = 0xaa;\ - break;\ - case ER_BREAK:\ - debug_break();\ - break;\ - }\ -) - - -////////////////////////////////////////////////////////////////////////////// -// -// output -// - -// write to the debugger output window (may take ~1 ms!) -extern void debug_printf(const char* fmt, ...); -extern void debug_wprintf(const wchar_t* fmt, ...); - -// write to memory buffer (fast) -// used for "last activity" reporting in the crashlog. -extern void debug_wprintf_mem(const wchar_t* fmt, ...); - -// warn of unexpected state. less error-prone than assert(!"text"); -#define debug_warn(str) assert2(0 && (str)) - -// TODO -extern int debug_write_crashlog(const wchar_t* text); - - -////////////////////////////////////////////////////////////////////////////// -// -// breakpoints -// - -// trigger a breakpoint when reached/"called". -// defined as a macro by the platform-specific header above; this allows -// breaking directly into the target function, instead of one frame -// below it as with a conventional call-based implementation. -//#define debug_break() - - -// sometimes mmgr's 'fences' (making sure padding before and after the -// allocation remains intact) aren't enough to catch hard-to-find -// memory corruption bugs. another tool is to trigger a debug exception -// when the later to be corrupted variable is accessed; the problem should -// then become apparent. -// the VC++ IDE provides such 'breakpoints', but can only detect write access. -// additionally, it can't resolve symbols in Release mode (where this would -// be most useful), so we provide a breakpoint API. - -// values chosen to match IA-32 bit defs, so compiler can optimize. -// this isn't required, it'll work regardless. -enum DbgBreakType -{ - DBG_BREAK_CODE = 0, // execute - DBG_BREAK_DATA_WRITE = 1, // write - DBG_BREAK_DATA = 3 // read or write -}; - -// arrange for a debug exception to be raised when is accessed -// according to . -// for simplicity, the length (range of bytes to be checked) is derived -// from addr's alignment, and is typically 1 machine word. -// breakpoints are a limited resource (4 on IA-32); abort and -// return ERR_LIMIT if none are available. -extern int debug_set_break(void* addr, DbgBreakType type); - -// remove all breakpoints that were set by debug_set_break. -// important, since these are a limited resource. -extern int debug_remove_all_breaks(); - - -////////////////////////////////////////////////////////////////////////////// -// -// symbol access -// - -// TODO: rationale+comments - -const size_t DBG_SYMBOL_LEN = 1000; -const size_t DBG_FILE_LEN = 100; - -extern void* debug_get_nth_caller(uint n); - -extern int debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char* file, int* line); - -extern const wchar_t* debug_dump_stack(wchar_t* buf, size_t max_chars, uint skip, void* context); - -#endif // #ifndef DEBUG_H_INCLUDED +// platform-independent debug interface +// Copyright (c) 2002-2005 Jan Wassenberg +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// Contact info: +// Jan.Wassenberg@stud.uni-karlsruhe.de +// http://www.stud.uni-karlsruhe.de/~urkt/ + +#ifndef DEBUG_H_INCLUDED +#define DEBUG_H_INCLUDED + +#include "sysdep/sysdep.h" // ErrorReaction +#ifdef _WIN32 +# include "sysdep/win/wdbg.h" +#else +# include "sysdep/unix/udbg.h" +#endif + + +//----------------------------------------------------------------------------- +// debug memory allocator +//----------------------------------------------------------------------------- + +// check heap integrity (independently of mmgr). +// errors are reported by the CRT, e.g. via assert. +extern void debug_heap_check(void); + +enum DebugHeapChecks +{ + // no automatic checks + DEBUG_HEAP_NONE = 0, + + // default automatic checks when deallocating + DEBUG_HEAP_NORMAL = 1, + + // all automatic checks on every memory API call. this is really + // slow (x100), but reports errors closer to where they occurred. + DEBUG_HEAP_ALL = 2 +}; + +extern void debug_heap_enable(DebugHeapChecks what); + + +//----------------------------------------------------------------------------- +// assert +//----------------------------------------------------------------------------- + +// notify the user that an assertion failed; displays a +// stack trace with local variables. +// returns one of UserErrorReaction. +extern enum ErrorReaction debug_assert_failed(const char* source_file, int line, const char* assert_expr); + +// recommended use: assert2(expr && "descriptive string") +#define assert2(expr)\ +STMT(\ + static unsigned char suppress__ = 0x55;\ + if(suppress__ == 0x55 && !(expr))\ + switch(debug_assert_failed(__FILE__, __LINE__, #expr))\ + {\ + case ER_SUPPRESS:\ + suppress__ = 0xaa;\ + break;\ + case ER_BREAK:\ + debug_break();\ + break;\ + }\ +) + + +//----------------------------------------------------------------------------- +// output +//----------------------------------------------------------------------------- + +// write to the debugger output window (may take ~1 ms!) +extern void debug_printf(const char* fmt, ...); +extern void debug_wprintf(const wchar_t* fmt, ...); + +// write to memory buffer (fast) +// used for "last activity" reporting in the crashlog. +extern void debug_wprintf_mem(const wchar_t* fmt, ...); + +// warn of unexpected state. less error-prone than assert(!"text"); +#define debug_warn(str) assert2(0 && (str)) + +// TODO +extern int debug_write_crashlog(const wchar_t* text); + + +//----------------------------------------------------------------------------- +// breakpoints +//----------------------------------------------------------------------------- + +// trigger a breakpoint when reached/"called". +// defined as a macro by the platform-specific header above; this allows +// breaking directly into the target function, instead of one frame +// below it as with a conventional call-based implementation. +//#define debug_break() + + +// sometimes mmgr's 'fences' (making sure padding before and after the +// allocation remains intact) aren't enough to catch hard-to-find +// memory corruption bugs. another tool is to trigger a debug exception +// when the later to be corrupted variable is accessed; the problem should +// then become apparent. +// the VC++ IDE provides such 'breakpoints', but can only detect write access. +// additionally, it can't resolve symbols in Release mode (where this would +// be most useful), so we provide a breakpoint API. + +// values chosen to match IA-32 bit defs, so compiler can optimize. +// this isn't required, it'll work regardless. +enum DbgBreakType +{ + DBG_BREAK_CODE = 0, // execute + DBG_BREAK_DATA_WRITE = 1, // write + DBG_BREAK_DATA = 3 // read or write +}; + +// arrange for a debug exception to be raised when is accessed +// according to . +// for simplicity, the length (range of bytes to be checked) is derived +// from addr's alignment, and is typically 1 machine word. +// breakpoints are a limited resource (4 on IA-32); abort and +// return ERR_LIMIT if none are available. +extern int debug_set_break(void* addr, DbgBreakType type); + +// remove all breakpoints that were set by debug_set_break. +// important, since these are a limited resource. +extern int debug_remove_all_breaks(); + + +//----------------------------------------------------------------------------- +// symbol access +//----------------------------------------------------------------------------- + +// TODO: rationale+comments + +const size_t DBG_SYMBOL_LEN = 1000; +const size_t DBG_FILE_LEN = 100; + +extern void* debug_get_nth_caller(uint n); + +extern int debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char* file, int* line); + +extern const wchar_t* debug_dump_stack(wchar_t* buf, size_t max_chars, uint skip, void* context); + +#endif // #ifndef DEBUG_H_INCLUDED diff --git a/source/lib/lib.cpp b/source/lib/lib.cpp index 5ce6939626..97ae25ae9b 100755 --- a/source/lib/lib.cpp +++ b/source/lib/lib.cpp @@ -16,13 +16,13 @@ #include "precompiled.h" -#include "lib/types.h" -#include "lib.h" - #include #include #include +#include "lib/types.h" +#include "lib.h" + #include "sysdep/sysdep.h" diff --git a/source/lib/mmgr.cpp b/source/lib/mmgr.cpp index 194e5c34e1..b14faf51ec 100644 --- a/source/lib/mmgr.cpp +++ b/source/lib/mmgr.cpp @@ -21,7 +21,7 @@ // for easy removal in release builds, so that we don't cause any overhead. // note that any application calls to our functions must be removed also, // but this is preferable to stubbing them out here ("least surprise"). -#ifdef USE_MMGR +#ifdef CONFIG_USE_MMGR #include #include @@ -880,7 +880,7 @@ bool mmgr_are_all_valid() // do our check first, because it fails more cleanly // (=> better chance to see where it happened in the debugger) bool all_valid = validate_all(); - debug_check_heap(); + debug_heap_check(); unlock(); return all_valid; } @@ -1408,4 +1408,4 @@ void operator delete[](void* p, const char* file, int line, const char* func) th free_dbg(p, AT_DELETE_ARRAY, file,line,func, 1); } -#endif // #ifdef USE_MMGR +#endif // #ifdef CONFIG_USE_MMGR diff --git a/source/lib/mmgr.h b/source/lib/mmgr.h index c917f6d2bf..20b5bef64e 100644 --- a/source/lib/mmgr.h +++ b/source/lib/mmgr.h @@ -25,7 +25,7 @@ // // note: checking here messes up include guard detection, but we need to // cover both the guarded part (constants+externs) and the macros. -#ifdef USE_MMGR +#ifdef CONFIG_USE_MMGR #ifndef MMGR_H__ #define MMGR_H__ @@ -154,7 +154,7 @@ extern void operator delete[](void* p, const char* file, int line, const char* f #define wcsdup(p) mmgr_wcsdup_dbg(p, __FILE__,__LINE__,__FUNCTION__) #define getcwd(p,size) mmgr_getcwd_dbg(p, size, __FILE__,__LINE__,__FUNCTION__) -#endif // #ifdef USE_MMGR +#endif // #ifdef CONFIG_USE_MMGR // purpose and history diff --git a/source/lib/ogl.cpp b/source/lib/ogl.cpp index f6020deab6..9cc8ba9a3e 100755 --- a/source/lib/ogl.cpp +++ b/source/lib/ogl.cpp @@ -18,16 +18,17 @@ #include "precompiled.h" -#include "lib.h" -#include "sdl.h" -#include "ogl.h" -#include "detect.h" - #include #include #include #include +#include "lib.h" +#include "sdl.h" +#include "ogl.h" +#include "detect.h" +#include "debug.h" + #ifdef _MSC_VER #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glu32.lib") diff --git a/source/lib/precompiled.h b/source/lib/precompiled.h index 4b0ae1af88..6fd59219f6 100755 --- a/source/lib/precompiled.h +++ b/source/lib/precompiled.h @@ -8,19 +8,18 @@ // // this policy yields the best compile performance with or without PCH. -#include "config.h" -#include "lib/types.h" - #ifdef _MSC_VER #pragma warning(disable:4996) // function is deprecated #pragma warning(disable:4786) // identifier truncated to 255 chars #endif -// make string_s (secure CRT string functions) available everywhere -#include "lib/string_s.h" +// make these available everywhere for convenience: +#include "lib/config.h" +#include "lib/types.h" +#include "lib/string_s.h" // CRT secure string +#include "lib/debug.h" +#include "ps/Pyrogenesis.h" // MICROLOG and old error system -// make MICROLOG and the old error system available everywhere -#include "Pyrogenesis.h" // // memory headers @@ -100,7 +99,7 @@ #include "ps/CStr.h" // Some other external libraries that are used in several places: -#include "jsapi.h" +#include "scripting/SpiderMonkey.h" #include "boost/shared_ptr.hpp" #include "boost/weak_ptr.hpp" @@ -118,8 +117,11 @@ // manually #including from every file, but requires that all system // headers containing "new", "malloc" etc. come before this (see above). +// use custom memory tracker (lib/mmgr.cpp) +#if defined(CONFIG_USE_MMGR) +# include "mmgr.h" // use VC debug heap (superceded by mmgr; it remains for completeness) -#ifdef HAVE_DEBUGALLOC +#elif defined(HAVE_VC_DEBUG_ALLOC) // can't define _CRTDBG_MAP_ALLOC because crtdbg.h has a broken 'new', // so manually redefine the appropriate functions. # define new new(_NORMAL_BLOCK, __FILE__, __LINE__) @@ -127,9 +129,4 @@ # define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__) # define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) # define free(p) _free_dbg(p, _NORMAL_BLOCK) -#endif // #ifdef HAVE_DEBUGALLOC - -// use custom memory tracker (lib/mmgr.cpp) -#ifdef USE_MMGR -# include "mmgr.h" #endif diff --git a/source/lib/res/h_mgr.cpp b/source/lib/res/h_mgr.cpp index cd2a359c3e..3c92023331 100755 --- a/source/lib/res/h_mgr.cpp +++ b/source/lib/res/h_mgr.cpp @@ -179,7 +179,7 @@ static HDATA* h_data_from_idx(const i32 idx) { // makes things *crawl*! #ifdef PARANOIA - debug_check_heap(); + debug_heap_check(); #endif // don't compare against last_in_use - this is called before allocating diff --git a/source/lib/string_s.cpp b/source/lib/string_s.cpp index 45f88c064b..dc93d7fbf1 100644 --- a/source/lib/string_s.cpp +++ b/source/lib/string_s.cpp @@ -18,11 +18,11 @@ #include "precompiled.h" +#include + #include "lib.h" #include "posix.h" // SIZE_MAX -#include - #ifndef PERFORM_SELF_TEST #define PERFORM_SELF_TEST 0 #endif diff --git a/source/lib/sysdep/sysdep.h b/source/lib/sysdep/sysdep.h index 12a2ac73e5..c29176d219 100755 --- a/source/lib/sysdep/sysdep.h +++ b/source/lib/sysdep/sysdep.h @@ -3,13 +3,10 @@ #include "config.h" -#include "sysdep/debug.h" - -#ifdef _WIN32 -#include "win/win.h" -#include "win/wdbg.h" +#if defined(OS_WIN) +# include "win/win.h" #elif defined(OS_UNIX) -#include "unix/unix.h" +# include "unix/unix.h" #endif #ifdef __cplusplus @@ -26,8 +23,6 @@ extern int vsnprintf2(char* buffer, size_t count, const char* format, va_list ar #endif - - enum DisplayErrorFlags { DE_ALLOW_SUPPRESS = 1, @@ -58,14 +53,16 @@ enum ErrorReaction ER_EXIT }; - extern ErrorReaction display_error_impl(const wchar_t* text, int flags); -#define DISPLAY_ERROR(text) display_error(text, 0, 0, 0, __FILE__, __LINE__) - extern ErrorReaction display_error(const wchar_t* text, int flags, uint skip, void* context, const char* file, int line); +// convenience version, in case the advanced parameters aren't needed. +// done this way instead of with default values so that it also works in C. +#define DISPLAY_ERROR(text) display_error(text, 0, 0, 0, __FILE__, __LINE__) + + extern void display_msg(const char* caption, const char* msg); extern void wdisplay_msg(const wchar_t* caption, const wchar_t* msg); diff --git a/source/lib/sysdep/unix/udbg.cpp b/source/lib/sysdep/unix/udbg.cpp index 2a5f11809d..67053ea23c 100755 --- a/source/lib/sysdep/unix/udbg.cpp +++ b/source/lib/sysdep/unix/udbg.cpp @@ -338,23 +338,6 @@ int debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char* file, int* } #include "mmgr.h" -int debug_write_crashlog(const char* file, wchar_t* header, void* context) -{ - // TODO: Do this properly. (I don't know what I'm doing; I just - // know that this function is required in order to compile...) - - abort(); -} - - -void debug_check_heap() -{ - // TODO: Do this properly. (I don't know what I'm doing; I just - // know that this function is required in order to compile...) -} - - - void debug_printf(const char* fmt, ...) { va_list args; @@ -364,8 +347,34 @@ void debug_printf(const char* fmt, ...) fflush(stdout); } +// TODO: Do these properly. (I don't know what I'm doing; I just +// know that these functions are required in order to compile...) -void debug_disable_leak_reporting() +int debug_write_crashlog(const char* file, wchar_t* header, void* context) +{ + abort(); +} + + + + +void debug_heap_check() +{ +} + + +// if is true or PARANOIA #defined, all possible checks are +// performed as often as possible. this is really slow (we are talking x100), +// but reports errors closer to where they occurred. +void debug_heap_enable(bool full_monty) +{ +#ifdef PARANOIA + full_monty = true; +#endif +} + + +// disable all automatic checks until the next debug_heap_enable. +void debug_heap_disable() { - } diff --git a/source/lib/sysdep/unix/unix.h b/source/lib/sysdep/unix/unix.h index cc65d0dbdd..96c54411cb 100644 --- a/source/lib/sysdep/unix/unix.h +++ b/source/lib/sysdep/unix/unix.h @@ -1,6 +1,4 @@ #ifndef sysdep_unix_unix_h__ #define sysdep_unix_unix_h__ -#include "udbg.h" - #endif diff --git a/source/lib/sysdep/win/wdbg.cpp b/source/lib/sysdep/win/wdbg.cpp index 3a1556e3a9..7c3eedcde4 100755 --- a/source/lib/sysdep/win/wdbg.cpp +++ b/source/lib/sysdep/win/wdbg.cpp @@ -138,7 +138,11 @@ void debug_wprintf(const wchar_t* fmt, ...) } -void debug_check_heap() +//----------------------------------------------------------------------------- +// debug memory allocator +//----------------------------------------------------------------------------- + +void debug_heap_check() { __try { @@ -149,16 +153,33 @@ void debug_check_heap() } } -void debug_disable_leak_reporting() + +void debug_heap_enable(DebugHeapChecks what) { -#ifdef HAVE_DEBUGALLOC +#ifdef HAVE_VC_DEBUG_ALLOC uint flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - _CrtSetDbgFlag(flags & ~_CRTDBG_LEAK_CHECK_DF); -#endif + switch(what) + { + case DEBUG_HEAP_NONE: + flags = 0; + break; + case DEBUG_HEAP_NORMAL: + flags |= _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF; + break; + case DEBUG_HEAP_ALL: + flags |= _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_DELAY_FREE_MEM_DF | + _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF; + break; + default: + assert2("debug_heap_enable: invalid what"); + } + _CrtSetDbgFlag(flags); +#endif // HAVE_DEBUGALLOC } -////////////////////////////////////////////////////////////////////////////// + +//----------------------------------------------------------------------------- // to avoid deadlock, be VERY CAREFUL to avoid anything that may block, diff --git a/source/lib/sysdep/win/win.cpp b/source/lib/sysdep/win/win.cpp index c9ebc6977a..058719e210 100755 --- a/source/lib/sysdep/win/win.cpp +++ b/source/lib/sysdep/win/win.cpp @@ -34,25 +34,10 @@ #pragma comment(lib, "shell32.lib") // for pick_directory SH* calls #endif -void sle(int x) -{ - SetLastError((DWORD)x); -} +char win_sys_dir[MAX_PATH+1]; +char win_exe_dir[MAX_PATH+1]; -#ifdef HAVE_DEBUGALLOC -// Enable heap corruption checking after every allocation. Has the same -// effect as PARANOIA in pre_main_init, but lets you switch it on anywhere -// so that you can skip checking the whole of the initialisation code. -// The debugger will break in the allocation just after the one that -// corrupted the heap, so check its ID and then _CrtSetBreakAlloc(...) -// on the previous one and try again. -// Warning: This makes things rather slow. -void memory_debug_extreme_turbo_plus() -{ - _CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_DELAY_FREE_MEM_DF ); -} -#endif // we need to know the app's main window for the error dialog, so that @@ -92,6 +77,7 @@ HWND win_get_app_main_window() } +//----------------------------------------------------------------------------- // // safe allocator that may be used independently of libc malloc @@ -112,9 +98,7 @@ void win_free(void* p) } -char win_sys_dir[MAX_PATH+1]; -char win_exe_dir[MAX_PATH+1]; - +//----------------------------------------------------------------------------- // // these override the portable versions in sysdep.cpp @@ -201,16 +185,12 @@ int pick_directory(char* path, size_t buf_size) -////////////////////////////////////////////////////////////////////////////// -// +//----------------------------------------------------------------------------- // "program error" dialog (triggered by assert and exception) -// -////////////////////////////////////////////////////////////////////////////// +//----------------------------------------------------------------------------- -// // support for resizing the dialog / its controls // (have to do this manually - grr) -// static POINTS dlg_client_origin; static POINTS dlg_prev_client_size; @@ -411,11 +391,9 @@ ErrorReaction display_error_impl(const wchar_t* text, int flags) } -/////////////////////////////////////////////////////////////////////////////// -// +//----------------------------------------------------------------------------- // clipboard -// -/////////////////////////////////////////////////////////////////////////////// +//----------------------------------------------------------------------------- int clipboard_set(const wchar_t* text) { @@ -566,11 +544,9 @@ static void call_func_tbl(_PIFV* begin, _PIFV* end) } -/////////////////////////////////////////////////////////////////////////////// -// +//----------------------------------------------------------------------------- // locking for win-specific code -// -/////////////////////////////////////////////////////////////////////////////// +//----------------------------------------------------------------------------- // several init functions are before called before _cinit. // POSIX static mutex init may not have been done by then, @@ -623,11 +599,9 @@ static void cs_shutdown() } -/////////////////////////////////////////////////////////////////////////////// -// +//----------------------------------------------------------------------------- // startup -// -/////////////////////////////////////////////////////////////////////////////// +//----------------------------------------------------------------------------- // entry -> pre_libc -> WinMainCRTStartup -> WinMain -> pre_main -> main // at_exit is called as the last of the atexit handlers @@ -652,17 +626,13 @@ static #endif void win_pre_main_init() { -#ifdef HAVE_DEBUGALLOC - uint flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - // Always enable leak detection in debug builds - flags |= _CRTDBG_LEAK_CHECK_DF; + // enable memory tracking and leak detection; + // no effect if !defined(HAVE_VC_DEBUG_ALLOC). #ifdef PARANOIA - // force malloc et al. to check the heap every call. - // slower, but reports errors closer to where they occur. - flags |= _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_DELAY_FREE_MEM_DF; -#endif // PARANOIA - _CrtSetDbgFlag(flags); -#endif // HAVE_DEBUGALLOC + debug_heap_enable(DEBUG_HEAP_ALL); +#else + debug_heap_enable(DEBUG_HEAP_NORMAL); +#endif call_func_tbl(pre_main_begin, pre_main_end); diff --git a/source/lib/sysdep/win/win_internal.h b/source/lib/sysdep/win/win_internal.h index b4bbd7dbf0..68d1d80e74 100755 --- a/source/lib/sysdep/win/win_internal.h +++ b/source/lib/sysdep/win/win_internal.h @@ -346,6 +346,8 @@ extern "C" { extern _CRTIMP intptr_t _get_osfhandle(int); extern _CRTIMP int _open_osfhandle(intptr_t, int); extern _CRTIMP int _open(const char* fn, int mode, ...); +extern _CRTIMP int _read (int fd, void* buf, size_t nbytes); +extern _CRTIMP int _write(int fd, void* buf, size_t nbytes); extern _CRTIMP int _close(int); extern _CRTIMP char* _getcwd(char*, size_t); diff --git a/source/lib/sysdep/win/wposix.cpp b/source/lib/sysdep/win/wposix.cpp index e0271a2a06..020ceb835c 100755 --- a/source/lib/sysdep/win/wposix.cpp +++ b/source/lib/sysdep/win/wposix.cpp @@ -125,6 +125,22 @@ debug_printf("close %d\n", fd); } +// we don't want to #define read to _read, since that's a fairly common +// identifier. therefore, translate from MS CRT names via thunk functions. +// efficiency is less important, and the overhead could be optimized away. + +int read(int fd, void* buf, size_t nbytes) +{ + return _read(fd, buf, nbytes); +} + +int write(int fd, void* buf, size_t nbytes) +{ + return _write(fd, buf, nbytes); +} + + + int ioctl(int fd, int op, int* data) { const HANDLE h = cast_to_HANDLE(_get_osfhandle(fd)); diff --git a/source/lib/sysdep/win/wposix.h b/source/lib/sysdep/win/wposix.h index 678b424645..b8a6c71d3f 100755 --- a/source/lib/sysdep/win/wposix.h +++ b/source/lib/sysdep/win/wposix.h @@ -257,11 +257,9 @@ extern int open(const char* fn, int mode, ...); // MS implementation doesn't support this distinction. // hence, the file is reported executable if it exists. -#define read _read -#define write _write -_CRTIMP int read(int, void*, size_t); -_CRTIMP int write(int, void*, size_t); -_CRTIMP off_t lseek(int fd, off_t ofs, int whence); +extern int read (int fd, void* buf, size_t nbytes); // thunk +extern int write(int fd, void* buf, size_t nbytes); // thunk +extern _CRTIMP off_t lseek(int fd, off_t ofs, int whence); // redefinition error here => io.h is getting included somewhere. @@ -269,7 +267,7 @@ _CRTIMP off_t lseek(int fd, off_t ofs, int whence); // compiling against the DLL CRT. either rename the io.h def // (as with vc_stat), or don't include io.h. extern int close(int); -_CRTIMP int access(const char*, int); +extern _CRTIMP int access(const char*, int); extern int chdir(const char*); #undef getcwd diff --git a/source/lib/timer.h b/source/lib/timer.h index 90ced472a3..aef958f3d4 100755 --- a/source/lib/timer.h +++ b/source/lib/timer.h @@ -21,7 +21,7 @@ #include -#include "sysdep/debug.h" // debug_printf +#include "debug.h" // debug_printf #ifdef __cplusplus extern "C" {