X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/87a1e3085bc19deacd312a1dcf7d4eb89f51d5a3..f5ba273ecd799f652736ce2bc830283787302a56:/src/common/log.cpp diff --git a/src/common/log.cpp b/src/common/log.cpp index c512ffc3f2..0a44516706 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -48,6 +48,7 @@ #include "wx/utils.h" #include "wx/wxchar.h" #include "wx/log.h" +#include "wx/thread.h" // other standard headers #include @@ -55,9 +56,7 @@ #include #ifdef __WXMSW__ - #include - // Redefines OutputDebugString if necessary - #include "wx/msw/private.h" + #include "wx/msw/private.h" // includes windows.h for OutputDebugString #else //Unix #include #endif //Win/Unix @@ -78,26 +77,39 @@ // ============================================================================ // ---------------------------------------------------------------------------- -// implementation of Log functions -// -// NB: unfortunately we need all these distinct functions, we can't make them -// macros and not all compilers inline vararg functions. +// globals // ---------------------------------------------------------------------------- // log functions can't allocate memory (LogError("out of memory...") should // work!), so we use a static buffer for all log messages #define LOG_BUFFER_SIZE (4096) -// static buffer for error messages (FIXME MT-unsafe) +// static buffer for error messages static wxChar s_szBuf[LOG_BUFFER_SIZE]; +#if wxUSE_THREADS + +// the critical section protecting the static buffer +static wxCriticalSection gs_csLogBuf; + +#endif // wxUSE_THREADS + +// ---------------------------------------------------------------------------- +// implementation of Log functions +// +// NB: unfortunately we need all these distinct functions, we can't make them +// macros and not all compilers inline vararg functions. +// ---------------------------------------------------------------------------- + // generic log function void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...) { if ( wxLog::GetActiveTarget() != NULL ) { + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + va_list argptr; va_start(argptr, szFormat); - wxVsprintf(s_szBuf, szFormat, argptr); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); va_end(argptr); wxLog::OnLog(level, s_szBuf, time(NULL)); @@ -108,9 +120,11 @@ void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...) void wxLog##level(const wxChar *szFormat, ...) \ { \ if ( wxLog::GetActiveTarget() != NULL ) { \ + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \ + \ va_list argptr; \ va_start(argptr, szFormat); \ - wxVsprintf(s_szBuf, szFormat, argptr); \ + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \ va_end(argptr); \ \ wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ @@ -129,9 +143,11 @@ void wxLogVerbose(const wxChar *szFormat, ...) { wxLog *pLog = wxLog::GetActiveTarget(); if ( pLog != NULL && pLog->GetVerbose() ) { + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + va_list argptr; va_start(argptr, szFormat); - wxVsprintf(s_szBuf, szFormat, argptr); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); va_end(argptr); wxLog::OnLog(wxLOG_Info, s_szBuf, time(NULL)); @@ -144,9 +160,11 @@ void wxLogVerbose(const wxChar *szFormat, ...) void wxLog##level(const wxChar *szFormat, ...) \ { \ if ( wxLog::GetActiveTarget() != NULL ) { \ + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); \ + \ va_list argptr; \ va_start(argptr, szFormat); \ - wxVsprintf(s_szBuf, szFormat, argptr); \ + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); \ va_end(argptr); \ \ wxLog::OnLog(wxLOG_##level, s_szBuf, time(NULL)); \ @@ -158,9 +176,25 @@ void wxLogVerbose(const wxChar *szFormat, ...) wxLog *pLog = wxLog::GetActiveTarget(); if ( pLog != NULL && wxLog::IsAllowedTraceMask(mask) ) { + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + + wxChar *p = s_szBuf; + size_t len = WXSIZEOF(s_szBuf); + strncpy(s_szBuf, _T("("), len); + len -= 1; // strlen("(") + p += 1; + strncat(p, mask, len); + size_t lenMask = wxStrlen(mask); + len -= lenMask; + p += lenMask; + + strncat(p, _T(") "), len); + len -= 2; + p += 2; + va_list argptr; va_start(argptr, szFormat); - wxVsprintf(s_szBuf, szFormat, argptr); + wxVsnprintf(p, len, szFormat, argptr); va_end(argptr); wxLog::OnLog(wxLOG_Trace, s_szBuf, time(NULL)); @@ -175,9 +209,11 @@ void wxLogVerbose(const wxChar *szFormat, ...) // that wxLogTrace(wxTraceRefCount | wxTraceOle) will only do something // if both bits are set. if ( pLog != NULL && ((pLog->GetTraceMask() & mask) == mask) ) { + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + va_list argptr; va_start(argptr, szFormat); - wxVsprintf(s_szBuf, szFormat, argptr); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); va_end(argptr); wxLog::OnLog(wxLOG_Trace, s_szBuf, time(NULL)); @@ -198,7 +234,8 @@ IMPLEMENT_LOG_DEBUG_FUNCTION(Trace) void wxLogSysErrorHelper(long lErrCode) { wxChar szErrMsg[LOG_BUFFER_SIZE / 2]; - wxSprintf(szErrMsg, _(" (error %ld: %s)"), lErrCode, wxSysErrorMsg(lErrCode)); + wxSnprintf(szErrMsg, WXSIZEOF(szErrMsg), + _(" (error %ld: %s)"), lErrCode, wxSysErrorMsg(lErrCode)); wxStrncat(s_szBuf, szErrMsg, WXSIZEOF(s_szBuf) - wxStrlen(s_szBuf)); wxLog::OnLog(wxLOG_Error, s_szBuf, time(NULL)); @@ -206,9 +243,11 @@ void wxLogSysErrorHelper(long lErrCode) void WXDLLEXPORT wxLogSysError(const wxChar *szFormat, ...) { + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + va_list argptr; va_start(argptr, szFormat); - wxVsprintf(s_szBuf, szFormat, argptr); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); va_end(argptr); wxLogSysErrorHelper(wxSysErrorCode()); @@ -216,9 +255,11 @@ void WXDLLEXPORT wxLogSysError(const wxChar *szFormat, ...) void WXDLLEXPORT wxLogSysError(long lErrCode, const wxChar *szFormat, ...) { + wxCRIT_SECT_LOCKER(locker, gs_csLogBuf); + va_list argptr; va_start(argptr, szFormat); - wxVsprintf(s_szBuf, szFormat, argptr); + wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr); va_end(argptr); wxLogSysErrorHelper(lErrCode); @@ -328,8 +369,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; } } @@ -360,15 +406,19 @@ void wxLogStderr::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) { wxString str; TimeStamp(&str); - str << szString << wxT('\n'); + str << szString; fputs(str.mb_str(), m_fp); + fputc(_T('\n'), m_fp); fflush(m_fp); - // under Windows, programs usually don't have stderr at all, so make show the - // messages also under debugger -#ifdef __WXMSW__ - OutputDebugString(str + wxT('\r')); + // 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")); +#endif // MSW +#if defined(__WXMAC__) && wxUSE_GUI + debugstr(str + wxT("\r\n")); #endif // MSW } @@ -403,7 +453,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; @@ -507,7 +563,7 @@ const wxChar *wxSysErrorMsg(unsigned long nErrCode) wxConvCurrent->MB2WC(s_szBuf, strerror(nErrCode), WXSIZEOF(s_szBuf) -1); return s_szBuf; #else - return strerror(nErrCode); + return strerror((int)nErrCode); #endif #endif // Win/Unix } @@ -558,12 +614,14 @@ void wxOnAssert(const wxChar *szFile, int nLine, const wxChar *szMsg) // make life easier for people using VC++ IDE: clicking on the message // will take us immediately to the place of the failed assert + wxSnprintf(szBuf, WXSIZEOF(szBuf), #ifdef __VISUALC__ - wxSprintf(szBuf, wxT("%s(%d): assert failed"), szFile, nLine); + wxT("%s(%d): assert failed"), #else // !VC++ // make the error message more clear for all the others - wxSprintf(szBuf, wxT("Assert failed in file %s at line %d"), szFile, nLine); + wxT("Assert failed in file %s at line %d"), #endif // VC/!VC + szFile, nLine); if ( szMsg != NULL ) { wxStrcat(szBuf, wxT(": ")); @@ -577,15 +635,16 @@ void wxOnAssert(const wxChar *szFile, int nLine, const wxChar *szMsg) // send it to the normal log destination wxLogDebug(szBuf); -#if wxUSE_GUI +#if wxUSE_GUI || 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.")); + "\nYou can also choose [Cancel] to suppress " + "further warnings.")); - switch ( wxMessageBox(szBuf, _("Debug"), - wxYES_NO | wxCANCEL | wxICON_STOP ) ) { +#if wxUSE_GUI + switch ( wxMessageBox(szBuf, "Debug", + wxYES_NO | wxCANCEL | wxICON_STOP ) ) { case wxYES: Trap(); break; @@ -594,8 +653,23 @@ void wxOnAssert(const wxChar *szFile, int nLine, const wxChar *szMsg) s_bNoAsserts = TRUE; break; - //case wxNO: nothing to do + //case wxNO: nothing to do } +#else // !GUI, but MSW + switch ( ::MessageBox(NULL, szBuf, "Debug", + MB_YESNOCANCEL | MB_ICONSTOP ) ) { + case IDYES: + Trap(); + break; + + case IDCANCEL: + s_bNoAsserts = TRUE; + break; + + //case IDNO: nothing to do + } +#endif // GUI or MSW + #else // !GUI Trap(); #endif // GUI/!GUI