1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #if defined (UNX) || defined (__GNUC__)
28 #include <cstdarg> // combinations
37 #include <tools/debug.hxx>
38 #include <rtl/string.h>
39 #include <sal/log.hxx>
40 #include <sal/macros.h>
44 #include <osl/diagnose.h>
45 #include <tools/diagnose_ex.h>
51 #define PBLOCKCOUNT 1024
55 void* aData
[PBLOCKCOUNT
];
69 PointerList() { pFirst
= NULL
; pLast
= NULL
; nCount
= 0; }
72 void Add( const void* p
);
73 sal_Bool
Remove( const void* p
);
75 const void* Get( sal_uIntPtr nPos
) const;
76 sal_Bool
IsIn( const void* p
) const;
77 sal_uIntPtr
Count() const { return nCount
; }
82 #define DBG_MAXNAME 28
91 sal_uIntPtr nContinueTime
;
92 sal_uIntPtr nContinueStart
;
93 sal_Char aName
[DBG_MAXNAME
+1];
98 sal_uIntPtr nCtorCalls
;
99 sal_uIntPtr nDtorCalls
;
100 sal_uIntPtr nMaxCount
;
101 sal_uIntPtr nStatics
;
102 sal_Char aName
[DBG_MAXNAME
+1];
104 PointerList aThisList
;
111 DbgPrintLine pDbgPrintMsgBox
;
112 DbgPrintLine pDbgPrintWindow
;
113 DbgPrintLine pDbgPrintTestTool
;
114 DbgPrintLine pDbgAbort
;
115 ::std::vector
< DbgPrintLine
>
116 aDbgPrintUserChannels
;
117 PointerList
* pProfList
;
118 PointerList
* pXtorList
;
119 DbgTestSolarMutexProc pDbgTestSolarMutex
;
120 pfunc_osl_printDetailedDebugMessage
121 pOldDebugMessageFunc
;
126 ,pDbgPrintMsgBox( NULL
)
127 ,pDbgPrintWindow( NULL
)
128 ,pDbgPrintTestTool( NULL
)
132 ,pDbgTestSolarMutex( NULL
)
133 ,pOldDebugMessageFunc( NULL
)
134 ,bOslIsHooked( false )
136 aDbgData
.nTestFlags
= DBG_TEST_RESOURCE
;
137 aDbgData
.bOverwrite
= sal_True
;
138 aDbgData
.nTraceOut
= DBG_OUT_NULL
;
139 aDbgData
.nWarningOut
= DBG_OUT_NULL
;
141 aDbgData
.nErrorOut
= DBG_OUT_SHELL
;
143 aDbgData
.nErrorOut
= DBG_OUT_MSGBOX
;
145 aDbgData
.bHookOSLAssert
= sal_True
;
146 aDbgData
.aDebugName
[0] = 0;
147 aDbgData
.aInclFilter
[0] = 0;
148 aDbgData
.aExclFilter
[0] = 0;
149 aDbgData
.aInclClassFilter
[0] = 0;
150 aDbgData
.aExclClassFilter
[0] = 0;
151 aDbgData
.aDbgWinState
[0] = 0;
155 #define DBG_TEST_XTOR_EXTRA (DBG_TEST_XTOR_THIS | DBG_TEST_XTOR_FUNC | \
156 DBG_TEST_XTOR_EXIT | DBG_TEST_XTOR_REPORT )
158 // static maintenance variables
160 static DebugData aDebugData
;
161 static sal_Char aCurPath
[260];
162 static int bDbgImplInMain
= sal_False
;
165 static CRITICAL_SECTION aImplCritDbgSection
;
168 static sal_Bool bImplCritDbgSectionInit
= sal_False
;
170 void ImplDbgInitLock()
173 InitializeCriticalSection( &aImplCritDbgSection
);
175 bImplCritDbgSectionInit
= sal_True
;
178 void ImplDbgDeInitLock()
181 DeleteCriticalSection( &aImplCritDbgSection
);
183 bImplCritDbgSectionInit
= sal_False
;
188 if ( !bImplCritDbgSectionInit
)
192 EnterCriticalSection( &aImplCritDbgSection
);
198 if ( !bImplCritDbgSectionInit
)
202 LeaveCriticalSection( &aImplCritDbgSection
);
206 #define FILE_LINEEND "\n"
208 static sal_Bool
ImplActivateDebugger( const sal_Char
* pMsg
)
211 static sal_Char aImplDbgOutBuf
[DBG_BUF_MAXLEN
];
212 strcpy( aImplDbgOutBuf
, pMsg
);
213 strcat( aImplDbgOutBuf
, "\r\n" );
214 OutputDebugString( aImplDbgOutBuf
);
218 (void) pMsg
; // avoid warning about unused parameter
223 static sal_Bool
ImplCoreDump()
234 static sal_uIntPtr
ImplGetPerfTime()
237 return (sal_uIntPtr
)GetTickCount();
239 static sal_uIntPtr nImplTicksPerSecond
= 0;
240 static double dImplTicksPerSecond
;
241 sal_uIntPtr nTicks
= (sal_uIntPtr
)clock();
243 if ( !nImplTicksPerSecond
)
245 nImplTicksPerSecond
= CLOCKS_PER_SEC
;
246 dImplTicksPerSecond
= nImplTicksPerSecond
;
249 double fTicks
= nTicks
;
251 fTicks
/= dImplTicksPerSecond
;
252 return (sal_uIntPtr
)fTicks
;
256 typedef FILE* FILETYPE
;
257 #define FileOpen fopen
258 #define FileRead fread
259 #define FilePrintF fprintf
260 #define FileClose fclose
275 void lcl_lineFeed( FILETYPE _pFile
)
277 FilePrintF( _pFile
, "%s", FILE_LINEEND
);
280 const sal_Char
* lcl_getSectionName( ConfigSection _eSection
)
282 const sal_Char
* pSectionName
= NULL
;
285 case eOutput
: pSectionName
= "output"; break;
286 case eMemory
: pSectionName
= "memory"; break;
287 case eGUI
: pSectionName
= "gui"; break;
288 case eObjects
: pSectionName
= "objects"; break;
289 case eTest
: pSectionName
= "test"; break;
297 ConfigSection
lcl_getSectionFromName( const sal_Char
* _pSectionName
, size_t _nSectionNameLength
)
299 if ( strncmp( _pSectionName
, "output", _nSectionNameLength
< 6 ? _nSectionNameLength
: 6 ) == 0 )
301 if ( strncmp( _pSectionName
, "memory", _nSectionNameLength
< 6 ? _nSectionNameLength
: 6 ) == 0 )
303 if ( strncmp( _pSectionName
, "gui", _nSectionNameLength
< 3 ? _nSectionNameLength
: 3 ) == 0 )
305 if ( strncmp( _pSectionName
, "objects", _nSectionNameLength
< 7 ? _nSectionNameLength
: 7 ) == 0 )
307 if ( strncmp( _pSectionName
, "test", _nSectionNameLength
< 4 ? _nSectionNameLength
: 4 ) == 0 )
312 void lcl_startSection( FILETYPE _pFile
, ConfigSection _eSection
)
314 FilePrintF( _pFile
, "[%s]%s", lcl_getSectionName( _eSection
), FILE_LINEEND
);
317 void lcl_writeConfigString( FILETYPE _pFile
, const sal_Char
* _pKeyName
, const sal_Char
* _pValue
)
319 FilePrintF( _pFile
, "%s=%s%s", _pKeyName
, _pValue
, FILE_LINEEND
);
322 void lcl_writeConfigBoolean( FILETYPE _pFile
, const sal_Char
* _pKeyName
, bool _bValue
)
324 lcl_writeConfigString( _pFile
, _pKeyName
, _bValue
? "1" : "0" );
327 void lcl_writeConfigFlag( FILETYPE _pFile
, const sal_Char
* _pKeyName
, sal_uIntPtr _nAllFlags
, sal_uIntPtr _nCheckFlag
)
329 lcl_writeConfigBoolean( _pFile
, _pKeyName
, ( _nAllFlags
& _nCheckFlag
) != 0 );
332 void lcl_writeConfigOutChannel( FILETYPE _pFile
, const sal_Char
* _pKeyName
, sal_uIntPtr _nValue
)
334 const sal_Char
* names
[ DBG_OUT_COUNT
] =
336 "dev/null", "file", "window", "shell", "messagebox", "testtool", "debugger", "abort"
338 lcl_writeConfigString( _pFile
, _pKeyName
, names
[ _nValue
] );
341 bool lcl_isConfigSection( const sal_Char
* _pLine
, size_t _nLineLen
)
344 // not even enough space for '[' and ']'
346 if ( ( _pLine
[0] == '[' ) && ( _pLine
[ _nLineLen
- 1 ] == ']' ) )
351 bool lcl_isConfigKey( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
)
353 size_t nKeyLength
= strlen( _pKeyName
);
354 if ( nKeyLength
+ 1 >= _nLineLen
)
355 // not even long enough for the key name plus "=" plus a one-character value
357 if ( ( strncmp( _pLine
, _pKeyName
, nKeyLength
) == 0 ) && ( _pLine
[ nKeyLength
] == '=' ) )
362 sal_Int32
lcl_tryReadConfigString( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, sal_Char
* _pValue
, size_t _nValueLen
)
364 if ( !lcl_isConfigKey( _pLine
, _nLineLen
, _pKeyName
) )
366 size_t nValuePos
= strlen( _pKeyName
) + 1;
367 size_t nValueLen
= _nLineLen
- nValuePos
;
368 const sal_Char
* pValue
= _pLine
+ nValuePos
;
369 strncpy( _pValue
, pValue
, ( _nValueLen
> nValueLen
) ? nValueLen
: _nValueLen
);
370 _pValue
[ ( _nValueLen
> nValueLen
) ? nValueLen
: _nValueLen
- 1 ] = 0;
371 return strlen( _pValue
);
374 void lcl_tryReadConfigBoolean( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, sal_uIntPtr
* _out_pnValue
)
377 size_t nValueLen
= lcl_tryReadConfigString( _pLine
, _nLineLen
, _pKeyName
, aBuf
, sizeof( aBuf
) );
379 *_out_pnValue
= strcmp( aBuf
, "1" ) == 0 ? sal_True
: sal_False
;
382 void lcl_matchOutputChannel( sal_Char
const * i_buffer
, sal_uIntPtr
* o_value
)
384 if ( i_buffer
== NULL
)
386 const sal_Char
* names
[ DBG_OUT_COUNT
] =
388 "dev/null", "file", "window", "shell", "messagebox", "testtool", "debugger", "abort"
390 for ( size_t name
= 0; name
< SAL_N_ELEMENTS( names
); ++name
)
392 if ( strcmp( i_buffer
, names
[ name
] ) == 0 )
400 void lcl_tryReadOutputChannel( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, sal_uIntPtr
* _out_pnValue
)
403 size_t nValueLen
= lcl_tryReadConfigString( _pLine
, _nLineLen
, _pKeyName
, aBuf
, sizeof( aBuf
) );
405 lcl_matchOutputChannel( aBuf
, _out_pnValue
);
408 void lcl_tryReadConfigFlag( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, sal_uIntPtr
* _out_pnAllFlags
, sal_uIntPtr _nCheckFlag
)
411 size_t nValueLen
= lcl_tryReadConfigString( _pLine
, _nLineLen
, _pKeyName
, aBuf
, sizeof( aBuf
) );
414 if ( strcmp( aBuf
, "1" ) == 0 )
415 *_out_pnAllFlags
|= _nCheckFlag
;
417 *_out_pnAllFlags
&= ~_nCheckFlag
;
422 PointerList::~PointerList()
424 PBlock
* pBlock
= pFirst
;
427 PBlock
* pNextBlock
= pBlock
->pNext
;
433 void PointerList::Add( const void* p
)
438 memset( pFirst
->aData
, 0, PBLOCKCOUNT
* sizeof( void* ) );
440 pFirst
->pPrev
= NULL
;
441 pFirst
->pNext
= NULL
;
445 PBlock
* pBlock
= pFirst
;
446 while ( pBlock
&& (pBlock
->nCount
== PBLOCKCOUNT
) )
447 pBlock
= pBlock
->pNext
;
452 memset( pBlock
->aData
, 0, PBLOCKCOUNT
* sizeof( void* ) );
454 pBlock
->pPrev
= pLast
;
455 pBlock
->pNext
= NULL
;
456 pLast
->pNext
= pBlock
;
461 while ( pBlock
->aData
[i
] )
464 pBlock
->aData
[i
] = (void*)p
;
469 sal_Bool
PointerList::Remove( const void* p
)
474 PBlock
* pBlock
= pFirst
;
478 while ( i
< PBLOCKCOUNT
)
480 if ( ((sal_uIntPtr
)p
) == ((sal_uIntPtr
)pBlock
->aData
[i
]) )
482 pBlock
->aData
[i
] = NULL
;
486 if ( !pBlock
->nCount
)
489 pBlock
->pPrev
->pNext
= pBlock
->pNext
;
491 pBlock
->pNext
->pPrev
= pBlock
->pPrev
;
492 if ( pBlock
== pFirst
)
493 pFirst
= pBlock
->pNext
;
494 if ( pBlock
== pLast
)
495 pLast
= pBlock
->pPrev
;
504 pBlock
= pBlock
->pNext
;
510 const void* PointerList::Get( sal_uIntPtr nPos
) const
512 if ( nCount
<= nPos
)
515 PBlock
* pBlock
= pFirst
;
516 sal_uIntPtr nStart
= 0;
520 while ( i
< PBLOCKCOUNT
)
522 if ( pBlock
->aData
[i
] )
525 if ( (nStart
-1) == nPos
)
526 return pBlock
->aData
[i
];
532 pBlock
= pBlock
->pNext
;
538 sal_Bool
PointerList::IsIn( const void* p
) const
543 PBlock
* pBlock
= pFirst
;
547 while ( i
< PBLOCKCOUNT
)
549 if ( ((sal_uIntPtr
)p
) == ((sal_uIntPtr
)pBlock
->aData
[i
]) )
554 pBlock
= pBlock
->pNext
;
560 static void DbgGetDbgFileName( sal_Char
* pStr
, sal_Int32 nMaxLen
)
563 const sal_Char
* pName
= getenv("DBGSV_INIT");
565 pName
= ".dbgsv.init";
566 strncpy( pStr
, pName
, nMaxLen
);
568 const sal_Char
* pName
= getenv("DBGSV_INIT");
570 strncpy( pStr
, pName
, nMaxLen
);
572 GetProfileStringA( "sv", "dbgsv", "dbgsv.ini", pStr
, nMaxLen
);
574 strncpy( pStr
, "dbgsv.ini", nMaxLen
);
576 pStr
[ nMaxLen
- 1 ] = 0;
579 static void DbgGetLogFileName( sal_Char
* pStr
)
582 const sal_Char
* pName
= getenv("DBGSV_LOG");
585 strcpy( pStr
, pName
);
587 const sal_Char
* pName
= getenv("DBGSV_LOG");
589 strcpy( pStr
, pName
);
591 GetProfileStringA( "sv", "dbgsvlog", "dbgsv.log", pStr
, 200 );
593 strcpy( pStr
, "dbgsv.log" );
597 static DebugData
* GetDebugData()
599 if ( !aDebugData
.bInit
)
601 aDebugData
.bInit
= sal_True
;
603 // set default debug names
604 DbgGetLogFileName( aDebugData
.aDbgData
.aDebugName
);
607 sal_Char aBuf
[ 4096 ];
608 DbgGetDbgFileName( aBuf
, sizeof( aBuf
) );
609 FILETYPE pIniFile
= FileOpen( aBuf
, "r" );
610 if ( pIniFile
!= NULL
)
612 ConfigSection eCurrentSection
= eUnknown
;
614 // no sophisticated algorithm here, assume that the whole file fits into aBuf ...
615 sal_uIntPtr nReallyRead
= FileRead( aBuf
, 1, sizeof( aBuf
) / sizeof( sal_Char
) - 1, pIniFile
);
616 aBuf
[ nReallyRead
] = 0;
617 const sal_Char
* pLine
= aBuf
;
618 while ( const sal_Char
* pNextLine
= strstr( pLine
, FILE_LINEEND
) )
620 size_t nLineLength
= pNextLine
- pLine
;
622 if ( lcl_isConfigSection( pLine
, nLineLength
) )
623 eCurrentSection
= lcl_getSectionFromName( pLine
+ 1, nLineLength
- 2 );
625 // elements of the [output] section
626 if ( eCurrentSection
== eOutput
)
628 lcl_tryReadConfigString( pLine
, nLineLength
, "log_file", aDebugData
.aDbgData
.aDebugName
, sizeof( aDebugData
.aDbgData
.aDebugName
) );
629 lcl_tryReadConfigBoolean( pLine
, nLineLength
, "overwrite", &aDebugData
.aDbgData
.bOverwrite
);
630 lcl_tryReadConfigString( pLine
, nLineLength
, "include", aDebugData
.aDbgData
.aInclFilter
, sizeof( aDebugData
.aDbgData
.aInclFilter
) );
631 lcl_tryReadConfigString( pLine
, nLineLength
, "exclude", aDebugData
.aDbgData
.aExclFilter
, sizeof( aDebugData
.aDbgData
.aExclFilter
) );
632 lcl_tryReadConfigString( pLine
, nLineLength
, "include_class", aDebugData
.aDbgData
.aInclClassFilter
, sizeof( aDebugData
.aDbgData
.aInclClassFilter
) );
633 lcl_tryReadConfigString( pLine
, nLineLength
, "exclude_class", aDebugData
.aDbgData
.aExclClassFilter
, sizeof( aDebugData
.aDbgData
.aExclClassFilter
) );
634 lcl_tryReadOutputChannel( pLine
, nLineLength
, "trace", &aDebugData
.aDbgData
.nTraceOut
);
635 lcl_tryReadOutputChannel( pLine
, nLineLength
, "warning", &aDebugData
.aDbgData
.nWarningOut
);
636 lcl_tryReadOutputChannel( pLine
, nLineLength
, "error", &aDebugData
.aDbgData
.nErrorOut
);
637 lcl_tryReadConfigBoolean( pLine
, nLineLength
, "oslhook", &aDebugData
.aDbgData
.bHookOSLAssert
);
640 // elements of the [gui] section
641 if ( eCurrentSection
== eGUI
)
643 lcl_tryReadConfigString( pLine
, nLineLength
, "debug_window_state", aDebugData
.aDbgData
.aDbgWinState
, sizeof( aDebugData
.aDbgData
.aDbgWinState
) );
646 // elements of the [objects] section
647 if ( eCurrentSection
== eObjects
)
649 lcl_tryReadConfigFlag( pLine
, nLineLength
, "check_this", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_XTOR_THIS
);
650 lcl_tryReadConfigFlag( pLine
, nLineLength
, "check_function", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_XTOR_FUNC
);
651 lcl_tryReadConfigFlag( pLine
, nLineLength
, "check_exit", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_XTOR_EXIT
);
652 lcl_tryReadConfigFlag( pLine
, nLineLength
, "generate_report", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_XTOR_REPORT
);
653 lcl_tryReadConfigFlag( pLine
, nLineLength
, "trace", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_XTOR_TRACE
);
656 // elements of the [test] section
657 if ( eCurrentSection
== eTest
)
659 lcl_tryReadConfigFlag( pLine
, nLineLength
, "profiling", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_PROFILING
);
660 lcl_tryReadConfigFlag( pLine
, nLineLength
, "resources", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_RESOURCE
);
661 lcl_tryReadConfigFlag( pLine
, nLineLength
, "dialog", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_DIALOG
);
662 lcl_tryReadConfigFlag( pLine
, nLineLength
, "bold_app_font", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_BOLDAPPFONT
);
665 pLine
= pNextLine
+ strlen( FILE_LINEEND
);
668 FileClose( pIniFile
);
672 lcl_matchOutputChannel( getenv( "DBGSV_TRACE_OUT" ), &aDebugData
.aDbgData
.nTraceOut
);
673 lcl_matchOutputChannel( getenv( "DBGSV_WARNING_OUT" ), &aDebugData
.aDbgData
.nWarningOut
);
674 lcl_matchOutputChannel( getenv( "DBGSV_ERROR_OUT" ), &aDebugData
.aDbgData
.nErrorOut
);
678 sal_Char
* getcwdResult
= getcwd( aCurPath
, sizeof( aCurPath
) );
681 OSL_TRACE( "getcwd failed with error %s", strerror(errno
) );
684 // initialize debug data
685 if ( aDebugData
.aDbgData
.nTestFlags
& DBG_TEST_XTOR
)
686 aDebugData
.pXtorList
= new PointerList
;
687 if ( aDebugData
.aDbgData
.nTestFlags
& DBG_TEST_PROFILING
)
688 aDebugData
.pProfList
= new PointerList
;
694 inline DebugData
* ImplGetDebugData()
696 if ( !aDebugData
.bInit
)
697 return GetDebugData();
702 static FILETYPE
ImplDbgInitFile()
704 static sal_Bool bFileInit
= sal_False
;
707 sal_Char
* getcwdResult
= getcwd( aBuf
, sizeof( aBuf
) );
708 if ( !getcwdResult
) {
709 OSL_TRACE( "getcwd failed with error = %s", strerror(errno
) );
713 int chdirResult
= chdir( aCurPath
);
714 if ( !chdirResult
) {
715 OSL_TRACE ( "chdir failed with error = %s", strerror(errno
) );
719 DebugData
* pData
= GetDebugData();
724 bFileInit
= sal_True
;
726 if ( pData
->aDbgData
.bOverwrite
)
727 pDebugFile
= FileOpen( pData
->aDbgData
.aDebugName
, "w" );
729 pDebugFile
= FileOpen( pData
->aDbgData
.aDebugName
, "a" );
733 time_t nTime
= time( 0 );
737 pTime
= localtime_r( &nTime
, &aTime
);
739 pTime
= localtime( &nTime
);
743 FilePrintF( pDebugFile
, "******************************************************************************%s", FILE_LINEEND
);
744 FilePrintF( pDebugFile
, "%s%s", pData
->aDbgData
.aDebugName
, FILE_LINEEND
);
746 FilePrintF( pDebugFile
, "%s%s", asctime( pTime
), FILE_LINEEND
);
750 pDebugFile
= FileOpen( pData
->aDbgData
.aDebugName
, "a" );
752 chdirResult
= chdir( aBuf
);
755 OSL_TRACE( "chdir failed with error = %s", strerror(errno
) );
761 static void ImplDbgPrintFile( const sal_Char
* pLine
)
763 FILETYPE pDebugFile
= ImplDbgInitFile();
767 FilePrintF( pDebugFile
, "%s%s", pLine
, FILE_LINEEND
);
768 FileClose( pDebugFile
);
772 static int ImplStrSearch( const sal_Char
* pSearchStr
, int nSearchLen
,
773 const sal_Char
* pStr
, int nLen
)
776 while ( nPos
+nSearchLen
<= nLen
)
778 if ( strncmp( pStr
+nPos
, pSearchStr
, nSearchLen
) == 0 )
786 static int ImplDbgFilter( const sal_Char
* pFilter
, const sal_Char
* pMsg
,
789 int nStrLen
= strlen( pFilter
);
793 int nMsgLen
= strlen( pMsg
);
794 const sal_Char
* pTok
= pFilter
;
798 if ( pTok
[nTok
] == ';' )
800 if ( nTok
&& ImplStrSearch( pTok
, nTok
, pMsg
, nMsgLen
) )
810 if ( nTok
&& ImplStrSearch( pTok
, nTok
, pMsg
, nMsgLen
) )
817 void SAL_CALL
dbg_printOslDebugMessage( const sal_Char
* pszFileName
, sal_Int32 nLine
, const sal_Char
* pszMessage
)
819 DbgOut( pszMessage
? pszMessage
: "assertion failed!", DBG_OUT_ERROR
, pszFileName
, (sal_uInt16
)nLine
);
822 static void DebugInit()
824 bDbgImplInMain
= sal_True
;
827 DebugData
* pData
= GetDebugData();
828 if( pData
->aDbgData
.bHookOSLAssert
&& ! pData
->bOslIsHooked
)
830 pData
->pOldDebugMessageFunc
= osl_setDetailedDebugMessageFunc( &dbg_printOslDebugMessage
);
831 pData
->bOslIsHooked
= true;
835 static void DebugDeInit()
837 DebugData
* pData
= GetDebugData();
842 if( pData
->bOslIsHooked
)
844 osl_setDetailedDebugMessageFunc( pData
->pOldDebugMessageFunc
);
845 pData
->bOslIsHooked
= sal_False
;
848 // Output statistics trace data to file
849 nOldOut
= pData
->aDbgData
.nTraceOut
;
850 pData
->aDbgData
.nTraceOut
= DBG_OUT_FILE
;
853 if ( pData
->pXtorList
&& pData
->pXtorList
->Count() &&
854 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_REPORT
) )
856 DbgOutf( "------------------------------------------------------------------------------" );
857 DbgOutf( "Object Report" );
858 DbgOutf( "------------------------------------------------------------------------------" );
859 DbgOutf( "%-27s : %-9s : %-9s : %-7s : %-3s : %-6s :",
860 "XTor-List", "Ctor", "Dtor", "MaxInst", "St.", "Diff." );
861 DbgOutf( "----------------------------:-----------:-----------:---------:----:---------:" );
862 for( i
= 0, nCount
= pData
->pXtorList
->Count(); i
< nCount
; i
++ )
864 XtorType
* pXtorData
= (XtorType
*)pData
->pXtorList
->Get( i
);
865 if ( pXtorData
->bTest
)
867 // Add static objects
868 pXtorData
->nDtorCalls
+= pXtorData
->nStatics
;
869 if ( pXtorData
->nStatics
&& (pXtorData
->nDtorCalls
> pXtorData
->nCtorCalls
) )
870 pXtorData
->nDtorCalls
= pXtorData
->nCtorCalls
;
871 DbgOutf( "%-27s : %9lu : %9lu : %7lu : %3lu : %4lu %-1s :",
872 pXtorData
->aName
, pXtorData
->nCtorCalls
, pXtorData
->nDtorCalls
,
873 pXtorData
->nMaxCount
, pXtorData
->nStatics
,
874 pXtorData
->nCtorCalls
- pXtorData
->nDtorCalls
,
875 (pXtorData
->nCtorCalls
- pXtorData
->nDtorCalls
) ? "!" : " " );
878 DbgOutf( "==============================================================================" );
882 if ( pData
->pXtorList
)
884 for( i
= 0, nCount
= pData
->pXtorList
->Count(); i
< nCount
; i
++ )
886 XtorType
* pXtorData
= (XtorType
*)pData
->pXtorList
->Get( i
);
889 delete pData
->pXtorList
;
890 pData
->pXtorList
= NULL
;
893 // Set everything to sal_False, as global variables
894 // may cause a system crash otherwise.
895 // Maintain memory flags, as otherwise new/delete calls
896 // for global variables will crash,
897 // as pointer alignment won't work then.
898 pData
->aDbgData
.nTraceOut
= nOldOut
;
899 pData
->aDbgData
.nTestFlags
&= DBG_TEST_PROFILING
;
900 pData
->aDbgPrintUserChannels
.clear();
901 pData
->pDbgPrintTestTool
= NULL
;
902 pData
->pDbgPrintWindow
= NULL
;
903 pData
->pOldDebugMessageFunc
= NULL
;
907 static void DebugGlobalDeInit()
909 DebugData
* pData
= GetDebugData();
914 // Output statistics trace data to file
915 nOldOut
= pData
->aDbgData
.nTraceOut
;
916 pData
->aDbgData
.nTraceOut
= DBG_OUT_FILE
;
918 // output profile liste
919 if ( pData
->pProfList
&& pData
->pProfList
->Count() )
921 DbgOutf( "------------------------------------------------------------------------------" );
922 DbgOutf( "Profiling Report" );
923 DbgOutf( "------------------------------------------------------------------------------" );
924 DbgOutf( "%-25s : %-9s : %-6s : %-6s : %-6s : %-9s :",
925 "Prof-List (ms)", "Time", "Min", "Max", "Ave", "Count" );
926 DbgOutf( "--------------------------:-----------:--------:--------:--------:-----------:" );
927 for( i
= 0, nCount
= pData
->pProfList
->Count(); i
< nCount
; i
++ )
929 ProfType
* pProfData
= (ProfType
*)pData
->pProfList
->Get( i
);
930 sal_uIntPtr nAve
= pProfData
->nTime
/ pProfData
->nCount
;
931 DbgOutf( "%-25s : %9lu : %6lu : %6lu : %6lu : %9lu :",
932 pProfData
->aName
, pProfData
->nTime
,
933 pProfData
->nMinTime
, pProfData
->nMaxTime
, nAve
,
936 DbgOutf( "==============================================================================" );
940 if ( pData
->pProfList
)
942 for( i
= 0, nCount
= pData
->pProfList
->Count(); i
< nCount
; i
++ )
944 ProfType
* pProfData
= (ProfType
*)pData
->pProfList
->Get( i
);
947 delete pData
->pProfList
;
948 pData
->pProfList
= NULL
;
951 // disable profiling flags
952 pData
->aDbgData
.nTraceOut
= nOldOut
;
953 pData
->aDbgData
.nTestFlags
&= ~DBG_TEST_PROFILING
;
956 void ImpDbgOutfBuf( sal_Char
* pBuf
, const sal_Char
* pFStr
, ... )
960 va_start( pList
, pFStr
);
961 sal_Char aBuf
[DBG_BUF_MAXLEN
];
962 vsprintf( aBuf
, pFStr
, pList
);
965 strcat( pBuf
, aBuf
);
966 strcat( pBuf
, "\n" );
969 static void DebugXTorInfo( sal_Char
* pBuf
)
971 DebugData
* pData
= GetDebugData();
976 if ( pData
->pXtorList
&& pData
->pXtorList
->Count() &&
977 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_REPORT
) )
979 ImpDbgOutfBuf( pBuf
, "------------------------------------------------------------------------------" );
980 ImpDbgOutfBuf( pBuf
, "Object Report" );
981 ImpDbgOutfBuf( pBuf
, "------------------------------------------------------------------------------" );
982 ImpDbgOutfBuf( pBuf
, "%-27s : %-9s : %-9s : %-7s : %-3s : %-6s :",
983 "XTor-List", "Ctor", "Dtor", "MaxInst", "St.", "Diff." );
984 ImpDbgOutfBuf( pBuf
, "----------------------------:-----------:-----------:---------:----:---------:" );
985 for( i
= 0, nCount
= pData
->pXtorList
->Count(); i
< nCount
; i
++ )
987 XtorType
* pXtorData
= (XtorType
*)pData
->pXtorList
->Get( i
);
988 if ( pXtorData
->bTest
)
990 ImpDbgOutfBuf( pBuf
, "%-27s : %9lu : %9lu : %7lu : %3lu : %6lu :",
991 pXtorData
->aName
, pXtorData
->nCtorCalls
, pXtorData
->nDtorCalls
,
992 pXtorData
->nMaxCount
, pXtorData
->nStatics
,
993 pXtorData
->nCtorCalls
- pXtorData
->nDtorCalls
);
996 ImpDbgOutfBuf( pBuf
, "==============================================================================" );
997 ImpDbgOutfBuf( pBuf
, "" );
1001 sal_Bool
ImplDbgFilterMessage( const sal_Char
* pMsg
)
1003 DebugData
* pData
= GetDebugData();
1004 if ( !ImplDbgFilter( pData
->aDbgData
.aInclFilter
, pMsg
, sal_True
) )
1006 if ( ImplDbgFilter( pData
->aDbgData
.aExclFilter
, pMsg
, sal_False
) )
1011 void* DbgFunc( sal_uInt16 nAction
, void* pParam
)
1013 DebugData
* pDebugData
= ImplGetDebugData();
1015 if ( nAction
== DBG_FUNC_GETDATA
)
1016 return (void*)&(pDebugData
->aDbgData
);
1017 else if ( nAction
== DBG_FUNC_GETPRINTMSGBOX
)
1018 return (void*)(long)(pDebugData
->pDbgPrintMsgBox
);
1019 else if ( nAction
== DBG_FUNC_FILTERMESSAGE
)
1020 if ( ImplDbgFilterMessage( (const sal_Char
*) pParam
) )
1023 return (void*) 0; // aka NULL
1029 case DBG_FUNC_DEBUGSTART
:
1033 case DBG_FUNC_DEBUGEND
:
1037 case DBG_FUNC_GLOBALDEBUGEND
:
1038 DebugGlobalDeInit();
1041 case DBG_FUNC_SETPRINTMSGBOX
:
1042 pDebugData
->pDbgPrintMsgBox
= (DbgPrintLine
)(long)pParam
;
1045 case DBG_FUNC_SETPRINTWINDOW
:
1046 pDebugData
->pDbgPrintWindow
= (DbgPrintLine
)(long)pParam
;
1049 case DBG_FUNC_SETPRINTTESTTOOL
:
1050 pDebugData
->pDbgPrintTestTool
= (DbgPrintLine
)(long)pParam
;
1053 case DBG_FUNC_SET_ABORT
:
1054 pDebugData
->pDbgAbort
= (DbgPrintLine
)(long)pParam
;
1057 case DBG_FUNC_SAVEDATA
:
1059 const DbgData
* pData
= static_cast< const DbgData
* >( pParam
);
1061 sal_Char aBuf
[ 4096 ];
1062 DbgGetDbgFileName( aBuf
, sizeof( aBuf
) );
1063 FILETYPE pIniFile
= FileOpen( aBuf
, "w" );
1064 if ( pIniFile
== NULL
)
1067 lcl_startSection( pIniFile
, eOutput
);
1068 lcl_writeConfigString( pIniFile
, "log_file", pData
->aDebugName
);
1069 lcl_writeConfigBoolean( pIniFile
, "overwrite", pData
->bOverwrite
);
1070 lcl_writeConfigString( pIniFile
, "include", pData
->aInclFilter
);
1071 lcl_writeConfigString( pIniFile
, "exclude", pData
->aExclFilter
);
1072 lcl_writeConfigString( pIniFile
, "include_class", pData
->aInclClassFilter
);
1073 lcl_writeConfigString( pIniFile
, "exclude_class", pData
->aExclClassFilter
);
1074 lcl_writeConfigOutChannel( pIniFile
, "trace", pData
->nTraceOut
);
1075 lcl_writeConfigOutChannel( pIniFile
, "warning", pData
->nWarningOut
);
1076 lcl_writeConfigOutChannel( pIniFile
, "error", pData
->nErrorOut
);
1077 lcl_writeConfigBoolean( pIniFile
, "oslhook", pData
->bHookOSLAssert
);
1079 lcl_lineFeed( pIniFile
);
1080 lcl_startSection( pIniFile
, eGUI
);
1081 lcl_writeConfigString( pIniFile
, "debug_window_state", pData
->aDbgWinState
);
1083 lcl_lineFeed( pIniFile
);
1084 lcl_startSection( pIniFile
, eObjects
);
1085 lcl_writeConfigFlag( pIniFile
, "check_this", pData
->nTestFlags
, DBG_TEST_XTOR_THIS
);
1086 lcl_writeConfigFlag( pIniFile
, "check_function", pData
->nTestFlags
, DBG_TEST_XTOR_FUNC
);
1087 lcl_writeConfigFlag( pIniFile
, "check_exit", pData
->nTestFlags
, DBG_TEST_XTOR_EXIT
);
1088 lcl_writeConfigFlag( pIniFile
, "generate_report", pData
->nTestFlags
, DBG_TEST_XTOR_REPORT
);
1089 lcl_writeConfigFlag( pIniFile
, "trace", pData
->nTestFlags
, DBG_TEST_XTOR_TRACE
);
1091 lcl_lineFeed( pIniFile
);
1092 lcl_startSection( pIniFile
, eTest
);
1093 lcl_writeConfigFlag( pIniFile
, "profiling", pData
->nTestFlags
, DBG_TEST_PROFILING
);
1094 lcl_writeConfigFlag( pIniFile
, "resources", pData
->nTestFlags
, DBG_TEST_RESOURCE
);
1095 lcl_writeConfigFlag( pIniFile
, "dialog", pData
->nTestFlags
, DBG_TEST_DIALOG
);
1096 lcl_writeConfigFlag( pIniFile
, "bold_app_font", pData
->nTestFlags
, DBG_TEST_BOLDAPPFONT
);
1098 FileClose( pIniFile
);
1102 case DBG_FUNC_XTORINFO
:
1103 DebugXTorInfo( (sal_Char
*)pParam
);
1106 case DBG_FUNC_COREDUMP
:
1110 case DBG_FUNC_ALLERROROUT
:
1111 return (void*)(sal_uIntPtr
)sal_True
;
1113 case DBG_FUNC_SETTESTSOLARMUTEX
:
1114 pDebugData
->pDbgTestSolarMutex
= (DbgTestSolarMutexProc
)(long)pParam
;
1117 case DBG_FUNC_TESTSOLARMUTEX
:
1118 if ( pDebugData
->pDbgTestSolarMutex
)
1119 pDebugData
->pDbgTestSolarMutex();
1122 case DBG_FUNC_PRINTFILE
:
1123 ImplDbgPrintFile( (const sal_Char
*)pParam
);
1125 case DBG_FUNC_UPDATEOSLHOOK
:
1127 const DbgData
* pData
= static_cast< const DbgData
* >( pParam
);
1128 pDebugData
->aDbgData
.bHookOSLAssert
= pData
->bHookOSLAssert
;
1129 if( pDebugData
->bOslIsHooked
&& ! pData
->bHookOSLAssert
)
1131 osl_setDetailedDebugMessageFunc( pDebugData
->pOldDebugMessageFunc
);
1132 pDebugData
->bOslIsHooked
= sal_False
;
1134 else if( ! pDebugData
->bOslIsHooked
&& pData
->bHookOSLAssert
)
1136 pDebugData
->pOldDebugMessageFunc
= osl_setDetailedDebugMessageFunc( &dbg_printOslDebugMessage
);
1137 pDebugData
->bOslIsHooked
= sal_True
;
1147 DbgChannelId
DbgRegisterUserChannel( DbgPrintLine pProc
)
1149 DebugData
* pData
= ImplGetDebugData();
1150 pData
->aDbgPrintUserChannels
.push_back( pProc
);
1151 return (DbgChannelId
)( pData
->aDbgPrintUserChannels
.size() - 1 + DBG_OUT_USER_CHANNEL_0
);
1154 void DbgProf( sal_uInt16 nAction
, DbgDataType
* pDbgData
)
1156 DebugData
* pData
= ImplGetDebugData();
1158 if ( !(pData
->aDbgData
.nTestFlags
& DBG_TEST_PROFILING
) )
1161 ProfType
* pProfData
= (ProfType
*)pDbgData
->pData
;
1163 if ( (nAction
!= DBG_PROF_START
) && !pProfData
)
1167 "DBG_PROF...() without DBG_PROFSTART(): " << pDbgData
->pName
);
1173 case DBG_PROF_START
:
1174 if ( !pDbgData
->pData
)
1176 pDbgData
->pData
= (void*)new ProfType
;
1177 pProfData
= (ProfType
*)pDbgData
->pData
;
1178 strncpy( pProfData
->aName
, pDbgData
->pName
, DBG_MAXNAME
);
1179 pProfData
->aName
[DBG_MAXNAME
] = '\0';
1180 pProfData
->nCount
= 0;
1181 pProfData
->nTime
= 0;
1182 pProfData
->nMinTime
= 0xFFFFFFFF;
1183 pProfData
->nMaxTime
= 0;
1184 pProfData
->nStart
= 0xFFFFFFFF;
1185 pProfData
->nContinueTime
= 0;
1186 pProfData
->nContinueStart
= 0xFFFFFFFF;
1187 pData
->pProfList
->Add( (void*)pProfData
);
1190 if ( pProfData
->nStart
== 0xFFFFFFFF )
1192 pProfData
->nStart
= ImplGetPerfTime();
1193 pProfData
->nCount
++;
1198 nTime
= ImplGetPerfTime();
1200 if ( pProfData
->nStart
== 0xFFFFFFFF )
1203 "tools.debug", "DBG_PROF...() without DBG_PROFSTART()");
1207 if ( pProfData
->nContinueStart
!= 0xFFFFFFFF )
1209 pProfData
->nContinueTime
+= ImplGetPerfTime() - pProfData
->nContinueStart
;
1210 pProfData
->nContinueStart
= 0xFFFFFFFF;
1213 nTime
-= pProfData
->nStart
;
1214 nTime
-= pProfData
->nContinueTime
;
1216 if ( nTime
< pProfData
->nMinTime
)
1217 pProfData
->nMinTime
= nTime
;
1219 if ( nTime
> pProfData
->nMaxTime
)
1220 pProfData
->nMaxTime
= nTime
;
1222 pProfData
->nTime
+= nTime
;
1224 pProfData
->nStart
= 0xFFFFFFFF;
1225 pProfData
->nContinueTime
= 0;
1226 pProfData
->nContinueStart
= 0xFFFFFFFF;
1229 case DBG_PROF_CONTINUE
:
1230 if ( pProfData
->nContinueStart
!= 0xFFFFFFFF )
1232 pProfData
->nContinueTime
+= ImplGetPerfTime() - pProfData
->nContinueStart
;
1233 pProfData
->nContinueStart
= 0xFFFFFFFF;
1237 case DBG_PROF_PAUSE
:
1238 if ( pProfData
->nContinueStart
== 0xFFFFFFFF )
1239 pProfData
->nContinueStart
= ImplGetPerfTime();
1244 void DbgXtor( DbgDataType
* pDbgData
, sal_uInt16 nAction
, const void* pThis
,
1247 DebugData
* pData
= ImplGetDebugData();
1250 if ( !(pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR
) )
1253 XtorType
* pXtorData
= (XtorType
*)pDbgData
->pData
;
1256 pDbgData
->pData
= (void*)new XtorType
;
1257 pXtorData
= (XtorType
*)pDbgData
->pData
;
1258 strncpy( pXtorData
->aName
, pDbgData
->pName
, DBG_MAXNAME
);
1259 pXtorData
->aName
[DBG_MAXNAME
] = '\0';
1260 pXtorData
->nCtorCalls
= 0;
1261 pXtorData
->nDtorCalls
= 0;
1262 pXtorData
->nMaxCount
= 0;
1263 pXtorData
->nStatics
= 0;
1264 pXtorData
->bTest
= sal_True
;
1265 pData
->pXtorList
->Add( (void*)pXtorData
);
1267 if ( !ImplDbgFilter( pData
->aDbgData
.aInclClassFilter
, pXtorData
->aName
, sal_True
) )
1268 pXtorData
->bTest
= sal_False
;
1269 if ( ImplDbgFilter( pData
->aDbgData
.aExclClassFilter
, pXtorData
->aName
, sal_False
) )
1270 pXtorData
->bTest
= sal_False
;
1272 if ( !pXtorData
->bTest
)
1275 sal_uInt16 nAct
= nAction
& ~DBG_XTOR_DTOROBJ
;
1278 ((pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_TRACE
)
1279 && !(nAction
& DBG_XTOR_DTOROBJ
) && nAct
!= DBG_XTOR_CHKOBJ
),
1281 (nAct
== DBG_XTOR_CTOR
? "Enter Ctor from class "
1282 : nAct
== DBG_XTOR_DTOR
? "Enter Dtor from class "
1283 : "Enter method from class ") << pDbgData
->pName
);
1285 // If some Xtor-tests are still tracing
1286 if ( pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_EXTRA
)
1288 // call DBG_CTOR before all other DBG_XTOR calls
1289 if ( ((nAction
& ~DBG_XTOR_DTOROBJ
) != DBG_XTOR_CTOR
) && !pDbgData
->pData
)
1293 "DBG_DTOR() or DBG_CHKTHIS() without DBG_CTOR(): "
1294 << pDbgData
->pName
);
1298 // Test if the pointer is still valid
1299 if ( pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_THIS
)
1301 if ( (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_EXIT
) ||
1302 !(nAction
& DBG_XTOR_DTOROBJ
) )
1304 // This-Pointer == NULL
1309 "this == NULL in class " << pDbgData
->pName
);
1313 if ( (nAction
& ~DBG_XTOR_DTOROBJ
) != DBG_XTOR_CTOR
)
1316 !pXtorData
->aThisList
.IsIn(pThis
), "tools.debug",
1317 "invalid this-Pointer %p in class " << pDbgData
->pName
);
1322 // execute function test and update maintenance data
1323 const sal_Char
* pMsg
= NULL
;
1324 switch ( nAction
& ~DBG_XTOR_DTOROBJ
)
1327 if ( nAction
& DBG_XTOR_DTOROBJ
)
1330 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_EXIT
) &&
1331 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_FUNC
) )
1332 pMsg
= fDbgUsr( pThis
);
1336 pXtorData
->nCtorCalls
++;
1337 if ( !bDbgImplInMain
)
1338 pXtorData
->nStatics
++;
1339 if ( (pXtorData
->nCtorCalls
-pXtorData
->nDtorCalls
) > pXtorData
->nMaxCount
)
1340 pXtorData
->nMaxCount
= pXtorData
->nCtorCalls
- pXtorData
->nDtorCalls
;
1342 if ( pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_THIS
)
1343 pXtorData
->aThisList
.Add( pThis
);
1348 if ( nAction
& DBG_XTOR_DTOROBJ
)
1350 pXtorData
->nDtorCalls
++;
1351 if ( pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_THIS
)
1352 pXtorData
->aThisList
.Remove( pThis
);
1357 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_FUNC
) )
1358 pMsg
= fDbgUsr( pThis
);
1362 case DBG_XTOR_CHKTHIS
:
1363 case DBG_XTOR_CHKOBJ
:
1364 if ( nAction
& DBG_XTOR_DTOROBJ
)
1367 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_EXIT
) &&
1368 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_FUNC
) )
1369 pMsg
= fDbgUsr( pThis
);
1374 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_FUNC
) )
1375 pMsg
= fDbgUsr( pThis
);
1381 pMsg
, "tools.debug",
1382 "Error-Msg from Object " << pThis
<< " in class "
1383 << pDbgData
->pName
<< ": " << pMsg
);
1387 ((pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_TRACE
)
1388 && (nAction
& DBG_XTOR_DTOROBJ
) && nAct
!= DBG_XTOR_CHKOBJ
),
1390 (nAct
== DBG_XTOR_CTOR
1391 ? "Leave Ctor from class "
1392 : nAct
== DBG_XTOR_DTOR
1393 ? "Leave Dtor from class "
1394 : "Leave method from class ") << pDbgData
->pName
);
1397 void DbgOut( const sal_Char
* pMsg
, sal_uInt16 nDbgOut
, const sal_Char
* pFile
, sal_uInt16 nLine
)
1399 static sal_Bool bIn
= sal_False
;
1404 DebugData
* pData
= GetDebugData();
1405 sal_Char
const * pStr
;
1409 if ( nDbgOut
== DBG_OUT_ERROR
)
1411 nOut
= pData
->aDbgData
.nErrorOut
;
1414 else if ( nDbgOut
== DBG_OUT_WARNING
)
1416 nOut
= pData
->aDbgData
.nWarningOut
;
1421 nOut
= pData
->aDbgData
.nTraceOut
;
1425 if ( nOut
== DBG_OUT_NULL
)
1431 if ( ImplDbgFilterMessage( pMsg
) )
1439 sal_Char aBufOut
[DBG_BUF_MAXLEN
];
1442 strcpy( aBufOut
, pStr
);
1443 nBufLen
= strlen( pStr
);
1448 int nMsgLen
= strlen( pMsg
);
1449 if ( nBufLen
+nMsgLen
> DBG_BUF_MAXLEN
)
1451 int nCopyLen
= DBG_BUF_MAXLEN
-nBufLen
-4;
1452 strncpy( &(aBufOut
[nBufLen
]), pMsg
, nCopyLen
);
1453 strcpy( &(aBufOut
[nBufLen
+nCopyLen
]), "..." );
1456 strcpy( &(aBufOut
[nBufLen
]), pMsg
);
1458 if ( pFile
&& nLine
&& (nBufLen
+nMsgLen
< DBG_BUF_MAXLEN
) )
1460 if ( nOut
== DBG_OUT_MSGBOX
)
1461 strcat( aBufOut
, "\n" );
1463 strcat( aBufOut
, " " );
1464 strcat( aBufOut
, "From File " );
1465 strcat( aBufOut
, pFile
);
1466 strcat( aBufOut
, " at Line " );
1468 // Convert line to String and append
1470 sal_Char
* pLine
= &aLine
[7];
1472 memset( aLine
, 0, sizeof( aLine
) );
1477 *(pLine
) = (sal_Char
)i
+ 48;
1481 strcat( aBufOut
, pLine
);
1484 if ( ( nOut
>= DBG_OUT_USER_CHANNEL_0
) && ( nOut
- DBG_OUT_USER_CHANNEL_0
< pData
->aDbgPrintUserChannels
.size() ) )
1486 DbgPrintLine pPrinter
= pData
->aDbgPrintUserChannels
[ nOut
- DBG_OUT_USER_CHANNEL_0
];
1488 pPrinter( aBufOut
);
1490 nOut
= DBG_OUT_DEBUGGER
;
1493 if ( nOut
== DBG_OUT_ABORT
)
1495 if ( pData
->pDbgAbort
!= NULL
)
1496 pData
->pDbgAbort( aBufOut
);
1500 if ( nOut
== DBG_OUT_DEBUGGER
)
1502 if ( !ImplActivateDebugger( aBufOut
) )
1503 nOut
= DBG_OUT_TESTTOOL
;
1506 if ( nOut
== DBG_OUT_TESTTOOL
)
1508 if ( pData
->pDbgPrintTestTool
)
1509 pData
->pDbgPrintTestTool( aBufOut
);
1511 nOut
= DBG_OUT_MSGBOX
;
1514 if ( nOut
== DBG_OUT_MSGBOX
)
1516 if ( pData
->pDbgPrintMsgBox
)
1517 pData
->pDbgPrintMsgBox( aBufOut
);
1519 nOut
= DBG_OUT_WINDOW
;
1522 if ( nOut
== DBG_OUT_WINDOW
)
1524 if ( pData
->pDbgPrintWindow
)
1525 pData
->pDbgPrintWindow( aBufOut
);
1527 nOut
= DBG_OUT_FILE
;
1533 DbgPrintShell( aBufOut
);
1536 ImplDbgPrintFile( aBufOut
);
1545 void DbgPrintShell(char const * message
) {
1546 fprintf(stderr
, "%s\n", message
);
1548 OutputDebugStringA(message
);
1552 void DbgOutTypef( sal_uInt16 nDbgOut
, const sal_Char
* pFStr
, ... )
1556 va_start( pList
, pFStr
);
1557 sal_Char aBuf
[DBG_BUF_MAXLEN
];
1558 vsprintf( aBuf
, pFStr
, pList
);
1561 DbgOut( aBuf
, nDbgOut
);
1564 void DbgOutf( const sal_Char
* pFStr
, ... )
1568 va_start( pList
, pFStr
);
1569 sal_Char aBuf
[DBG_BUF_MAXLEN
];
1570 vsprintf( aBuf
, pFStr
, pList
);
1578 void* DbgFunc( sal_uInt16
, void* ) { return NULL
; }
1580 void DbgProf( sal_uInt16
, DbgDataType
* ) {}
1581 void DbgXtor( DbgDataType
*, sal_uInt16
, const void*, DbgUsr
) {}
1583 void DbgOut( const sal_Char
*, sal_uInt16
, const sal_Char
*, sal_uInt16
) {}
1584 void DbgOutTypef( sal_uInt16
, const sal_Char
*, ... ) {}
1585 void DbgOutf( const sal_Char
*, ... ) {}
1590 #if OSL_DEBUG_LEVEL > 0
1592 TOOLS_DLLPUBLIC
void DbgUnhandledException(const css::uno::Any
& caught
, const char* currentFunction
, const char* fileAndLineNo
)
1594 OString
sMessage( "caught an exception!" );
1595 sMessage
+= "\nin function:";
1596 sMessage
+= currentFunction
;
1597 sMessage
+= "\ntype: ";
1598 sMessage
+= OUStringToOString( caught
.getValueTypeName(), osl_getThreadTextEncoding() );
1599 ::com::sun::star::uno::Exception exception
;
1600 caught
>>= exception
;
1601 if ( !exception
.Message
.isEmpty() )
1603 sMessage
+= "\nmessage: ";
1604 sMessage
+= OUStringToOString( exception
.Message
, osl_getThreadTextEncoding() );
1606 if ( exception
.Context
.is() )
1608 const char* pContext
= typeid( *exception
.Context
.get() ).name();
1609 sMessage
+= "\ncontext: ";
1610 sMessage
+= pContext
;
1613 ::com::sun::star::configuration::CorruptedConfigurationException
1615 if ( caught
>>= specialized
)
1617 sMessage
+= "\ndetails: ";
1618 sMessage
+= OUStringToOString(
1619 specialized
.Details
, osl_getThreadTextEncoding() );
1623 ::com::sun::star::task::ErrorCodeIOException specialized
;
1624 if ( caught
>>= specialized
)
1626 sMessage
+= "\ndetails: ";
1627 sMessage
+= OString::valueOf( specialized
.ErrCode
);
1632 SAL_DETAIL_LOG_FORMAT(
1633 SAL_DETAIL_ENABLE_LOG_WARN
, SAL_DETAIL_LOG_LEVEL_WARN
,
1634 "legacy.osl", fileAndLineNo
, "%s", sMessage
.getStr());
1637 #endif // OSL_DEBUG_LEVEL
1640 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */