X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/13111b2ac81e694d6b69822dff61838ae66052b2..fa8dca8dd1ba0d6ee9b2c5919a3a944ecde68a50:/src/common/log.cpp diff --git a/src/common/log.cpp b/src/common/log.cpp index 6d99576b99..ffeeef2daa 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -50,6 +50,8 @@ #include "wx/log.h" #include "wx/thread.h" +#if wxUSE_LOG + // other standard headers #include #include @@ -94,6 +96,12 @@ static wxCriticalSection gs_csLogBuf; #endif // wxUSE_THREADS +// return true if we have a non NULL non disabled log target +static inline bool IsLoggingEnabled() +{ + return wxLog::IsEnabled() && (wxLog::GetActiveTarget() != NULL); +} + // ---------------------------------------------------------------------------- // implementation of Log functions // @@ -104,31 +112,31 @@ static wxCriticalSection gs_csLogBuf; // generic log function void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...) { - if ( wxLog::GetActiveTarget() != NULL ) { - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + 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); + va_list argptr; + va_start(argptr, szFormat); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); + va_end(argptr); - wxLog::OnLog(level, s_szBuf, time(NULL)); - } + wxLog::OnLog(level, s_szBuf, time(NULL)); + } } -#define IMPLEMENT_LOG_FUNCTION(level) \ - void wxLog##level(const wxChar *szFormat, ...) \ - { \ - if ( wxLog::GetActiveTarget() != NULL ) { \ - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \ - \ - va_list argptr; \ - va_start(argptr, szFormat); \ - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \ - va_end(argptr); \ - \ - wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ - } \ +#define IMPLEMENT_LOG_FUNCTION(level) \ + void wxLog##level(const wxChar *szFormat, ...) \ + { \ + 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); \ + \ + wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ + } \ } IMPLEMENT_LOG_FUNCTION(FatalError) @@ -141,46 +149,60 @@ IMPLEMENT_LOG_FUNCTION(Status) // same as info, but only if 'verbose' mode is on void wxLogVerbose(const wxChar *szFormat, ...) { - wxLog *pLog = wxLog::GetActiveTarget(); - if ( pLog != NULL && pLog->GetVerbose() ) { - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + 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); + va_list argptr; + va_start(argptr, szFormat); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); + va_end(argptr); - wxLog::OnLog(wxLOG_Info, s_szBuf, time(NULL)); - } + wxLog::OnLog(wxLOG_Info, s_szBuf, time(NULL)); + } + } } // debug functions #ifdef __WXDEBUG__ -#define IMPLEMENT_LOG_DEBUG_FUNCTION(level) \ - void wxLog##level(const wxChar *szFormat, ...) \ - { \ - if ( wxLog::GetActiveTarget() != NULL ) { \ - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \ - \ - va_list argptr; \ - va_start(argptr, szFormat); \ - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \ - va_end(argptr); \ - \ - wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ - } \ +#define IMPLEMENT_LOG_DEBUG_FUNCTION(level) \ + void wxLog##level(const wxChar *szFormat, ...) \ + { \ + 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); \ + \ + wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ + } \ } void wxLogTrace(const wxChar *mask, const wxChar *szFormat, ...) { - wxLog *pLog = wxLog::GetActiveTarget(); - - if ( pLog != NULL && wxLog::IsAllowedTraceMask(mask) ) { + if ( IsLoggingEnabled() && wxLog::IsAllowedTraceMask(mask) ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + wxChar *p = s_szBuf; + size_t len = WXSIZEOF(s_szBuf); + wxStrncpy(s_szBuf, _T("("), len); + len -= 1; // strlen("(") + p += 1; + wxStrncat(p, mask, len); + size_t lenMask = wxStrlen(mask); + len -= lenMask; + p += lenMask; + + wxStrncat(p, _T(") "), len); + len -= 2; + p += 2; + va_list argptr; va_start(argptr, szFormat); - wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); + wxVsnprintf(p, len, szFormat, argptr); va_end(argptr); wxLog::OnLog(wxLOG_Trace, s_szBuf, time(NULL)); @@ -189,12 +211,10 @@ void wxLogVerbose(const wxChar *szFormat, ...) void wxLogTrace(wxTraceMask mask, const wxChar *szFormat, ...) { - wxLog *pLog = wxLog::GetActiveTarget(); - // we check that all of mask bits are set in the current mask, so // that wxLogTrace(wxTraceRefCount | wxTraceOle) will only do something // if both bits are set. - if ( pLog != NULL && ((pLog->GetTraceMask() & mask) == mask) ) { + if ( IsLoggingEnabled() && ((wxLog::GetTraceMask() & mask) == mask) ) { wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); va_list argptr; @@ -229,26 +249,30 @@ void wxLogSysErrorHelper(long lErrCode) void WXDLLEXPORT wxLogSysError(const wxChar *szFormat, ...) { - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + 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); + va_list argptr; + va_start(argptr, szFormat); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); + va_end(argptr); - wxLogSysErrorHelper(wxSysErrorCode()); + wxLogSysErrorHelper(wxSysErrorCode()); + } } void WXDLLEXPORT wxLogSysError(long lErrCode, const wxChar *szFormat, ...) { - wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + 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); + va_list argptr; + va_start(argptr, szFormat); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); + va_end(argptr); - wxLogSysErrorHelper(lErrCode); + wxLogSysErrorHelper(lErrCode); + } } // ---------------------------------------------------------------------------- @@ -258,13 +282,7 @@ void WXDLLEXPORT wxLogSysError(long lErrCode, const wxChar *szFormat, ...) wxLog::wxLog() { m_bHasMessages = FALSE; - - // enable verbose messages by default in the debug builds -#ifdef __WXDEBUG__ - m_bVerbose = TRUE; -#else // release m_bVerbose = FALSE; -#endif // debug/release } wxLog *wxLog::GetActiveTarget() @@ -305,6 +323,16 @@ wxLog *wxLog::SetActiveTarget(wxLog *pLogger) return pOldLogger; } +void wxLog::DontCreateOnDemand() +{ + ms_bAutoCreate = FALSE; + + // this is usually called at the end of the program and we assume that it + // is *always* called at the end - so we free memory here to avoid false + // memory leak reports from wxWin memory tracking code + ClearTraceMasks(); +} + void wxLog::RemoveTraceMask(const wxString& str) { int index = ms_aTraceMasks.Index(str); @@ -312,6 +340,11 @@ void wxLog::RemoveTraceMask(const wxString& str) ms_aTraceMasks.Remove((size_t)index); } +void wxLog::ClearTraceMasks() +{ + ms_aTraceMasks.Clear(); +} + void wxLog::TimeStamp(wxString *str) { if ( ms_timestamp ) @@ -355,8 +388,13 @@ void wxLog::DoLog(wxLogLevel level, const wxChar *szString, time_t t) case wxLOG_Trace: case wxLOG_Debug: #ifdef __WXDEBUG__ - DoLogString(szString, t); -#endif + { + wxString msg = level == wxLOG_Trace ? wxT("Trace: ") + : wxT("Debug: "); + msg << szString; + DoLogString(msg, t); + } +#endif // Debug break; } } @@ -383,6 +421,86 @@ wxLogStderr::wxLogStderr(FILE *fp) m_fp = fp; } +#if defined(__WXMAC__) && !defined(__UNIX__) +#define kDebuggerSignature 'MWDB' + +static Boolean FindProcessBySignature(OSType signature, ProcessInfoRec* info) +{ + OSErr err; + ProcessSerialNumber psn; + Boolean found = false; + psn.highLongOfPSN = 0; + psn.lowLongOfPSN = kNoProcess; + + if (!info) return false; + + info->processInfoLength = sizeof(ProcessInfoRec); + info->processName = NULL; + info->processAppSpec = NULL; + + err = noErr; + while (!found && err == noErr) + { + err = GetNextProcess(&psn); + if (err == noErr) + { + err = GetProcessInformation(&psn, info); + found = err == noErr && info->processSignature == signature; + } + } + return found; +} + +pascal Boolean MWDebuggerIsRunning(void) +{ + ProcessInfoRec info; + return FindProcessBySignature(kDebuggerSignature, &info); +} + +pascal OSErr AmIBeingMWDebugged(Boolean* result) +{ + OSErr err; + ProcessSerialNumber psn; + OSType sig = kDebuggerSignature; + AppleEvent theAE = {typeNull, NULL}; + AppleEvent theReply = {typeNull, NULL}; + AEAddressDesc addr = {typeNull, NULL}; + DescType actualType; + Size actualSize; + + if (!result) return paramErr; + + err = AECreateDesc(typeApplSignature, &sig, sizeof(sig), &addr); + if (err != noErr) goto exit; + + err = AECreateAppleEvent('MWDB', 'Dbg?', &addr, + kAutoGenerateReturnID, kAnyTransactionID, &theAE); + if (err != noErr) goto exit; + + GetCurrentProcess(&psn); + err = AEPutParamPtr(&theAE, keyDirectObject, typeProcessSerialNumber, + &psn, sizeof(psn)); + if (err != noErr) goto exit; + + err = AESend(&theAE, &theReply, kAEWaitReply, kAENormalPriority, + kAEDefaultTimeout, NULL, NULL); + if (err != noErr) goto exit; + + err = AEGetParamPtr(&theReply, keyAEResult, typeBoolean, &actualType, result, + sizeof(Boolean), &actualSize); + +exit: + if (addr.dataHandle) + AEDisposeDesc(&addr); + if (theAE.dataHandle) + AEDisposeDesc(&theAE); + if (theReply.dataHandle) + AEDisposeDesc(&theReply); + + return err; +} +#endif + void wxLogStderr::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) { wxString str; @@ -396,8 +514,41 @@ void wxLogStderr::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) // under Windows, programs usually don't have stderr at all, so show the // messages also under debugger - unless it's a console program #if defined(__WXMSW__) && wxUSE_GUI - OutputDebugString(str + wxT("\r\n")); + str += wxT("\r\n") ; + OutputDebugString(str.c_str()); #endif // MSW +#if defined(__WXMAC__) && !defined(__WXMAC_X__) && wxUSE_GUI + Str255 pstr ; + strcpy( (char*) pstr , str.c_str() ) ; + strcat( (char*) pstr , ";g" ) ; + c2pstr( (char*) pstr ) ; +#if __WXDEBUG__ + Boolean running = false ; + +/* + if ( MWDebuggerIsRunning() ) + { + AmIBeingMWDebugged( &running ) ; + } +*/ + if (running) + { + #ifdef __powerc + DebugStr(pstr); + #else + SysBreakStr(pstr); + #endif + } + else +#endif + { + #ifdef __powerc + DebugStr(pstr); + #else + DebugStr(pstr); + #endif + } +#endif // Mac } // ---------------------------------------------------------------------------- @@ -405,17 +556,19 @@ void wxLogStderr::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) // ---------------------------------------------------------------------------- #if wxUSE_STD_IOSTREAM -wxLogStream::wxLogStream(ostream *ostr) +wxLogStream::wxLogStream(wxSTD ostream *ostr) { if ( ostr == NULL ) - m_ostr = &cerr; + m_ostr = &wxSTD cerr; else m_ostr = ostr; } void wxLogStream::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) { - (*m_ostr) << wxConvertWX2MB(szString) << endl; + wxString str; + TimeStamp(&str); + (*m_ostr) << str << wxConvertWX2MB(szString) << wxSTD endl; } #endif // wxUSE_STD_IOSTREAM @@ -431,7 +584,13 @@ wxLog *wxLog::ms_pLogger = (wxLog *)NULL; bool wxLog::ms_doLog = TRUE; bool wxLog::ms_bAutoCreate = TRUE; -const wxChar *wxLog::ms_timestamp = wxT("%X"); // time only, no date +size_t wxLog::ms_suspendCount = 0; + +#if wxUSE_GUI + const wxChar *wxLog::ms_timestamp = wxT("%X"); // time only, no date +#else + const wxChar *wxLog::ms_timestamp = NULL; // save space +#endif wxTraceMask wxLog::ms_ulTraceMask = (wxTraceMask)0; wxArrayString wxLog::ms_aTraceMasks; @@ -546,8 +705,14 @@ const wxChar *wxSysErrorMsg(unsigned long nErrCode) #ifdef __WXDEBUG__ +// wxASSERT() helper +bool wxAssertIsEqual(int x, int y) +{ + return x == y; +} + // break into the debugger -void Trap() +void wxTrap() { #ifdef __WXMSW__ DebugBreak(); @@ -573,7 +738,7 @@ void wxOnAssert(const wxChar *szFile, int nLine, const wxChar *szMsg) if ( s_bInAssert ) { // He-e-e-e-elp!! we're trapped in endless loop - Trap(); + wxTrap(); s_bInAssert = FALSE; @@ -607,43 +772,43 @@ void wxOnAssert(const wxChar *szFile, int nLine, const wxChar *szMsg) // send it to the normal log destination wxLogDebug(szBuf); -#if wxUSE_GUI || defined(__WXMSW__) +#if (wxUSE_GUI && wxUSE_MSGDLG) || defined(__WXMSW__) // this message is intentionally not translated - it is for // developpers only - wxStrcat(szBuf, wxT("\nDo you want to stop the program?" - "\nYou can also choose [Cancel] to suppress " - "further warnings.")); + wxStrcat(szBuf, wxT("\nDo you want to stop the program?\nYou can also choose [Cancel] to suppress further warnings.")); -#if wxUSE_GUI - switch ( wxMessageBox(szBuf, "Debug", - wxYES_NO | wxCANCEL | wxICON_STOP ) ) { - case wxYES: - Trap(); + // use the native message box if available: this is more robust than + // using our own +#ifdef __WXMSW__ + switch ( ::MessageBox(NULL, szBuf, _T("Debug"), + MB_YESNOCANCEL | MB_ICONSTOP ) ) { + case IDYES: + wxTrap(); break; - case wxCANCEL: + case IDCANCEL: s_bNoAsserts = TRUE; break; - //case wxNO: nothing to do + //case IDNO: nothing to do } -#else // !GUI, but MSW - switch ( ::MessageBox(NULL, szBuf, "Debug", - MB_YESNOCANCEL | MB_ICONSTOP ) ) { - case IDYES: - Trap(); +#else // !MSW + switch ( wxMessageBox(szBuf, wxT("Debug"), + wxYES_NO | wxCANCEL | wxICON_STOP ) ) { + case wxYES: + wxTrap(); break; - case IDCANCEL: + case wxCANCEL: s_bNoAsserts = TRUE; break; - //case IDNO: nothing to do + //case wxNO: nothing to do } #endif // GUI or MSW #else // !GUI - Trap(); + wxTrap(); #endif // GUI/!GUI } @@ -652,3 +817,4 @@ void wxOnAssert(const wxChar *szFile, int nLine, const wxChar *szMsg) #endif //WXDEBUG +#endif //wxUSE_LOG