1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: debug.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
34 #define _TOOLS_DEBUG_CXX
36 #if defined (UNX) || defined (GCC)
43 #include <cstdarg> // combinations
49 #define INCL_DOSSEMAPHORES
51 #define INCL_WINDIALOGS
52 #define INCL_WINSHELLDATA
58 #pragma warning (push,1)
60 #include <tools/svwin.h>
66 #include <tools/debug.hxx>
67 #include <rtl/string.h>
71 #include <osl/diagnose.h>
73 // =======================================================================
79 static sal_Char
const DbgError_ProfEnd1
[] = "DBG_PROF...() without DBG_PROFSTART(): ";
80 static sal_Char
const DbgError_Xtor1
[] = "DBG_DTOR() or DBG_CHKTHIS() without DBG_CTOR(): ";
82 static sal_Char
const DbgError_CtorDtor1
[] = "this == NULL in class ";
83 static sal_Char
const DbgError_CtorDtor2
[] = "invalid this-Pointer %p in class ";
84 static sal_Char
const DbgError_CtorDtor3
[] = "Error-Msg from Object %p in class ";
86 static sal_Char
const DbgTrace_EnterCtor
[] = "Enter Ctor from class ";
87 static sal_Char
const DbgTrace_LeaveCtor
[] = "Leave Ctor from class ";
88 static sal_Char
const DbgTrace_EnterDtor
[] = "Enter Dtor from class ";
89 static sal_Char
const DbgTrace_LeaveDtor
[] = "Leave Dtor from class ";
90 static sal_Char
const DbgTrace_EnterMeth
[] = "Enter method from class ";
91 static sal_Char
const DbgTrace_LeaveMeth
[] = "Leave method from class ";
93 // --- PointerList ---
95 #define PBLOCKCOUNT 1024
99 void* aData
[PBLOCKCOUNT
];
113 PointerList() { pFirst
= NULL
; pLast
= NULL
; nCount
= 0; }
116 void Add( const void* p
);
117 BOOL
Remove( const void* p
);
119 const void* Get( ULONG nPos
) const;
120 BOOL
IsIn( const void* p
) const;
121 ULONG
Count() const { return nCount
; }
124 // --- Datentypen ---
126 #define DBG_MAXNAME 28
136 ULONG nContinueStart
;
137 sal_Char aName
[DBG_MAXNAME
+1];
146 sal_Char aName
[DBG_MAXNAME
+1];
148 PointerList aThisList
;
155 DbgPrintLine pDbgPrintMsgBox
;
156 DbgPrintLine pDbgPrintWindow
;
157 DbgPrintLine pDbgPrintShell
;
158 DbgPrintLine pDbgPrintTestTool
;
159 ::std::vector
< DbgPrintLine
>
160 aDbgPrintUserChannels
;
161 PointerList
* pProfList
;
162 PointerList
* pXtorList
;
163 DbgTestSolarMutexProc pDbgTestSolarMutex
;
164 pfunc_osl_printDetailedDebugMessage
165 pOldDebugMessageFunc
;
170 ,pDbgPrintMsgBox( FALSE
)
171 ,pDbgPrintWindow( NULL
)
172 ,pDbgPrintShell( NULL
)
173 ,pDbgPrintTestTool( NULL
)
176 ,pDbgTestSolarMutex( NULL
)
177 ,pOldDebugMessageFunc( NULL
)
178 ,bOslIsHooked( false )
180 aDbgData
.nTestFlags
= DBG_TEST_RESOURCE
| DBG_TEST_MEM_INIT
;
181 aDbgData
.bOverwrite
= TRUE
;
182 aDbgData
.nTraceOut
= DBG_OUT_NULL
;
183 aDbgData
.nWarningOut
= DBG_OUT_NULL
;
185 aDbgData
.nErrorOut
= DBG_OUT_SHELL
;
187 aDbgData
.nErrorOut
= DBG_OUT_MSGBOX
;
189 aDbgData
.bMemInit
= 0x77;
190 aDbgData
.bMemBound
= 0x55;
191 aDbgData
.bMemFree
= 0x33;
192 aDbgData
.bHookOSLAssert
= TRUE
;
193 aDbgData
.aDebugName
[0] = 0;
194 aDbgData
.aInclFilter
[0] = 0;
195 aDbgData
.aExclFilter
[0] = 0;
196 aDbgData
.aInclClassFilter
[0] = 0;
197 aDbgData
.aExclClassFilter
[0] = 0;
198 aDbgData
.aDbgWinState
[0] = 0;
202 #define DBG_TEST_XTOR_EXTRA (DBG_TEST_XTOR_THIS | DBG_TEST_XTOR_FUNC | \
203 DBG_TEST_XTOR_EXIT | DBG_TEST_XTOR_REPORT )
205 // ------------------------------
206 // - statische Verwaltungsdaten -
207 // ------------------------------
209 static DebugData aDebugData
;
211 static sal_Char aCurPath
[260];
213 static int bDbgImplInMain
= FALSE
;
215 // =======================================================================
218 static CRITICAL_SECTION aImplCritDbgSection
;
220 static HMTX hImplCritDbgSection
= 0;
222 static BOOL bImplCritDbgSectionInit
= FALSE
;
224 // -----------------------------------------------------------------------
226 void ImplDbgInitLock()
229 InitializeCriticalSection( &aImplCritDbgSection
);
231 DosCreateMutexSem( NULL
, &hImplCritDbgSection
, 0, FALSE
);
233 bImplCritDbgSectionInit
= TRUE
;
236 // -----------------------------------------------------------------------
238 void ImplDbgDeInitLock()
241 DeleteCriticalSection( &aImplCritDbgSection
);
243 DosCloseMutexSem( hImplCritDbgSection
);
245 bImplCritDbgSectionInit
= FALSE
;
248 // -----------------------------------------------------------------------
252 if ( !bImplCritDbgSectionInit
)
256 EnterCriticalSection( &aImplCritDbgSection
);
258 DosRequestMutexSem( hImplCritDbgSection
, SEM_INDEFINITE_WAIT
);
262 // -----------------------------------------------------------------------
266 if ( !bImplCritDbgSectionInit
)
270 LeaveCriticalSection( &aImplCritDbgSection
);
272 DosReleaseMutexSem( hImplCritDbgSection
);
276 // =======================================================================
278 #if (defined WNT || defined OS2) && !defined SVX_LIGHT
279 //#define SV_MEMMGR //
282 void DbgImpCheckMemory( void* p
= NULL
);
283 void DbgImpCheckMemoryDeInit();
284 void DbgImpMemoryInfo( sal_Char
* pBuf
);
287 #define FILE_LINEEND "\n"
289 // =======================================================================
291 static BOOL
ImplActivateDebugger( const sal_Char
* pMsg
)
294 static sal_Char aImplDbgOutBuf
[DBG_BUF_MAXLEN
];
295 strcpy( aImplDbgOutBuf
, pMsg
);
296 strcat( aImplDbgOutBuf
, "\r\n" );
297 OutputDebugString( aImplDbgOutBuf
);
301 (void) pMsg
; // avoid warning about unused parameter
306 // -----------------------------------------------------------------------
308 static BOOL
ImplCoreDump()
319 // =======================================================================
321 static ULONG
ImplGetPerfTime()
324 return (ULONG
)GetTickCount();
327 DosQuerySysInfo( QSV_MS_COUNT
, QSV_MS_COUNT
, &nClock
, sizeof( nClock
) );
328 return (ULONG
)nClock
;
330 static ULONG nImplTicksPerSecond
= 0;
331 static double dImplTicksPerSecond
;
332 ULONG nTicks
= (ULONG
)clock();
334 if ( !nImplTicksPerSecond
)
336 nImplTicksPerSecond
= CLOCKS_PER_SEC
;
337 dImplTicksPerSecond
= nImplTicksPerSecond
;
340 double fTicks
= nTicks
;
342 fTicks
/= dImplTicksPerSecond
;
343 return (ULONG
)fTicks
;
347 // -----------------------------------------------------------------------
349 typedef FILE* FILETYPE
;
350 #define FileOpen fopen
351 #define FileRead fread
352 #define FileWrite fwrite
353 #define FilePrintF fprintf
354 #define FileClose fclose
356 // =======================================================================
371 void lcl_lineFeed( FILETYPE _pFile
)
373 FilePrintF( _pFile
, "%s", FILE_LINEEND
);
376 const sal_Char
* lcl_getSectionName( ConfigSection _eSection
)
378 const sal_Char
* pSectionName
= NULL
;
381 case eOutput
: pSectionName
= "output"; break;
382 case eMemory
: pSectionName
= "memory"; break;
383 case eGUI
: pSectionName
= "gui"; break;
384 case eObjects
: pSectionName
= "objects"; break;
385 case eTest
: pSectionName
= "test"; break;
393 ConfigSection
lcl_getSectionFromName( const sal_Char
* _pSectionName
, size_t _nSectionNameLength
)
395 if ( strncmp( _pSectionName
, "output", _nSectionNameLength
< 6 ? _nSectionNameLength
: 6 ) == 0 )
397 if ( strncmp( _pSectionName
, "memory", _nSectionNameLength
< 6 ? _nSectionNameLength
: 6 ) == 0 )
399 if ( strncmp( _pSectionName
, "gui", _nSectionNameLength
< 3 ? _nSectionNameLength
: 3 ) == 0 )
401 if ( strncmp( _pSectionName
, "objects", _nSectionNameLength
< 7 ? _nSectionNameLength
: 7 ) == 0 )
403 if ( strncmp( _pSectionName
, "test", _nSectionNameLength
< 4 ? _nSectionNameLength
: 4 ) == 0 )
408 void lcl_startSection( FILETYPE _pFile
, ConfigSection _eSection
)
410 FilePrintF( _pFile
, "[%s]%s", lcl_getSectionName( _eSection
), FILE_LINEEND
);
413 void lcl_writeConfigString( FILETYPE _pFile
, const sal_Char
* _pKeyName
, const sal_Char
* _pValue
)
415 FilePrintF( _pFile
, "%s=%s%s", _pKeyName
, _pValue
, FILE_LINEEND
);
418 void lcl_writeConfigBoolean( FILETYPE _pFile
, const sal_Char
* _pKeyName
, bool _bValue
)
420 lcl_writeConfigString( _pFile
, _pKeyName
, _bValue
? "1" : "0" );
423 void lcl_writeConfigFlag( FILETYPE _pFile
, const sal_Char
* _pKeyName
, ULONG _nAllFlags
, ULONG _nCheckFlag
)
425 lcl_writeConfigBoolean( _pFile
, _pKeyName
, ( _nAllFlags
& _nCheckFlag
) != 0 );
428 void lcl_writeConfigOutChannel( FILETYPE _pFile
, const sal_Char
* _pKeyName
, ULONG _nValue
)
430 const sal_Char
* names
[ DBG_OUT_COUNT
] =
432 "dev/null", "file", "window", "shell", "messagebox", "testtool", "debugger", "coredump"
434 lcl_writeConfigString( _pFile
, _pKeyName
, names
[ _nValue
] );
436 void lcl_writeHexByte( FILETYPE _pFile
, const sal_Char
* _pKeyName
, BYTE _nValue
)
438 sal_Char buf
[RTL_STR_MAX_VALUEOFINT32
];
439 rtl_String
* stringData
= NULL
;
440 rtl_string_newFromStr_WithLength( &stringData
, buf
, rtl_str_valueOfInt32( buf
, _nValue
, 16 ) );
442 lcl_writeConfigString( _pFile
, _pKeyName
, stringData
->buffer
);
444 rtl_string_release( stringData
);
446 bool lcl_isConfigSection( const sal_Char
* _pLine
, size_t _nLineLen
)
449 // not even enough space for '[' and ']'
451 if ( ( _pLine
[0] == '[' ) && ( _pLine
[ _nLineLen
- 1 ] == ']' ) )
455 bool lcl_isConfigKey( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
)
457 size_t nKeyLength
= strlen( _pKeyName
);
458 if ( nKeyLength
+ 1 >= _nLineLen
)
459 // not even long enough for the key name plus "=" plus a one-character value
461 if ( ( strncmp( _pLine
, _pKeyName
, nKeyLength
) == 0 ) && ( _pLine
[ nKeyLength
] == '=' ) )
465 sal_Int32
lcl_tryReadConfigString( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, sal_Char
* _pValue
, size_t _nValueLen
)
467 if ( !lcl_isConfigKey( _pLine
, _nLineLen
, _pKeyName
) )
469 size_t nValuePos
= strlen( _pKeyName
) + 1;
470 size_t nValueLen
= _nLineLen
- nValuePos
;
471 const sal_Char
* pValue
= _pLine
+ nValuePos
;
472 strncpy( _pValue
, pValue
, ( _nValueLen
> nValueLen
) ? nValueLen
: _nValueLen
);
473 _pValue
[ ( _nValueLen
> nValueLen
) ? nValueLen
: _nValueLen
- 1 ] = 0;
474 return strlen( _pValue
);
476 void lcl_tryReadConfigBoolean( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, ULONG
* _out_pnValue
)
479 size_t nValueLen
= lcl_tryReadConfigString( _pLine
, _nLineLen
, _pKeyName
, aBuf
, sizeof( aBuf
) );
481 *_out_pnValue
= strcmp( aBuf
, "1" ) == 0 ? TRUE
: FALSE
;
483 void lcl_tryReadOutputChannel( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, ULONG
* _out_pnValue
)
485 const sal_Char
* names
[ DBG_OUT_COUNT
] =
487 "dev/null", "file", "window", "shell", "messagebox", "testtool", "debugger", "coredump"
490 size_t nValueLen
= lcl_tryReadConfigString( _pLine
, _nLineLen
, _pKeyName
, aBuf
, sizeof( aBuf
) );
493 for ( ULONG name
= 0; name
< sizeof( names
) / sizeof( names
[0] ); ++name
)
495 if ( strcmp( aBuf
, names
[ name
] ) == 0 )
497 *_out_pnValue
= name
;
503 void lcl_tryReadConfigFlag( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, ULONG
* _out_pnAllFlags
, ULONG _nCheckFlag
)
506 size_t nValueLen
= lcl_tryReadConfigString( _pLine
, _nLineLen
, _pKeyName
, aBuf
, sizeof( aBuf
) );
508 if ( strcmp( aBuf
, "1" ) == 0 )
509 *_out_pnAllFlags
|= _nCheckFlag
;
511 *_out_pnAllFlags
&= ~_nCheckFlag
;
513 void lcl_tryReadHexByte( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, BYTE
* _out_pnValue
)
516 size_t nValueLen
= lcl_tryReadConfigString( _pLine
, _nLineLen
, _pKeyName
, aBuf
, sizeof( aBuf
) );
518 *_out_pnValue
= (BYTE
)rtl_str_toInt32( aBuf
, 16 );
522 // =======================================================================
524 PointerList::~PointerList()
526 PBlock
* pBlock
= pFirst
;
529 PBlock
* pNextBlock
= pBlock
->pNext
;
535 // -----------------------------------------------------------------------
537 void PointerList::Add( const void* p
)
542 memset( pFirst
->aData
, 0, PBLOCKCOUNT
* sizeof( void* ) );
544 pFirst
->pPrev
= NULL
;
545 pFirst
->pNext
= NULL
;
549 PBlock
* pBlock
= pFirst
;
550 while ( pBlock
&& (pBlock
->nCount
== PBLOCKCOUNT
) )
551 pBlock
= pBlock
->pNext
;
556 memset( pBlock
->aData
, 0, PBLOCKCOUNT
* sizeof( void* ) );
558 pBlock
->pPrev
= pLast
;
559 pBlock
->pNext
= NULL
;
560 pLast
->pNext
= pBlock
;
565 while ( pBlock
->aData
[i
] )
568 pBlock
->aData
[i
] = (void*)p
;
573 // -----------------------------------------------------------------------
575 BOOL
PointerList::Remove( const void* p
)
580 PBlock
* pBlock
= pFirst
;
584 while ( i
< PBLOCKCOUNT
)
586 if ( ((ULONG
)p
) == ((ULONG
)pBlock
->aData
[i
]) )
588 pBlock
->aData
[i
] = NULL
;
592 if ( !pBlock
->nCount
)
595 pBlock
->pPrev
->pNext
= pBlock
->pNext
;
597 pBlock
->pNext
->pPrev
= pBlock
->pPrev
;
598 if ( pBlock
== pFirst
)
599 pFirst
= pBlock
->pNext
;
600 if ( pBlock
== pLast
)
601 pLast
= pBlock
->pPrev
;
610 pBlock
= pBlock
->pNext
;
616 // -----------------------------------------------------------------------
618 const void* PointerList::Get( ULONG nPos
) const
620 if ( nCount
<= nPos
)
623 PBlock
* pBlock
= pFirst
;
628 while ( i
< PBLOCKCOUNT
)
630 if ( pBlock
->aData
[i
] )
633 if ( (nStart
-1) == nPos
)
634 return pBlock
->aData
[i
];
640 pBlock
= pBlock
->pNext
;
646 // -----------------------------------------------------------------------
648 BOOL
PointerList::IsIn( const void* p
) const
653 PBlock
* pBlock
= pFirst
;
657 while ( i
< PBLOCKCOUNT
)
659 if ( ((ULONG
)p
) == ((ULONG
)pBlock
->aData
[i
]) )
664 pBlock
= pBlock
->pNext
;
671 // =======================================================================
673 static void DbgGetDbgFileName( sal_Char
* pStr
, sal_Int32 nMaxLen
)
676 const sal_Char
* pName
= getenv("DBGSV_INIT");
678 pName
= ".dbgsv.init";
679 strncpy( pStr
, pName
, nMaxLen
);
681 const sal_Char
* pName
= getenv("DBGSV_INIT");
683 strncpy( pStr
, pName
, nMaxLen
);
685 GetProfileStringA( "sv", "dbgsv", "dbgsv.ini", pStr
, nMaxLen
);
687 PrfQueryProfileString( HINI_PROFILE
, (PSZ
)"SV", (PSZ
)"DBGSV",
688 "dbgsv.ini", (PSZ
)pStr
, nMaxLen
);
690 strncpy( pStr
, "dbgsv.ini", nMaxLen
);
692 pStr
[ nMaxLen
- 1 ] = 0;
695 // -----------------------------------------------------------------------
697 static void DbgGetLogFileName( sal_Char
* pStr
)
700 const sal_Char
* pName
= getenv("DBGSV_LOG");
703 strcpy( pStr
, pName
);
705 const sal_Char
* pName
= getenv("DBGSV_LOG");
707 strcpy( pStr
, pName
);
709 GetProfileStringA( "sv", "dbgsvlog", "dbgsv.log", pStr
, 200 );
711 PrfQueryProfileString( HINI_PROFILE
, (PSZ
)"SV", (PSZ
)"DBGSVLOG",
712 "dbgsv.log", (PSZ
)pStr
, 200 );
714 strcpy( pStr
, "dbgsv.log" );
718 // -----------------------------------------------------------------------
720 static void DbgDebugBeep()
723 MessageBeep( MB_ICONHAND
);
725 WinAlarm( HWND_DESKTOP
, WA_ERROR
);
729 // -----------------------------------------------------------------------
731 static DebugData
* GetDebugData()
733 if ( !aDebugData
.bInit
)
735 aDebugData
.bInit
= TRUE
;
737 // Default Debug-Namen setzen
738 DbgGetLogFileName( aDebugData
.aDbgData
.aDebugName
);
741 sal_Char aBuf
[ 4096 ];
742 DbgGetDbgFileName( aBuf
, sizeof( aBuf
) );
743 FILETYPE pIniFile
= FileOpen( aBuf
, "r" );
744 if ( pIniFile
!= NULL
)
746 ConfigSection eCurrentSection
= eUnknown
;
748 // no sophisticated algorithm here, assume that the whole file fits into aBuf ...
749 ULONG nReallyRead
= FileRead( aBuf
, 1, sizeof( aBuf
) / sizeof( sal_Char
) - 1, pIniFile
);
750 aBuf
[ nReallyRead
] = 0;
751 const sal_Char
* pLine
= aBuf
;
752 while ( const sal_Char
* pNextLine
= strstr( pLine
, FILE_LINEEND
) )
754 size_t nLineLength
= pNextLine
- pLine
;
756 if ( lcl_isConfigSection( pLine
, nLineLength
) )
757 eCurrentSection
= lcl_getSectionFromName( pLine
+ 1, nLineLength
- 2 );
759 // elements of the [output] section
760 if ( eCurrentSection
== eOutput
)
762 lcl_tryReadConfigString( pLine
, nLineLength
, "log_file", aDebugData
.aDbgData
.aDebugName
, sizeof( aDebugData
.aDbgData
.aDebugName
) );
763 lcl_tryReadConfigBoolean( pLine
, nLineLength
, "overwrite", &aDebugData
.aDbgData
.bOverwrite
);
764 lcl_tryReadConfigString( pLine
, nLineLength
, "include", aDebugData
.aDbgData
.aInclFilter
, sizeof( aDebugData
.aDbgData
.aInclFilter
) );
765 lcl_tryReadConfigString( pLine
, nLineLength
, "exclude", aDebugData
.aDbgData
.aExclFilter
, sizeof( aDebugData
.aDbgData
.aExclFilter
) );
766 lcl_tryReadConfigString( pLine
, nLineLength
, "include_class", aDebugData
.aDbgData
.aInclClassFilter
, sizeof( aDebugData
.aDbgData
.aInclClassFilter
) );
767 lcl_tryReadConfigString( pLine
, nLineLength
, "exclude_class", aDebugData
.aDbgData
.aExclClassFilter
, sizeof( aDebugData
.aDbgData
.aExclClassFilter
) );
768 lcl_tryReadOutputChannel( pLine
, nLineLength
, "trace", &aDebugData
.aDbgData
.nTraceOut
);
769 lcl_tryReadOutputChannel( pLine
, nLineLength
, "warning", &aDebugData
.aDbgData
.nWarningOut
);
770 lcl_tryReadOutputChannel( pLine
, nLineLength
, "error", &aDebugData
.aDbgData
.nErrorOut
);
771 lcl_tryReadConfigBoolean( pLine
, nLineLength
, "oslhook", &aDebugData
.aDbgData
.bHookOSLAssert
);
774 // elements of the [memory] section
775 if ( eCurrentSection
== eMemory
)
777 lcl_tryReadConfigFlag( pLine
, nLineLength
, "initialize", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_MEM_INIT
);
778 lcl_tryReadConfigFlag( pLine
, nLineLength
, "overwrite", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_MEM_OVERWRITE
);
779 lcl_tryReadConfigFlag( pLine
, nLineLength
, "overwrite_free", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_MEM_OVERWRITEFREE
);
780 lcl_tryReadConfigFlag( pLine
, nLineLength
, "pointer", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_MEM_POINTER
);
781 lcl_tryReadConfigFlag( pLine
, nLineLength
, "report", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_MEM_REPORT
);
782 lcl_tryReadConfigFlag( pLine
, nLineLength
, "trace", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_MEM_TRACE
);
783 lcl_tryReadConfigFlag( pLine
, nLineLength
, "new_and_delete", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_MEM_NEWDEL
);
784 lcl_tryReadConfigFlag( pLine
, nLineLength
, "object_test", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_MEM_XTOR
);
785 lcl_tryReadConfigFlag( pLine
, nLineLength
, "sys_alloc", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_MEM_SYSALLOC
);
786 lcl_tryReadConfigFlag( pLine
, nLineLength
, "leak_report", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_MEM_LEAKREPORT
);
788 lcl_tryReadHexByte( pLine
, nLineLength
, "init_byte", &aDebugData
.aDbgData
.bMemInit
);
789 lcl_tryReadHexByte( pLine
, nLineLength
, "bound_byte", &aDebugData
.aDbgData
.bMemBound
);
790 lcl_tryReadHexByte( pLine
, nLineLength
, "free_byte", &aDebugData
.aDbgData
.bMemFree
);
793 // elements of the [gui] section
794 if ( eCurrentSection
== eGUI
)
796 lcl_tryReadConfigString( pLine
, nLineLength
, "debug_window_state", aDebugData
.aDbgData
.aDbgWinState
, sizeof( aDebugData
.aDbgData
.aDbgWinState
) );
799 // elements of the [objects] section
800 if ( eCurrentSection
== eObjects
)
802 lcl_tryReadConfigFlag( pLine
, nLineLength
, "check_this", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_XTOR_THIS
);
803 lcl_tryReadConfigFlag( pLine
, nLineLength
, "check_function", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_XTOR_FUNC
);
804 lcl_tryReadConfigFlag( pLine
, nLineLength
, "check_exit", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_XTOR_EXIT
);
805 lcl_tryReadConfigFlag( pLine
, nLineLength
, "generate_report", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_XTOR_REPORT
);
806 lcl_tryReadConfigFlag( pLine
, nLineLength
, "trace", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_XTOR_TRACE
);
809 // elements of the [test] section
810 if ( eCurrentSection
== eTest
)
812 lcl_tryReadConfigFlag( pLine
, nLineLength
, "profiling", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_PROFILING
);
813 lcl_tryReadConfigFlag( pLine
, nLineLength
, "resources", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_RESOURCE
);
814 lcl_tryReadConfigFlag( pLine
, nLineLength
, "dialog", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_DIALOG
);
815 lcl_tryReadConfigFlag( pLine
, nLineLength
, "bold_app_font", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_BOLDAPPFONT
);
818 pLine
= pNextLine
+ strlen( FILE_LINEEND
);
821 FileClose( pIniFile
);
824 getcwd( aCurPath
, sizeof( aCurPath
) );
826 // Daten initialisieren
827 if ( aDebugData
.aDbgData
.nTestFlags
& DBG_TEST_XTOR
)
828 aDebugData
.pXtorList
= new PointerList
;
829 if ( aDebugData
.aDbgData
.nTestFlags
& DBG_TEST_PROFILING
)
830 aDebugData
.pProfList
= new PointerList
;
836 // -----------------------------------------------------------------------
838 inline DebugData
* ImplGetDebugData()
840 if ( !aDebugData
.bInit
)
841 return GetDebugData();
846 // -----------------------------------------------------------------------
848 static FILETYPE
ImplDbgInitFile()
850 static BOOL bFileInit
= FALSE
;
853 getcwd( aBuf
, sizeof( aBuf
) );
856 DebugData
* pData
= GetDebugData();
863 if ( pData
->aDbgData
.bOverwrite
)
864 pDebugFile
= FileOpen( pData
->aDbgData
.aDebugName
, "w" );
866 pDebugFile
= FileOpen( pData
->aDbgData
.aDebugName
, "a" );
870 time_t nTime
= time( 0 );
874 pTime
= localtime_r( &nTime
, &aTime
);
876 pTime
= localtime( &nTime
);
880 FilePrintF( pDebugFile
, "******************************************************************************%s", FILE_LINEEND
);
881 FilePrintF( pDebugFile
, "%s%s", pData
->aDbgData
.aDebugName
, FILE_LINEEND
);
883 FilePrintF( pDebugFile
, "%s%s", asctime( pTime
), FILE_LINEEND
);
887 pDebugFile
= FileOpen( pData
->aDbgData
.aDebugName
, "a" );
894 // -----------------------------------------------------------------------
896 static void ImplDbgPrintFile( const sal_Char
* pLine
)
898 FILETYPE pDebugFile
= ImplDbgInitFile();
902 FilePrintF( pDebugFile
, "%s%s", pLine
, FILE_LINEEND
);
903 FileClose( pDebugFile
);
907 // -----------------------------------------------------------------------
909 static int ImplStrSearch( const sal_Char
* pSearchStr
, int nSearchLen
,
910 const sal_Char
* pStr
, int nLen
)
913 while ( nPos
+nSearchLen
<= nLen
)
915 if ( strncmp( pStr
+nPos
, pSearchStr
, nSearchLen
) == 0 )
923 // -----------------------------------------------------------------------
925 static int ImplDbgFilter( const sal_Char
* pFilter
, const sal_Char
* pMsg
,
928 int nStrLen
= strlen( pFilter
);
932 int nMsgLen
= strlen( pMsg
);
933 const sal_Char
* pTok
= pFilter
;
937 if ( pTok
[nTok
] == ';' )
939 if ( nTok
&& ImplStrSearch( pTok
, nTok
, pMsg
, nMsgLen
) )
949 if ( nTok
&& ImplStrSearch( pTok
, nTok
, pMsg
, nMsgLen
) )
955 // -----------------------------------------------------------------------
958 void SAL_CALL
dbg_printOslDebugMessage( const sal_Char
* pszFileName
, sal_Int32 nLine
, const sal_Char
* pszMessage
)
960 DbgOut( pszMessage
? pszMessage
: "assertion failed!", DBG_OUT_ERROR
, pszFileName
, (USHORT
)nLine
);
963 // -----------------------------------------------------------------------
965 static void DebugInit()
967 bDbgImplInMain
= TRUE
;
970 DebugData
* pData
= GetDebugData();
971 if( pData
->aDbgData
.bHookOSLAssert
&& ! pData
->bOslIsHooked
)
973 pData
->pOldDebugMessageFunc
= osl_setDetailedDebugMessageFunc( &dbg_printOslDebugMessage
);
974 pData
->bOslIsHooked
= true;
978 // -----------------------------------------------------------------------
980 static void DebugDeInit()
982 DebugData
* pData
= GetDebugData();
987 if( pData
->bOslIsHooked
)
989 osl_setDetailedDebugMessageFunc( pData
->pOldDebugMessageFunc
);
990 pData
->bOslIsHooked
= FALSE
;
993 // Statistik-Ausgaben immer in File
994 nOldOut
= pData
->aDbgData
.nTraceOut
;
995 pData
->aDbgData
.nTraceOut
= DBG_OUT_FILE
;
997 // Xtor-Liste ausgeben
998 if ( pData
->pXtorList
&& pData
->pXtorList
->Count() &&
999 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_REPORT
) )
1001 DbgOutf( "------------------------------------------------------------------------------" );
1002 DbgOutf( "Object Report" );
1003 DbgOutf( "------------------------------------------------------------------------------" );
1004 DbgOutf( "%-27s : %-9s : %-9s : %-7s : %-3s : %-6s :",
1005 "XTor-List", "Ctor", "Dtor", "MaxInst", "St.", "Diff." );
1006 DbgOutf( "----------------------------:-----------:-----------:---------:----:---------:" );
1007 for( i
= 0, nCount
= pData
->pXtorList
->Count(); i
< nCount
; i
++ )
1009 XtorType
* pXtorData
= (XtorType
*)pData
->pXtorList
->Get( i
);
1010 if ( pXtorData
->bTest
)
1012 // Static-Objekte dazurechnen
1013 pXtorData
->nDtorCalls
+= pXtorData
->nStatics
;
1014 if ( pXtorData
->nStatics
&& (pXtorData
->nDtorCalls
> pXtorData
->nCtorCalls
) )
1015 pXtorData
->nDtorCalls
= pXtorData
->nCtorCalls
;
1016 DbgOutf( "%-27s : %9lu : %9lu : %7lu : %3lu : %4lu %-1s :",
1017 pXtorData
->aName
, pXtorData
->nCtorCalls
, pXtorData
->nDtorCalls
,
1018 pXtorData
->nMaxCount
, pXtorData
->nStatics
,
1019 pXtorData
->nCtorCalls
- pXtorData
->nDtorCalls
,
1020 (pXtorData
->nCtorCalls
- pXtorData
->nDtorCalls
) ? "!" : " " );
1023 DbgOutf( "==============================================================================" );
1027 if ( pData
->pXtorList
)
1029 for( i
= 0, nCount
= pData
->pXtorList
->Count(); i
< nCount
; i
++ )
1031 XtorType
* pXtorData
= (XtorType
*)pData
->pXtorList
->Get( i
);
1034 delete pData
->pXtorList
;
1035 pData
->pXtorList
= NULL
;
1038 // Alles auf FALSE setzen, damit globale Variablen nicht das
1039 // System zum Abstuerzen bringt. Dabei muessen aber die
1040 // Memory-Flags erhalten bleiben, da sonst new/delete in globalen
1041 // Variablen abstuerzen, da die Pointeranpassung dann nicht mehr richtig
1043 pData
->aDbgData
.nTraceOut
= nOldOut
;
1044 pData
->aDbgData
.nTestFlags
&= (DBG_TEST_MEM
| DBG_TEST_PROFILING
);
1045 pData
->aDbgPrintUserChannels
.clear();
1046 pData
->pDbgPrintTestTool
= NULL
;
1047 pData
->pDbgPrintShell
= NULL
;
1048 pData
->pDbgPrintWindow
= NULL
;
1049 pData
->pDbgPrintShell
= NULL
;
1050 pData
->pOldDebugMessageFunc
= NULL
;
1051 ImplDbgDeInitLock();
1054 // -----------------------------------------------------------------------
1056 static void DebugGlobalDeInit()
1058 DebugData
* pData
= GetDebugData();
1063 // Statistik-Ausgaben immer in File
1064 nOldOut
= pData
->aDbgData
.nTraceOut
;
1065 pData
->aDbgData
.nTraceOut
= DBG_OUT_FILE
;
1067 // Profileliste ausgeben
1068 if ( pData
->pProfList
&& pData
->pProfList
->Count() )
1070 DbgOutf( "------------------------------------------------------------------------------" );
1071 DbgOutf( "Profiling Report" );
1072 DbgOutf( "------------------------------------------------------------------------------" );
1073 DbgOutf( "%-25s : %-9s : %-6s : %-6s : %-6s : %-9s :",
1074 "Prof-List (ms)", "Time", "Min", "Max", "Ave", "Count" );
1075 DbgOutf( "--------------------------:-----------:--------:--------:--------:-----------:" );
1076 for( i
= 0, nCount
= pData
->pProfList
->Count(); i
< nCount
; i
++ )
1078 ProfType
* pProfData
= (ProfType
*)pData
->pProfList
->Get( i
);
1079 ULONG nAve
= pProfData
->nTime
/ pProfData
->nCount
;
1080 DbgOutf( "%-25s : %9lu : %6lu : %6lu : %6lu : %9lu :",
1081 pProfData
->aName
, pProfData
->nTime
,
1082 pProfData
->nMinTime
, pProfData
->nMaxTime
, nAve
,
1083 pProfData
->nCount
);
1085 DbgOutf( "==============================================================================" );
1089 if ( pData
->pProfList
)
1091 for( i
= 0, nCount
= pData
->pProfList
->Count(); i
< nCount
; i
++ )
1093 ProfType
* pProfData
= (ProfType
*)pData
->pProfList
->Get( i
);
1096 delete pData
->pProfList
;
1097 pData
->pProfList
= NULL
;
1101 DbgImpCheckMemoryDeInit();
1104 // Profiling-Flags ausschalten
1105 pData
->aDbgData
.nTraceOut
= nOldOut
;
1106 pData
->aDbgData
.nTestFlags
&= ~DBG_TEST_PROFILING
;
1109 // -----------------------------------------------------------------------
1111 void ImpDbgOutfBuf( sal_Char
* pBuf
, const sal_Char
* pFStr
, ... )
1115 va_start( pList
, pFStr
);
1116 sal_Char aBuf
[DBG_BUF_MAXLEN
];
1117 vsprintf( aBuf
, pFStr
, pList
);
1120 strcat( pBuf
, aBuf
);
1121 strcat( pBuf
, "\n" );
1124 // -----------------------------------------------------------------------
1126 static void DebugXTorInfo( sal_Char
* pBuf
)
1128 DebugData
* pData
= GetDebugData();
1132 // Xtor-Liste ausgeben
1133 if ( pData
->pXtorList
&& pData
->pXtorList
->Count() &&
1134 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_REPORT
) )
1136 ImpDbgOutfBuf( pBuf
, "------------------------------------------------------------------------------" );
1137 ImpDbgOutfBuf( pBuf
, "Object Report" );
1138 ImpDbgOutfBuf( pBuf
, "------------------------------------------------------------------------------" );
1139 ImpDbgOutfBuf( pBuf
, "%-27s : %-9s : %-9s : %-7s : %-3s : %-6s :",
1140 "XTor-List", "Ctor", "Dtor", "MaxInst", "St.", "Diff." );
1141 ImpDbgOutfBuf( pBuf
, "----------------------------:-----------:-----------:---------:----:---------:" );
1142 for( i
= 0, nCount
= pData
->pXtorList
->Count(); i
< nCount
; i
++ )
1144 XtorType
* pXtorData
= (XtorType
*)pData
->pXtorList
->Get( i
);
1145 if ( pXtorData
->bTest
)
1147 ImpDbgOutfBuf( pBuf
, "%-27s : %9lu : %9lu : %7lu : %3lu : %6lu :",
1148 pXtorData
->aName
, pXtorData
->nCtorCalls
, pXtorData
->nDtorCalls
,
1149 pXtorData
->nMaxCount
, pXtorData
->nStatics
,
1150 pXtorData
->nCtorCalls
- pXtorData
->nDtorCalls
);
1153 ImpDbgOutfBuf( pBuf
, "==============================================================================" );
1154 ImpDbgOutfBuf( pBuf
, "" );
1158 // -----------------------------------------------------------------------
1159 BOOL
ImplDbgFilterMessage( const sal_Char
* pMsg
)
1161 DebugData
* pData
= GetDebugData();
1162 if ( !ImplDbgFilter( pData
->aDbgData
.aInclFilter
, pMsg
, TRUE
) )
1164 if ( ImplDbgFilter( pData
->aDbgData
.aExclFilter
, pMsg
, FALSE
) )
1169 // -----------------------------------------------------------------------
1171 void* DbgFunc( USHORT nAction
, void* pParam
)
1173 DebugData
* pDebugData
= ImplGetDebugData();
1175 if ( nAction
== DBG_FUNC_GETDATA
)
1176 return (void*)&(pDebugData
->aDbgData
);
1177 else if ( nAction
== DBG_FUNC_GETPRINTMSGBOX
)
1178 return (void*)(long)(pDebugData
->pDbgPrintMsgBox
);
1179 else if ( nAction
== DBG_FUNC_FILTERMESSAGE
)
1180 if ( ImplDbgFilterMessage( (const sal_Char
*) pParam
) )
1183 return (void*) 0; // aka NULL
1189 case DBG_FUNC_DEBUGSTART
:
1193 case DBG_FUNC_DEBUGEND
:
1197 case DBG_FUNC_GLOBALDEBUGEND
:
1198 DebugGlobalDeInit();
1201 case DBG_FUNC_SETPRINTMSGBOX
:
1202 pDebugData
->pDbgPrintMsgBox
= (DbgPrintLine
)(long)pParam
;
1205 case DBG_FUNC_SETPRINTWINDOW
:
1206 pDebugData
->pDbgPrintWindow
= (DbgPrintLine
)(long)pParam
;
1209 case DBG_FUNC_SETPRINTSHELL
:
1210 pDebugData
->pDbgPrintShell
= (DbgPrintLine
)(long)pParam
;
1213 case DBG_FUNC_SETPRINTTESTTOOL
:
1214 pDebugData
->pDbgPrintTestTool
= (DbgPrintLine
)(long)pParam
;
1217 case DBG_FUNC_SAVEDATA
:
1219 const DbgData
* pData
= static_cast< const DbgData
* >( pParam
);
1221 sal_Char aBuf
[ 4096 ];
1222 DbgGetDbgFileName( aBuf
, sizeof( aBuf
) );
1223 FILETYPE pIniFile
= FileOpen( aBuf
, "w" );
1224 if ( pIniFile
== NULL
)
1227 lcl_startSection( pIniFile
, eOutput
);
1228 lcl_writeConfigString( pIniFile
, "log_file", pData
->aDebugName
);
1229 lcl_writeConfigBoolean( pIniFile
, "overwrite", pData
->bOverwrite
);
1230 lcl_writeConfigString( pIniFile
, "include", pData
->aInclFilter
);
1231 lcl_writeConfigString( pIniFile
, "exclude", pData
->aExclFilter
);
1232 lcl_writeConfigString( pIniFile
, "include_class", pData
->aInclClassFilter
);
1233 lcl_writeConfigString( pIniFile
, "exclude_class", pData
->aExclClassFilter
);
1234 lcl_writeConfigOutChannel( pIniFile
, "trace", pData
->nTraceOut
);
1235 lcl_writeConfigOutChannel( pIniFile
, "warning", pData
->nWarningOut
);
1236 lcl_writeConfigOutChannel( pIniFile
, "error", pData
->nErrorOut
);
1237 lcl_writeConfigBoolean( pIniFile
, "oslhook", pData
->bHookOSLAssert
);
1239 lcl_lineFeed( pIniFile
);
1240 lcl_startSection( pIniFile
, eMemory
);
1241 lcl_writeConfigFlag( pIniFile
, "initialize", pData
->nTestFlags
, DBG_TEST_MEM_INIT
);
1242 lcl_writeConfigFlag( pIniFile
, "overwrite", pData
->nTestFlags
, DBG_TEST_MEM_OVERWRITE
);
1243 lcl_writeConfigFlag( pIniFile
, "overwrite_free", pData
->nTestFlags
, DBG_TEST_MEM_OVERWRITEFREE
);
1244 lcl_writeConfigFlag( pIniFile
, "pointer", pData
->nTestFlags
, DBG_TEST_MEM_POINTER
);
1245 lcl_writeConfigFlag( pIniFile
, "report", pData
->nTestFlags
, DBG_TEST_MEM_REPORT
);
1246 lcl_writeConfigFlag( pIniFile
, "trace", pData
->nTestFlags
, DBG_TEST_MEM_TRACE
);
1247 lcl_writeConfigFlag( pIniFile
, "new_and_delete", pData
->nTestFlags
, DBG_TEST_MEM_NEWDEL
);
1248 lcl_writeConfigFlag( pIniFile
, "object_test", pData
->nTestFlags
, DBG_TEST_MEM_XTOR
);
1249 lcl_writeConfigFlag( pIniFile
, "sys_alloc", pData
->nTestFlags
, DBG_TEST_MEM_SYSALLOC
);
1250 lcl_writeConfigFlag( pIniFile
, "leak_report", pData
->nTestFlags
, DBG_TEST_MEM_LEAKREPORT
);
1252 lcl_lineFeed( pIniFile
);
1253 lcl_writeHexByte( pIniFile
, "init_byte", pData
->bMemInit
);
1254 lcl_writeHexByte( pIniFile
, "bound_byte", pData
->bMemBound
);
1255 lcl_writeHexByte( pIniFile
, "free_byte", pData
->bMemFree
);
1257 lcl_lineFeed( pIniFile
);
1258 lcl_startSection( pIniFile
, eGUI
);
1259 lcl_writeConfigString( pIniFile
, "debug_window_state", pData
->aDbgWinState
);
1261 lcl_lineFeed( pIniFile
);
1262 lcl_startSection( pIniFile
, eObjects
);
1263 lcl_writeConfigFlag( pIniFile
, "check_this", pData
->nTestFlags
, DBG_TEST_XTOR_THIS
);
1264 lcl_writeConfigFlag( pIniFile
, "check_function", pData
->nTestFlags
, DBG_TEST_XTOR_FUNC
);
1265 lcl_writeConfigFlag( pIniFile
, "check_exit", pData
->nTestFlags
, DBG_TEST_XTOR_EXIT
);
1266 lcl_writeConfigFlag( pIniFile
, "generate_report", pData
->nTestFlags
, DBG_TEST_XTOR_REPORT
);
1267 lcl_writeConfigFlag( pIniFile
, "trace", pData
->nTestFlags
, DBG_TEST_XTOR_TRACE
);
1269 lcl_lineFeed( pIniFile
);
1270 lcl_startSection( pIniFile
, eTest
);
1271 lcl_writeConfigFlag( pIniFile
, "profiling", pData
->nTestFlags
, DBG_TEST_PROFILING
);
1272 lcl_writeConfigFlag( pIniFile
, "resources", pData
->nTestFlags
, DBG_TEST_RESOURCE
);
1273 lcl_writeConfigFlag( pIniFile
, "dialog", pData
->nTestFlags
, DBG_TEST_DIALOG
);
1274 lcl_writeConfigFlag( pIniFile
, "bold_app_font", pData
->nTestFlags
, DBG_TEST_BOLDAPPFONT
);
1276 FileClose( pIniFile
);
1280 case DBG_FUNC_MEMTEST
:
1282 DbgImpCheckMemory( pParam
);
1286 case DBG_FUNC_XTORINFO
:
1287 DebugXTorInfo( (sal_Char
*)pParam
);
1290 case DBG_FUNC_MEMINFO
:
1292 DbgImpMemoryInfo( (sal_Char
*)pParam
);
1296 case DBG_FUNC_COREDUMP
:
1300 case DBG_FUNC_ALLERROROUT
:
1301 return (void*)(ULONG
)TRUE
;
1303 case DBG_FUNC_SETTESTSOLARMUTEX
:
1304 pDebugData
->pDbgTestSolarMutex
= (DbgTestSolarMutexProc
)(long)pParam
;
1307 case DBG_FUNC_TESTSOLARMUTEX
:
1308 if ( pDebugData
->pDbgTestSolarMutex
)
1309 pDebugData
->pDbgTestSolarMutex();
1312 case DBG_FUNC_PRINTFILE
:
1313 ImplDbgPrintFile( (const sal_Char
*)pParam
);
1315 case DBG_FUNC_UPDATEOSLHOOK
:
1317 const DbgData
* pData
= static_cast< const DbgData
* >( pParam
);
1318 pDebugData
->aDbgData
.bHookOSLAssert
= pData
->bHookOSLAssert
;
1319 if( pDebugData
->bOslIsHooked
&& ! pData
->bHookOSLAssert
)
1321 osl_setDetailedDebugMessageFunc( pDebugData
->pOldDebugMessageFunc
);
1322 pDebugData
->bOslIsHooked
= FALSE
;
1324 else if( ! pDebugData
->bOslIsHooked
&& pData
->bHookOSLAssert
)
1326 pDebugData
->pOldDebugMessageFunc
= osl_setDetailedDebugMessageFunc( &dbg_printOslDebugMessage
);
1327 pDebugData
->bOslIsHooked
= TRUE
;
1337 // -----------------------------------------------------------------------
1339 DbgChannelId
DbgRegisterUserChannel( DbgPrintLine pProc
)
1341 DebugData
* pData
= ImplGetDebugData();
1342 pData
->aDbgPrintUserChannels
.push_back( pProc
);
1343 return (DbgChannelId
)( pData
->aDbgPrintUserChannels
.size() - 1 + DBG_OUT_USER_CHANNEL_0
);
1346 // -----------------------------------------------------------------------
1348 void DbgProf( USHORT nAction
, DbgDataType
* pDbgData
)
1350 // Ueberhaupt Profiling-Test an
1351 DebugData
* pData
= ImplGetDebugData();
1353 if ( !(pData
->aDbgData
.nTestFlags
& DBG_TEST_PROFILING
) )
1356 sal_Char aBuf
[DBG_BUF_MAXLEN
];
1357 ProfType
* pProfData
= (ProfType
*)pDbgData
->pData
;
1359 if ( (nAction
!= DBG_PROF_START
) && !pProfData
)
1361 strcpy( aBuf
, DbgError_ProfEnd1
);
1362 strcat( aBuf
, pDbgData
->pName
);
1369 case DBG_PROF_START
:
1370 if ( !pDbgData
->pData
)
1372 pDbgData
->pData
= (void*)new ProfType
;
1373 pProfData
= (ProfType
*)pDbgData
->pData
;
1374 strncpy( pProfData
->aName
, pDbgData
->pName
, DBG_MAXNAME
);
1375 pProfData
->aName
[DBG_MAXNAME
] = '\0';
1376 pProfData
->nCount
= 0;
1377 pProfData
->nTime
= 0;
1378 pProfData
->nMinTime
= 0xFFFFFFFF;
1379 pProfData
->nMaxTime
= 0;
1380 pProfData
->nStart
= 0xFFFFFFFF;
1381 pProfData
->nContinueTime
= 0;
1382 pProfData
->nContinueStart
= 0xFFFFFFFF;
1383 pData
->pProfList
->Add( (void*)pProfData
);
1386 if ( pProfData
->nStart
== 0xFFFFFFFF )
1388 pProfData
->nStart
= ImplGetPerfTime();
1389 pProfData
->nCount
++;
1394 nTime
= ImplGetPerfTime();
1396 if ( pProfData
->nStart
== 0xFFFFFFFF )
1398 DbgError( DbgError_ProfEnd1
);
1402 if ( pProfData
->nContinueStart
!= 0xFFFFFFFF )
1404 pProfData
->nContinueTime
+= ImplGetPerfTime() - pProfData
->nContinueStart
;
1405 pProfData
->nContinueStart
= 0xFFFFFFFF;
1408 nTime
-= pProfData
->nStart
;
1409 nTime
-= pProfData
->nContinueTime
;
1411 if ( nTime
< pProfData
->nMinTime
)
1412 pProfData
->nMinTime
= nTime
;
1414 if ( nTime
> pProfData
->nMaxTime
)
1415 pProfData
->nMaxTime
= nTime
;
1417 pProfData
->nTime
+= nTime
;
1419 pProfData
->nStart
= 0xFFFFFFFF;
1420 pProfData
->nContinueTime
= 0;
1421 pProfData
->nContinueStart
= 0xFFFFFFFF;
1424 case DBG_PROF_CONTINUE
:
1425 if ( pProfData
->nContinueStart
!= 0xFFFFFFFF )
1427 pProfData
->nContinueTime
+= ImplGetPerfTime() - pProfData
->nContinueStart
;
1428 pProfData
->nContinueStart
= 0xFFFFFFFF;
1432 case DBG_PROF_PAUSE
:
1433 if ( pProfData
->nContinueStart
== 0xFFFFFFFF )
1434 pProfData
->nContinueStart
= ImplGetPerfTime();
1439 // -----------------------------------------------------------------------
1441 void DbgXtor( DbgDataType
* pDbgData
, USHORT nAction
, const void* pThis
,
1444 DebugData
* pData
= ImplGetDebugData();
1446 // Verbindung zu Debug-Memory-Manager testen
1448 if ( pData
->aDbgData
.nTestFlags
& DBG_TEST_MEM_XTOR
)
1449 DbgImpCheckMemory();
1453 if ( !(pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR
) )
1456 XtorType
* pXtorData
= (XtorType
*)pDbgData
->pData
;
1459 pDbgData
->pData
= (void*)new XtorType
;
1460 pXtorData
= (XtorType
*)pDbgData
->pData
;
1461 strncpy( pXtorData
->aName
, pDbgData
->pName
, DBG_MAXNAME
);
1462 pXtorData
->aName
[DBG_MAXNAME
] = '\0';
1463 pXtorData
->nCtorCalls
= 0;
1464 pXtorData
->nDtorCalls
= 0;
1465 pXtorData
->nMaxCount
= 0;
1466 pXtorData
->nStatics
= 0;
1467 pXtorData
->bTest
= TRUE
;
1468 pData
->pXtorList
->Add( (void*)pXtorData
);
1470 if ( !ImplDbgFilter( pData
->aDbgData
.aInclClassFilter
, pXtorData
->aName
, TRUE
) )
1471 pXtorData
->bTest
= FALSE
;
1472 if ( ImplDbgFilter( pData
->aDbgData
.aExclClassFilter
, pXtorData
->aName
, FALSE
) )
1473 pXtorData
->bTest
= FALSE
;
1475 if ( !pXtorData
->bTest
)
1478 sal_Char aBuf
[DBG_BUF_MAXLEN
];
1479 USHORT nAct
= nAction
& ~DBG_XTOR_DTOROBJ
;
1482 if ( (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_TRACE
) &&
1483 !(nAction
& DBG_XTOR_DTOROBJ
) )
1485 if ( nAct
!= DBG_XTOR_CHKOBJ
)
1487 if ( nAct
== DBG_XTOR_CTOR
)
1488 strcpy( aBuf
, DbgTrace_EnterCtor
);
1489 else if ( nAct
== DBG_XTOR_DTOR
)
1490 strcpy( aBuf
, DbgTrace_EnterDtor
);
1492 strcpy( aBuf
, DbgTrace_EnterMeth
);
1493 strcat( aBuf
, pDbgData
->pName
);
1498 // Sind noch Xtor-Tests als Trace an
1499 if ( pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_EXTRA
)
1501 // DBG_CTOR-Aufruf vor allen anderen DBG_XTOR-Aufrufen
1502 if ( ((nAction
& ~DBG_XTOR_DTOROBJ
) != DBG_XTOR_CTOR
) && !pDbgData
->pData
)
1504 strcpy( aBuf
, DbgError_Xtor1
);
1505 strcat( aBuf
, pDbgData
->pName
);
1510 // Testen, ob This-Pointer gueltig
1511 if ( pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_THIS
)
1513 if ( (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_EXIT
) ||
1514 !(nAction
& DBG_XTOR_DTOROBJ
) )
1516 // This-Pointer == NULL
1519 strcpy( aBuf
, DbgError_CtorDtor1
);
1520 strcat( aBuf
, pDbgData
->pName
);
1525 if ( (nAction
& ~DBG_XTOR_DTOROBJ
) != DBG_XTOR_CTOR
)
1527 if ( !pXtorData
->aThisList
.IsIn( pThis
) )
1529 sprintf( aBuf
, DbgError_CtorDtor2
, pThis
);
1530 strcat( aBuf
, pDbgData
->pName
);
1537 // Function-Test durchfuehren und Verwaltungsdaten updaten
1538 const sal_Char
* pMsg
= NULL
;
1539 switch ( nAction
& ~DBG_XTOR_DTOROBJ
)
1542 if ( nAction
& DBG_XTOR_DTOROBJ
)
1545 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_EXIT
) &&
1546 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_FUNC
) )
1547 pMsg
= fDbgUsr( pThis
);
1551 pXtorData
->nCtorCalls
++;
1552 if ( !bDbgImplInMain
)
1553 pXtorData
->nStatics
++;
1554 if ( (pXtorData
->nCtorCalls
-pXtorData
->nDtorCalls
) > pXtorData
->nMaxCount
)
1555 pXtorData
->nMaxCount
= pXtorData
->nCtorCalls
- pXtorData
->nDtorCalls
;
1557 if ( pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_THIS
)
1558 pXtorData
->aThisList
.Add( pThis
);
1563 if ( nAction
& DBG_XTOR_DTOROBJ
)
1565 pXtorData
->nDtorCalls
++;
1566 if ( pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_THIS
)
1567 pXtorData
->aThisList
.Remove( pThis
);
1572 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_FUNC
) )
1573 pMsg
= fDbgUsr( pThis
);
1577 case DBG_XTOR_CHKTHIS
:
1578 case DBG_XTOR_CHKOBJ
:
1579 if ( nAction
& DBG_XTOR_DTOROBJ
)
1582 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_EXIT
) &&
1583 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_FUNC
) )
1584 pMsg
= fDbgUsr( pThis
);
1589 (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_FUNC
) )
1590 pMsg
= fDbgUsr( pThis
);
1595 // Gegebenenfalls Fehlermeldung ausgeben
1598 sprintf( aBuf
, DbgError_CtorDtor3
, pThis
);
1599 strcat( aBuf
, pDbgData
->pName
);
1600 strcat( aBuf
, ": \n" );
1601 strcat( aBuf
, pMsg
);
1607 if ( (pData
->aDbgData
.nTestFlags
& DBG_TEST_XTOR_TRACE
) &&
1608 (nAction
& DBG_XTOR_DTOROBJ
) )
1610 if ( nAct
!= DBG_XTOR_CHKOBJ
)
1612 if ( nAct
== DBG_XTOR_CTOR
)
1613 strcpy( aBuf
, DbgTrace_LeaveCtor
);
1614 else if ( nAct
== DBG_XTOR_DTOR
)
1615 strcpy( aBuf
, DbgTrace_LeaveDtor
);
1617 strcpy( aBuf
, DbgTrace_LeaveMeth
);
1618 strcat( aBuf
, pDbgData
->pName
);
1624 // -----------------------------------------------------------------------
1626 void DbgOut( const sal_Char
* pMsg
, USHORT nDbgOut
, const sal_Char
* pFile
, USHORT nLine
)
1628 static BOOL bIn
= FALSE
;
1633 DebugData
* pData
= GetDebugData();
1634 sal_Char
const * pStr
;
1638 if ( nDbgOut
== DBG_OUT_ERROR
)
1640 nOut
= pData
->aDbgData
.nErrorOut
;
1642 if ( pData
->aDbgData
.nErrorOut
== DBG_OUT_FILE
)
1645 else if ( nDbgOut
== DBG_OUT_WARNING
)
1647 nOut
= pData
->aDbgData
.nWarningOut
;
1652 nOut
= pData
->aDbgData
.nTraceOut
;
1656 if ( nOut
== DBG_OUT_NULL
)
1662 if ( ImplDbgFilterMessage( pMsg
) )
1670 sal_Char aBufOut
[DBG_BUF_MAXLEN
];
1673 strcpy( aBufOut
, pStr
);
1674 nBufLen
= strlen( pStr
);
1679 int nMsgLen
= strlen( pMsg
);
1680 if ( nBufLen
+nMsgLen
> DBG_BUF_MAXLEN
)
1682 int nCopyLen
= DBG_BUF_MAXLEN
-nBufLen
-3;
1683 strncpy( &(aBufOut
[nBufLen
]), pMsg
, nCopyLen
);
1684 strcpy( &(aBufOut
[nBufLen
+nCopyLen
]), "..." );
1687 strcpy( &(aBufOut
[nBufLen
]), pMsg
);
1689 if ( pFile
&& nLine
&& (nBufLen
+nMsgLen
< DBG_BUF_MAXLEN
) )
1691 if ( nOut
== DBG_OUT_MSGBOX
)
1692 strcat( aBufOut
, "\n" );
1694 strcat( aBufOut
, " " );
1695 strcat( aBufOut
, "From File " );
1696 strcat( aBufOut
, pFile
);
1697 strcat( aBufOut
, " at Line " );
1699 // Line in String umwandeln und dranhaengen
1701 sal_Char
* pLine
= &aLine
[7];
1703 memset( aLine
, 0, sizeof( aLine
) );
1708 *(pLine
) = (sal_Char
)i
+ 48;
1712 strcat( aBufOut
, pLine
);
1715 if ( ( nOut
>= DBG_OUT_USER_CHANNEL_0
) && ( nOut
- DBG_OUT_USER_CHANNEL_0
< pData
->aDbgPrintUserChannels
.size() ) )
1717 DbgPrintLine pPrinter
= pData
->aDbgPrintUserChannels
[ nOut
- DBG_OUT_USER_CHANNEL_0
];
1719 pPrinter( aBufOut
);
1721 nOut
= DBG_OUT_DEBUGGER
;
1724 if ( nOut
== DBG_OUT_COREDUMP
)
1726 if ( !ImplCoreDump() )
1727 nOut
= DBG_OUT_DEBUGGER
;
1730 if ( nOut
== DBG_OUT_DEBUGGER
)
1732 if ( !ImplActivateDebugger( aBufOut
) )
1733 nOut
= DBG_OUT_TESTTOOL
;
1736 if ( nOut
== DBG_OUT_TESTTOOL
)
1738 if ( pData
->pDbgPrintTestTool
)
1739 pData
->pDbgPrintTestTool( aBufOut
);
1741 nOut
= DBG_OUT_MSGBOX
;
1744 if ( nOut
== DBG_OUT_MSGBOX
)
1746 if ( pData
->pDbgPrintMsgBox
)
1747 pData
->pDbgPrintMsgBox( aBufOut
);
1749 nOut
= DBG_OUT_SHELL
;
1752 if ( nOut
== DBG_OUT_SHELL
)
1754 if ( pData
->pDbgPrintShell
)
1755 pData
->pDbgPrintShell( aBufOut
);
1757 nOut
= DBG_OUT_WINDOW
;
1760 if ( nOut
== DBG_OUT_WINDOW
)
1762 if ( pData
->pDbgPrintWindow
)
1763 pData
->pDbgPrintWindow( aBufOut
);
1765 nOut
= DBG_OUT_FILE
;
1768 if ( nOut
== DBG_OUT_FILE
)
1769 ImplDbgPrintFile( aBufOut
);
1776 // -----------------------------------------------------------------------
1778 void DbgOutTypef( USHORT nDbgOut
, const sal_Char
* pFStr
, ... )
1782 va_start( pList
, pFStr
);
1783 sal_Char aBuf
[DBG_BUF_MAXLEN
];
1784 vsprintf( aBuf
, pFStr
, pList
);
1787 DbgOut( aBuf
, nDbgOut
);
1790 // -----------------------------------------------------------------------
1792 void DbgOutf( const sal_Char
* pFStr
, ... )
1796 va_start( pList
, pFStr
);
1797 sal_Char aBuf
[DBG_BUF_MAXLEN
];
1798 vsprintf( aBuf
, pFStr
, pList
);
1804 // =======================================================================
1808 void* DbgFunc( USHORT
, void* ) { return NULL
; }
1810 void DbgProf( USHORT
, DbgDataType
* ) {}
1811 void DbgXtor( DbgDataType
*, USHORT
, const void*, DbgUsr
) {}
1813 void DbgOut( const sal_Char
*, USHORT
, const sal_Char
*, USHORT
) {}
1814 void DbgOutTypef( USHORT
, const sal_Char
*, ... ) {}
1815 void DbgOutf( const sal_Char
*, ... ) {}