X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5c9226425091564c526b61ea557ecec151d84637..c5c04fabb02c27bcc8115bff024d74ddd48f8175:/src/common/log.cpp diff --git a/src/common/log.cpp b/src/common/log.cpp index 3dfb000b32..c51d5c62bf 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -6,7 +6,7 @@ // Created: 29/01/98 // RCS-ID: $Id$ // Copyright: (c) 1998 Vadim Zeitlin -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -36,6 +36,7 @@ #if wxUSE_GUI #include "wx/window.h" + #include "wx/msgdlg.h" #ifdef __WXMSW__ #include "wx/msw/private.h" #endif @@ -88,7 +89,10 @@ #define LOG_BUFFER_SIZE (4096) // static buffer for error messages -static wxChar s_szBuf[LOG_BUFFER_SIZE]; +static wxChar s_szBufStatic[LOG_BUFFER_SIZE]; + +static wxChar *s_szBuf = s_szBufStatic; +static size_t s_szBufSize = WXSIZEOF( s_szBufStatic ); #if wxUSE_THREADS @@ -111,84 +115,129 @@ static inline bool IsLoggingEnabled() // ---------------------------------------------------------------------------- // generic log function -void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...) +void wxVLogGeneric(wxLogLevel level, const wxChar *szFormat, va_list argptr) { if ( IsLoggingEnabled() ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); - va_list argptr; - va_start(argptr, szFormat); - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); - va_end(argptr); + wxVsnprintf(s_szBuf, s_szBufSize, szFormat, argptr); wxLog::OnLog(level, s_szBuf, time(NULL)); } } +void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...) +{ + va_list argptr; + va_start(argptr, szFormat); + wxVLogGeneric(level, szFormat, argptr); + va_end(argptr); +} + #define IMPLEMENT_LOG_FUNCTION(level) \ - void wxLog##level(const wxChar *szFormat, ...) \ + void wxVLog##level(const wxChar *szFormat, va_list argptr) \ { \ if ( IsLoggingEnabled() ) { \ wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \ \ - va_list argptr; \ - va_start(argptr, szFormat); \ - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \ - va_end(argptr); \ + wxVsnprintf(s_szBuf, s_szBufSize, szFormat, argptr); \ \ wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ } \ + } \ + void wxLog##level(const wxChar *szFormat, ...) \ + { \ + va_list argptr; \ + va_start(argptr, szFormat); \ + wxVLog##level(szFormat, argptr); \ + va_end(argptr); \ } -IMPLEMENT_LOG_FUNCTION(FatalError) IMPLEMENT_LOG_FUNCTION(Error) IMPLEMENT_LOG_FUNCTION(Warning) IMPLEMENT_LOG_FUNCTION(Message) IMPLEMENT_LOG_FUNCTION(Info) IMPLEMENT_LOG_FUNCTION(Status) +void wxSafeShowMessage(const wxString& title, const wxString& text) +{ +#ifdef __WINDOWS__ + ::MessageBox(NULL, text, title, MB_OK | MB_ICONSTOP); +#else + wxFprintf(stderr, _T("%s: %s\n"), title.c_str(), text.c_str()); +#endif +} + +// fatal errors can't be suppressed nor handled by the custom log target and +// always terminate the program +void wxVLogFatalError(const wxChar *szFormat, va_list argptr) +{ + wxVsnprintf(s_szBuf, s_szBufSize, szFormat, argptr); + + wxSafeShowMessage(_T("Fatal Error"), s_szBuf); + + abort(); +} + +void wxLogFatalError(const wxChar *szFormat, ...) +{ + va_list argptr; + va_start(argptr, szFormat); + wxVLogFatalError(szFormat, argptr); + va_end(argptr); +} + // same as info, but only if 'verbose' mode is on -void wxLogVerbose(const wxChar *szFormat, ...) +void wxVLogVerbose(const wxChar *szFormat, va_list argptr) { if ( IsLoggingEnabled() ) { wxLog *pLog = wxLog::GetActiveTarget(); if ( pLog != NULL && pLog->GetVerbose() ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); - va_list argptr; - va_start(argptr, szFormat); - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); - va_end(argptr); + wxVsnprintf(s_szBuf, s_szBufSize, szFormat, argptr); wxLog::OnLog(wxLOG_Info, s_szBuf, time(NULL)); } } } +void wxLogVerbose(const wxChar *szFormat, ...) +{ + va_list argptr; + va_start(argptr, szFormat); + wxVLogVerbose(szFormat, argptr); + va_end(argptr); +} + // debug functions #ifdef __WXDEBUG__ #define IMPLEMENT_LOG_DEBUG_FUNCTION(level) \ - void wxLog##level(const wxChar *szFormat, ...) \ + void wxVLog##level(const wxChar *szFormat, va_list argptr) \ { \ if ( IsLoggingEnabled() ) { \ wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \ \ - va_list argptr; \ - va_start(argptr, szFormat); \ - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \ - va_end(argptr); \ + wxVsnprintf(s_szBuf, s_szBufSize, szFormat, argptr); \ \ wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ } \ + } \ + void wxLog##level(const wxChar *szFormat, ...) \ + { \ + va_list argptr; \ + va_start(argptr, szFormat); \ + wxVLog##level(szFormat, argptr); \ + va_end(argptr); \ } - void wxLogTrace(const wxChar *mask, const wxChar *szFormat, ...) + void wxVLogTrace(const wxChar *mask, const wxChar *szFormat, va_list argptr) { if ( IsLoggingEnabled() && wxLog::IsAllowedTraceMask(mask) ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); wxChar *p = s_szBuf; - size_t len = WXSIZEOF(s_szBuf); + size_t len = s_szBufSize; wxStrncpy(s_szBuf, _T("("), len); len -= 1; // strlen("(") p += 1; @@ -201,16 +250,21 @@ void wxLogVerbose(const wxChar *szFormat, ...) len -= 2; p += 2; - va_list argptr; - va_start(argptr, szFormat); wxVsnprintf(p, len, szFormat, argptr); - va_end(argptr); wxLog::OnLog(wxLOG_Trace, s_szBuf, time(NULL)); } } - void wxLogTrace(wxTraceMask mask, const wxChar *szFormat, ...) + void wxLogTrace(const wxChar *mask, const wxChar *szFormat, ...) + { + va_list argptr; + va_start(argptr, szFormat); + wxVLogTrace(mask, szFormat, argptr); + va_end(argptr); + } + + void wxVLogTrace(wxTraceMask mask, const wxChar *szFormat, va_list argptr) { // we check that all of mask bits are set in the current mask, so // that wxLogTrace(wxTraceRefCount | wxTraceOle) will only do something @@ -218,15 +272,20 @@ void wxLogVerbose(const wxChar *szFormat, ...) if ( IsLoggingEnabled() && ((wxLog::GetTraceMask() & mask) == mask) ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); - va_list argptr; - va_start(argptr, szFormat); - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); - va_end(argptr); + wxVsnprintf(s_szBuf, s_szBufSize, szFormat, argptr); wxLog::OnLog(wxLOG_Trace, s_szBuf, time(NULL)); } } + void wxLogTrace(wxTraceMask mask, const wxChar *szFormat, ...) + { + va_list argptr; + va_start(argptr, szFormat); + wxVLogTrace(mask, szFormat, argptr); + va_end(argptr); + } + #else // release #define IMPLEMENT_LOG_DEBUG_FUNCTION(level) #endif @@ -243,46 +302,73 @@ void wxLogSysErrorHelper(long lErrCode) wxChar szErrMsg[LOG_BUFFER_SIZE / 2]; wxSnprintf(szErrMsg, WXSIZEOF(szErrMsg), _(" (error %ld: %s)"), lErrCode, wxSysErrorMsg(lErrCode)); - wxStrncat(s_szBuf, szErrMsg, WXSIZEOF(s_szBuf) - wxStrlen(s_szBuf)); + wxStrncat(s_szBuf, szErrMsg, s_szBufSize - wxStrlen(s_szBuf)); wxLog::OnLog(wxLOG_Error, s_szBuf, time(NULL)); } -void WXDLLEXPORT wxLogSysError(const wxChar *szFormat, ...) +void WXDLLEXPORT wxVLogSysError(const wxChar *szFormat, va_list argptr) { if ( IsLoggingEnabled() ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); - va_list argptr; - va_start(argptr, szFormat); - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); - va_end(argptr); + wxVsnprintf(s_szBuf, s_szBufSize, szFormat, argptr); wxLogSysErrorHelper(wxSysErrorCode()); } } -void WXDLLEXPORT wxLogSysError(long lErrCode, const wxChar *szFormat, ...) +void WXDLLEXPORT wxLogSysError(const wxChar *szFormat, ...) +{ + va_list argptr; + va_start(argptr, szFormat); + wxVLogSysError(szFormat, argptr); + va_end(argptr); +} + +void WXDLLEXPORT wxVLogSysError(long lErrCode, const wxChar *szFormat, va_list argptr) { if ( IsLoggingEnabled() ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); - va_list argptr; - va_start(argptr, szFormat); - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); - va_end(argptr); + wxVsnprintf(s_szBuf, s_szBufSize, szFormat, argptr); wxLogSysErrorHelper(lErrCode); } } +void WXDLLEXPORT wxLogSysError(long lErrCode, const wxChar *szFormat, ...) +{ + va_list argptr; + va_start(argptr, szFormat); + wxVLogSysError(lErrCode, szFormat, argptr); + va_end(argptr); +} + // ---------------------------------------------------------------------------- // wxLog class implementation // ---------------------------------------------------------------------------- wxLog::wxLog() { - m_bHasMessages = FALSE; +} + +wxChar *wxLog::SetLogBuffer( wxChar *buf, size_t size) +{ + wxChar *oldbuf = s_szBuf; + + if( buf == 0 ) + { + s_szBuf = s_szBufStatic; + s_szBufSize = WXSIZEOF( s_szBufStatic ); + } + else + { + s_szBuf = buf; + s_szBufSize = size; + } + + return (oldbuf == s_szBufStatic ) ? 0 : oldbuf; } wxLog *wxLog::GetActiveTarget() @@ -406,8 +492,7 @@ void wxLog::DoLogString(const wxChar *WXUNUSED(szString), time_t WXUNUSED(t)) void wxLog::Flush() { - // remember that we don't have any more messages to show - m_bHasMessages = FALSE; + // nothing to do here } // ---------------------------------------------------------------------------- @@ -422,9 +507,8 @@ wxLogStderr::wxLogStderr(FILE *fp) m_fp = fp; } -#if defined(__WXMAC__) && !defined(__DARWIN__) && (__MWERKS__ > 0x5300) +#if defined(__WXMAC__) && !defined(__DARWIN__) && defined(__MWERKS__) && (__MWERKS__ >= 0x2400) -#if !TARGET_API_MAC_CARBON // MetroNub stuff doesn't seem to work in CodeWarrior 5.3 Carbon builds... #ifndef __MetroNubUtils__ @@ -432,7 +516,7 @@ wxLogStderr::wxLogStderr(FILE *fp) #endif #ifdef __cplusplus - extern "C" { + extern "C" { #endif #ifndef __GESTALT__ @@ -449,168 +533,165 @@ wxLogStderr::wxLogStderr(FILE *fp) #if TARGET_API_MAC_CARBON - #include + #include + + EXTERN_API_C( long ) + CallUniversalProc(UniversalProcPtr theProcPtr, ProcInfoType procInfo, ...); - EXTERN_API_C( long ) - CallUniversalProc(UniversalProcPtr theProcPtr, ProcInfoType procInfo, ...); + ProcPtr gCallUniversalProc_Proc = NULL; - ProcPtr gCallUniversalProc_Proc = NULL; - #endif -static MetroNubUserEntryBlock* gMetroNubEntry = NULL; +static MetroNubUserEntryBlock* gMetroNubEntry = NULL; static long fRunOnce = false; Boolean IsCompatibleVersion(short inVersion); /* --------------------------------------------------------------------------- - IsCompatibleVersion + IsCompatibleVersion --------------------------------------------------------------------------- */ Boolean IsCompatibleVersion(short inVersion) { - Boolean result = false; - - if (fRunOnce) - { - MetroNubUserEntryBlock* block = (MetroNubUserEntryBlock *)result; - - result = (inVersion <= block->apiHiVersion); - } - - return result; + Boolean result = false; + + if (fRunOnce) + { + MetroNubUserEntryBlock* block = (MetroNubUserEntryBlock *)result; + + result = (inVersion <= block->apiHiVersion); + } + + return result; } /* --------------------------------------------------------------------------- - IsMetroNubInstalled + IsMetroNubInstalled --------------------------------------------------------------------------- */ Boolean IsMetroNubInstalled() { - if (!fRunOnce) - { - long result, value; - - fRunOnce = true; - gMetroNubEntry = NULL; - - if (Gestalt(gestaltSystemVersion, &value) == noErr && value < 0x1000) - { - /* look for MetroNub's Gestalt selector */ - if (Gestalt(kMetroNubUserSignature, &result) == noErr) - { - - #if TARGET_API_MAC_CARBON - if (gCallUniversalProc_Proc == NULL) - { - CFragConnectionID connectionID; - Ptr mainAddress; - Str255 errorString; - ProcPtr symbolAddress; - OSErr err; - CFragSymbolClass symbolClass; - - symbolAddress = NULL; - err = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch, kFindCFrag, - &connectionID, &mainAddress, errorString); - - if (err != noErr) - { - gCallUniversalProc_Proc = NULL; - goto end; - } - - err = FindSymbol(connectionID, "\pCallUniversalProc", - (Ptr *) &gCallUniversalProc_Proc, &symbolClass); - - if (err != noErr) - { - gCallUniversalProc_Proc = NULL; - goto end; - } - } - #endif - - { - MetroNubUserEntryBlock* block = (MetroNubUserEntryBlock *)result; - - /* make sure the version of the API is compatible */ - if (block->apiLowVersion <= kMetroNubUserAPIVersion && - kMetroNubUserAPIVersion <= block->apiHiVersion) - gMetroNubEntry = block; /* success! */ - } - - } - } - } + if (!fRunOnce) + { + long result, value; + + fRunOnce = true; + gMetroNubEntry = NULL; + + if (Gestalt(gestaltSystemVersion, &value) == noErr && value < 0x1000) + { + /* look for MetroNub's Gestalt selector */ + if (Gestalt(kMetroNubUserSignature, &result) == noErr) + { + + #if TARGET_API_MAC_CARBON + if (gCallUniversalProc_Proc == NULL) + { + CFragConnectionID connectionID; + Ptr mainAddress; + Str255 errorString; + ProcPtr symbolAddress; + OSErr err; + CFragSymbolClass symbolClass; + + symbolAddress = NULL; + err = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch, kFindCFrag, + &connectionID, &mainAddress, errorString); + + if (err != noErr) + { + gCallUniversalProc_Proc = NULL; + goto end; + } + + err = FindSymbol(connectionID, "\pCallUniversalProc", + (Ptr *) &gCallUniversalProc_Proc, &symbolClass); + + if (err != noErr) + { + gCallUniversalProc_Proc = NULL; + goto end; + } + } + #endif + + { + MetroNubUserEntryBlock* block = (MetroNubUserEntryBlock *)result; + + /* make sure the version of the API is compatible */ + if (block->apiLowVersion <= kMetroNubUserAPIVersion && + kMetroNubUserAPIVersion <= block->apiHiVersion) + gMetroNubEntry = block; /* success! */ + } + + } + } + } end: #if TARGET_API_MAC_CARBON - return (gMetroNubEntry != NULL && gCallUniversalProc_Proc != NULL); + return (gMetroNubEntry != NULL && gCallUniversalProc_Proc != NULL); #else - return (gMetroNubEntry != NULL); + return (gMetroNubEntry != NULL); #endif } /* --------------------------------------------------------------------------- - IsMWDebuggerRunning [v1 API] + IsMWDebuggerRunning [v1 API] --------------------------------------------------------------------------- */ Boolean IsMWDebuggerRunning() { - if (IsMetroNubInstalled()) - return CallIsDebuggerRunningProc(gMetroNubEntry->isDebuggerRunning); - else - return false; + if (IsMetroNubInstalled()) + return CallIsDebuggerRunningProc(gMetroNubEntry->isDebuggerRunning); + else + return false; } /* --------------------------------------------------------------------------- - AmIBeingMWDebugged [v1 API] + AmIBeingMWDebugged [v1 API] --------------------------------------------------------------------------- */ Boolean AmIBeingMWDebugged() { - if (IsMetroNubInstalled()) - return CallAmIBeingDebuggedProc(gMetroNubEntry->amIBeingDebugged); - else - return false; + if (IsMetroNubInstalled()) + return CallAmIBeingDebuggedProc(gMetroNubEntry->amIBeingDebugged); + else + return false; } /* --------------------------------------------------------------------------- - UserSetWatchPoint [v2 API] + UserSetWatchPoint [v2 API] --------------------------------------------------------------------------- */ OSErr UserSetWatchPoint (Ptr address, long length, WatchPointIDT* watchPointID) { - if (IsMetroNubInstalled() && IsCompatibleVersion(kMetroNubUserAPIVersion)) - return CallUserSetWatchPointProc(gMetroNubEntry->userSetWatchPoint, - address, length, watchPointID); - else - return errProcessIsNotClient; + if (IsMetroNubInstalled() && IsCompatibleVersion(kMetroNubUserAPIVersion)) + return CallUserSetWatchPointProc(gMetroNubEntry->userSetWatchPoint, + address, length, watchPointID); + else + return errProcessIsNotClient; } /* --------------------------------------------------------------------------- - ClearWatchPoint [v2 API] + ClearWatchPoint [v2 API] --------------------------------------------------------------------------- */ OSErr ClearWatchPoint (WatchPointIDT watchPointID) { - if (IsMetroNubInstalled() && IsCompatibleVersion(kMetroNubUserAPIVersion)) - return CallClearWatchPointProc(gMetroNubEntry->clearWatchPoint, - watchPointID); - else - return errProcessIsNotClient; + if (IsMetroNubInstalled() && IsCompatibleVersion(kMetroNubUserAPIVersion)) + return CallClearWatchPointProc(gMetroNubEntry->clearWatchPoint, watchPointID); + else + return errProcessIsNotClient; } #ifdef __cplusplus - } + } #endif -#endif // !TARGET_API_MAC_CARBON - -#endif // defined(__WXMAC__) && !defined(__DARWIN__) && (__MWERKS__ > 0x5300) +#endif // defined(__WXMAC__) && !defined(__DARWIN__) && (__MWERKS__ >= 0x2400) void wxLogStderr::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) { @@ -623,11 +704,17 @@ void wxLogStderr::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) fflush(m_fp); // under Windows, programs usually don't have stderr at all, so show the - // messages also under debugger - unless it's a console program + // messages also under debugger (unless it's a console program which does + // have stderr or unless this is a file logger which doesn't use stderr at + // all) #if defined(__WXMSW__) && wxUSE_GUI && !defined(__WXMICROWIN__) - str += wxT("\r\n") ; - OutputDebugString(str.c_str()); + if ( m_fp == stderr ) + { + str += wxT("\r\n") ; + OutputDebugString(str.c_str()); + } #endif // MSW + #if defined(__WXMAC__) && !defined(__DARWIN__) && wxUSE_GUI Str255 pstr ; strcpy( (char*) pstr , str.c_str() ) ; @@ -636,7 +723,7 @@ void wxLogStderr::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) Boolean running = false ; -#if !TARGET_API_MAC_CARBON && (__MWERKS__ > 0x5300) +#if defined(__MWERKS__) && (__MWERKS__ >= 0x2400) if ( IsMWDebuggerRunning() && AmIBeingMWDebugged() ) { @@ -661,6 +748,7 @@ void wxLogStderr::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) // ---------------------------------------------------------------------------- #if wxUSE_STD_IOSTREAM +#include "wx/ioswrap.h" wxLogStream::wxLogStream(wxSTD ostream *ostr) { if ( ostr == NULL ) @@ -683,16 +771,24 @@ void wxLogStream::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) wxLogChain::wxLogChain(wxLog *logger) { + m_bPassMessages = TRUE; + m_logNew = logger; m_logOld = wxLog::SetActiveTarget(this); } -void wxLogChain::SetLog(wxLog *logger) +wxLogChain::~wxLogChain() { + delete m_logOld; + if ( m_logNew != this ) delete m_logNew; +} - wxLog::SetActiveTarget(logger); +void wxLogChain::SetLog(wxLog *logger) +{ + if ( m_logNew != this ) + delete m_logNew; m_logNew = logger; } @@ -702,7 +798,7 @@ void wxLogChain::Flush() if ( m_logOld ) m_logOld->Flush(); - // be careful to avoid inifinite recursion + // be careful to avoid infinite recursion if ( m_logNew && m_logNew != this ) m_logNew->Flush(); } @@ -754,6 +850,8 @@ bool wxLog::ms_doLog = TRUE; bool wxLog::ms_bAutoCreate = TRUE; bool wxLog::ms_bVerbose = FALSE; +wxLogLevel wxLog::ms_logLevel = wxLOG_Max; // log everything by default + size_t wxLog::ms_suspendCount = 0; #if wxUSE_GUI @@ -876,3 +974,5 @@ const wxChar *wxSysErrorMsg(unsigned long nErrCode) } #endif //wxUSE_LOG + +// vi:sts=4:sw=4:et