Update ooo320-m1
[ooovba.git] / tools / source / debug / debug.cxx
blob01faeadafa27ebdb9bf4770789037c5deb9b1012
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: debug.cxx,v $
10 * $Revision: 1.17 $
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)
37 #include <unistd.h>
38 #else
39 #include <direct.h>
40 #endif
42 #include <time.h>
43 #include <cstdarg> // combinations
44 #include <stdlib.h>
45 #include <string.h>
46 #include <stdio.h>
48 #ifdef OS2
49 #define INCL_DOSSEMAPHORES
50 #define INCL_DOSMISC
51 #define INCL_WINDIALOGS
52 #define INCL_WINSHELLDATA
53 #include <svpm.h>
54 #endif
56 #if defined ( WNT )
57 #ifdef _MSC_VER
58 #pragma warning (push,1)
59 #endif
60 #include <tools/svwin.h>
61 #ifdef _MSC_VER
62 #pragma warning (pop)
63 #endif
64 #endif
66 #include <tools/debug.hxx>
67 #include <rtl/string.h>
69 #include <vector>
71 #include <osl/diagnose.h>
73 // =======================================================================
75 #ifdef DBG_UTIL
77 // --- DbgErrors ---
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
97 struct PBlock
99 void* aData[PBLOCKCOUNT];
100 USHORT nCount;
101 PBlock* pPrev;
102 PBlock* pNext;
105 class PointerList
107 private:
108 PBlock* pFirst;
109 PBlock* pLast;
110 ULONG nCount;
112 public:
113 PointerList() { pFirst = NULL; pLast = NULL; nCount = 0; }
114 ~PointerList();
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
128 struct ProfType
130 ULONG nCount;
131 ULONG nTime;
132 ULONG nMinTime;
133 ULONG nMaxTime;
134 ULONG nStart;
135 ULONG nContinueTime;
136 ULONG nContinueStart;
137 sal_Char aName[DBG_MAXNAME+1];
140 struct XtorType
142 ULONG nCtorCalls;
143 ULONG nDtorCalls;
144 ULONG nMaxCount;
145 ULONG nStatics;
146 sal_Char aName[DBG_MAXNAME+1];
147 BOOL bTest;
148 PointerList aThisList;
151 struct DebugData
153 DbgData aDbgData;
154 USHORT bInit;
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;
166 bool bOslIsHooked;
168 DebugData()
169 :bInit( FALSE )
170 ,pDbgPrintMsgBox( FALSE )
171 ,pDbgPrintWindow( NULL )
172 ,pDbgPrintShell( NULL )
173 ,pDbgPrintTestTool( NULL )
174 ,pProfList( NULL )
175 ,pXtorList( 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;
184 #ifdef UNX
185 aDbgData.nErrorOut = DBG_OUT_SHELL;
186 #else
187 aDbgData.nErrorOut = DBG_OUT_MSGBOX;
188 #endif
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 // =======================================================================
217 #if defined( WNT )
218 static CRITICAL_SECTION aImplCritDbgSection;
219 #elif defined( OS2 )
220 static HMTX hImplCritDbgSection = 0;
221 #endif
222 static BOOL bImplCritDbgSectionInit = FALSE;
224 // -----------------------------------------------------------------------
226 void ImplDbgInitLock()
228 #if defined( WNT )
229 InitializeCriticalSection( &aImplCritDbgSection );
230 #elif defined( OS2 )
231 DosCreateMutexSem( NULL, &hImplCritDbgSection, 0, FALSE );
232 #endif
233 bImplCritDbgSectionInit = TRUE;
236 // -----------------------------------------------------------------------
238 void ImplDbgDeInitLock()
240 #if defined( WNT )
241 DeleteCriticalSection( &aImplCritDbgSection );
242 #elif defined( OS2 )
243 DosCloseMutexSem( hImplCritDbgSection );
244 #endif
245 bImplCritDbgSectionInit = FALSE;
248 // -----------------------------------------------------------------------
250 void ImplDbgLock()
252 if ( !bImplCritDbgSectionInit )
253 return;
255 #if defined( WNT )
256 EnterCriticalSection( &aImplCritDbgSection );
257 #elif defined( OS2 )
258 DosRequestMutexSem( hImplCritDbgSection, SEM_INDEFINITE_WAIT );
259 #endif
262 // -----------------------------------------------------------------------
264 void ImplDbgUnlock()
266 if ( !bImplCritDbgSectionInit )
267 return;
269 #if defined( WNT )
270 LeaveCriticalSection( &aImplCritDbgSection );
271 #elif defined( OS2 )
272 DosReleaseMutexSem( hImplCritDbgSection );
273 #endif
276 // =======================================================================
278 #if (defined WNT || defined OS2) && !defined SVX_LIGHT
279 //#define SV_MEMMGR //
280 #endif
281 #ifdef SV_MEMMGR
282 void DbgImpCheckMemory( void* p = NULL );
283 void DbgImpCheckMemoryDeInit();
284 void DbgImpMemoryInfo( sal_Char* pBuf );
285 #endif
287 #define FILE_LINEEND "\n"
289 // =======================================================================
291 static BOOL ImplActivateDebugger( const sal_Char* pMsg )
293 #if defined( WNT )
294 static sal_Char aImplDbgOutBuf[DBG_BUF_MAXLEN];
295 strcpy( aImplDbgOutBuf, pMsg );
296 strcat( aImplDbgOutBuf, "\r\n" );
297 OutputDebugString( aImplDbgOutBuf );
298 DebugBreak();
299 return TRUE;
300 #else
301 (void) pMsg; // avoid warning about unused parameter
302 return FALSE;
303 #endif
306 // -----------------------------------------------------------------------
308 static BOOL ImplCoreDump()
310 #if defined( WNT )
311 DebugBreak();
312 #else
313 long* pTemp = 0;
314 *pTemp = 0xCCCC;
315 #endif
316 return TRUE;
319 // =======================================================================
321 static ULONG ImplGetPerfTime()
323 #if defined( WNT )
324 return (ULONG)GetTickCount();
325 #elif defined( OS2 )
326 ULONG nClock;
327 DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) );
328 return (ULONG)nClock;
329 #else
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;
341 fTicks *= 1000;
342 fTicks /= dImplTicksPerSecond;
343 return (ULONG)fTicks;
344 #endif
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 // =======================================================================
358 namespace
360 enum ConfigSection
362 eOutput,
363 eMemory,
364 eGUI,
365 eObjects,
366 eTest,
368 eUnknown
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;
379 switch ( _eSection )
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;
386 case eUnknown:
387 OSL_ASSERT(false);
388 break;
390 return pSectionName;
393 ConfigSection lcl_getSectionFromName( const sal_Char* _pSectionName, size_t _nSectionNameLength )
395 if ( strncmp( _pSectionName, "output", _nSectionNameLength < 6 ? _nSectionNameLength : 6 ) == 0 )
396 return eOutput;
397 if ( strncmp( _pSectionName, "memory", _nSectionNameLength < 6 ? _nSectionNameLength : 6 ) == 0 )
398 return eMemory;
399 if ( strncmp( _pSectionName, "gui", _nSectionNameLength < 3 ? _nSectionNameLength : 3 ) == 0 )
400 return eGUI;
401 if ( strncmp( _pSectionName, "objects", _nSectionNameLength < 7 ? _nSectionNameLength : 7 ) == 0 )
402 return eObjects;
403 if ( strncmp( _pSectionName, "test", _nSectionNameLength < 4 ? _nSectionNameLength : 4 ) == 0 )
404 return eTest;
405 return eUnknown;
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 )
448 if ( _nLineLen < 2 )
449 // not even enough space for '[' and ']'
450 return false;
451 if ( ( _pLine[0] == '[' ) && ( _pLine[ _nLineLen - 1 ] == ']' ) )
452 return true;
453 return false;
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
460 return false;
461 if ( ( strncmp( _pLine, _pKeyName, nKeyLength ) == 0 ) && ( _pLine[ nKeyLength ] == '=' ) )
462 return true;
463 return false;
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 ) )
468 return 0;
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 )
478 sal_Char aBuf[2];
479 size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) );
480 if ( nValueLen )
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"
489 sal_Char aBuf[20];
490 size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) );
491 if ( nValueLen )
493 for ( ULONG name = 0; name < sizeof( names ) / sizeof( names[0] ); ++name )
495 if ( strcmp( aBuf, names[ name ] ) == 0 )
497 *_out_pnValue = name;
498 return;
503 void lcl_tryReadConfigFlag( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, ULONG* _out_pnAllFlags, ULONG _nCheckFlag )
505 sal_Char aBuf[2];
506 size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) );
507 if ( nValueLen )
508 if ( strcmp( aBuf, "1" ) == 0 )
509 *_out_pnAllFlags |= _nCheckFlag;
510 else
511 *_out_pnAllFlags &= ~_nCheckFlag;
513 void lcl_tryReadHexByte( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, BYTE* _out_pnValue )
515 sal_Char aBuf[3];
516 size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) );
517 if ( nValueLen )
518 *_out_pnValue = (BYTE)rtl_str_toInt32( aBuf, 16 );
522 // =======================================================================
524 PointerList::~PointerList()
526 PBlock* pBlock = pFirst;
527 while ( pBlock )
529 PBlock* pNextBlock = pBlock->pNext;
530 delete pBlock;
531 pBlock = pNextBlock;
535 // -----------------------------------------------------------------------
537 void PointerList::Add( const void* p )
539 if ( !pFirst )
541 pFirst = new PBlock;
542 memset( pFirst->aData, 0, PBLOCKCOUNT * sizeof( void* ) );
543 pFirst->nCount = 0;
544 pFirst->pPrev = NULL;
545 pFirst->pNext = NULL;
546 pLast = pFirst;
549 PBlock* pBlock = pFirst;
550 while ( pBlock && (pBlock->nCount == PBLOCKCOUNT) )
551 pBlock = pBlock->pNext;
553 if ( !pBlock )
555 pBlock = new PBlock;
556 memset( pBlock->aData, 0, PBLOCKCOUNT * sizeof( void* ) );
557 pBlock->nCount = 0;
558 pBlock->pPrev = pLast;
559 pBlock->pNext = NULL;
560 pLast->pNext = pBlock;
561 pLast = pBlock;
564 USHORT i = 0;
565 while ( pBlock->aData[i] )
566 i++;
568 pBlock->aData[i] = (void*)p;
569 pBlock->nCount++;
570 nCount++;
573 // -----------------------------------------------------------------------
575 BOOL PointerList::Remove( const void* p )
577 if ( !p )
578 return FALSE;
580 PBlock* pBlock = pFirst;
581 while ( pBlock )
583 USHORT i = 0;
584 while ( i < PBLOCKCOUNT )
586 if ( ((ULONG)p) == ((ULONG)pBlock->aData[i]) )
588 pBlock->aData[i] = NULL;
589 pBlock->nCount--;
590 nCount--;
592 if ( !pBlock->nCount )
594 if ( pBlock->pPrev )
595 pBlock->pPrev->pNext = pBlock->pNext;
596 if ( pBlock->pNext )
597 pBlock->pNext->pPrev = pBlock->pPrev;
598 if ( pBlock == pFirst )
599 pFirst = pBlock->pNext;
600 if ( pBlock == pLast )
601 pLast = pBlock->pPrev;
602 delete pBlock;
605 return TRUE;
607 i++;
610 pBlock = pBlock->pNext;
613 return FALSE;
616 // -----------------------------------------------------------------------
618 const void* PointerList::Get( ULONG nPos ) const
620 if ( nCount <= nPos )
621 return NULL;
623 PBlock* pBlock = pFirst;
624 ULONG nStart = 0;
625 while ( pBlock )
627 USHORT i = 0;
628 while ( i < PBLOCKCOUNT )
630 if ( pBlock->aData[i] )
632 nStart++;
633 if ( (nStart-1) == nPos )
634 return pBlock->aData[i];
637 i++;
640 pBlock = pBlock->pNext;
643 return NULL;
646 // -----------------------------------------------------------------------
648 BOOL PointerList::IsIn( const void* p ) const
650 if ( !p )
651 return FALSE;
653 PBlock* pBlock = pFirst;
654 while ( pBlock )
656 USHORT i = 0;
657 while ( i < PBLOCKCOUNT )
659 if ( ((ULONG)p) == ((ULONG)pBlock->aData[i]) )
660 return TRUE;
661 i++;
664 pBlock = pBlock->pNext;
667 return FALSE;
671 // =======================================================================
673 static void DbgGetDbgFileName( sal_Char* pStr, sal_Int32 nMaxLen )
675 #if defined( UNX )
676 const sal_Char* pName = getenv("DBGSV_INIT");
677 if ( !pName )
678 pName = ".dbgsv.init";
679 strncpy( pStr, pName, nMaxLen );
680 #elif defined( WNT )
681 const sal_Char* pName = getenv("DBGSV_INIT");
682 if ( pName )
683 strncpy( pStr, pName, nMaxLen );
684 else
685 GetProfileStringA( "sv", "dbgsv", "dbgsv.ini", pStr, nMaxLen );
686 #elif defined( OS2 )
687 PrfQueryProfileString( HINI_PROFILE, (PSZ)"SV", (PSZ)"DBGSV",
688 "dbgsv.ini", (PSZ)pStr, nMaxLen );
689 #else
690 strncpy( pStr, "dbgsv.ini", nMaxLen );
691 #endif
692 pStr[ nMaxLen - 1 ] = 0;
695 // -----------------------------------------------------------------------
697 static void DbgGetLogFileName( sal_Char* pStr )
699 #if defined( UNX )
700 const sal_Char* pName = getenv("DBGSV_LOG");
701 if ( !pName )
702 pName = "dbgsv.log";
703 strcpy( pStr, pName );
704 #elif defined( WNT )
705 const sal_Char* pName = getenv("DBGSV_LOG");
706 if ( pName )
707 strcpy( pStr, pName );
708 else
709 GetProfileStringA( "sv", "dbgsvlog", "dbgsv.log", pStr, 200 );
710 #elif defined( OS2 )
711 PrfQueryProfileString( HINI_PROFILE, (PSZ)"SV", (PSZ)"DBGSVLOG",
712 "dbgsv.log", (PSZ)pStr, 200 );
713 #else
714 strcpy( pStr, "dbgsv.log" );
715 #endif
718 // -----------------------------------------------------------------------
720 static void DbgDebugBeep()
722 #if defined( WNT )
723 MessageBeep( MB_ICONHAND );
724 #elif defined( OS2 )
725 WinAlarm( HWND_DESKTOP, WA_ERROR );
726 #endif
729 // -----------------------------------------------------------------------
731 static DebugData* GetDebugData()
733 if ( !aDebugData.bInit )
735 aDebugData.bInit = TRUE;
737 // Default Debug-Namen setzen
738 DbgGetLogFileName( aDebugData.aDbgData.aDebugName );
740 // DEBUG.INI-File
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;
833 return &aDebugData;
836 // -----------------------------------------------------------------------
838 inline DebugData* ImplGetDebugData()
840 if ( !aDebugData.bInit )
841 return GetDebugData();
842 else
843 return &aDebugData;
846 // -----------------------------------------------------------------------
848 static FILETYPE ImplDbgInitFile()
850 static BOOL bFileInit = FALSE;
852 sal_Char aBuf[4096];
853 getcwd( aBuf, sizeof( aBuf ) );
854 chdir( aCurPath );
856 DebugData* pData = GetDebugData();
857 FILETYPE pDebugFile;
859 if ( !bFileInit )
861 bFileInit = TRUE;
863 if ( pData->aDbgData.bOverwrite )
864 pDebugFile = FileOpen( pData->aDbgData.aDebugName, "w" );
865 else
866 pDebugFile = FileOpen( pData->aDbgData.aDebugName, "a" );
868 if ( pDebugFile )
870 time_t nTime = time( 0 );
871 tm* pTime;
872 #ifdef UNX
873 tm aTime;
874 pTime = localtime_r( &nTime, &aTime );
875 #else
876 pTime = localtime( &nTime );
877 #endif
879 // Header ausgeben
880 FilePrintF( pDebugFile, "******************************************************************************%s", FILE_LINEEND );
881 FilePrintF( pDebugFile, "%s%s", pData->aDbgData.aDebugName, FILE_LINEEND );
882 if ( pTime )
883 FilePrintF( pDebugFile, "%s%s", asctime( pTime ), FILE_LINEEND );
886 else
887 pDebugFile = FileOpen( pData->aDbgData.aDebugName, "a" );
889 chdir( aBuf );
891 return pDebugFile;
894 // -----------------------------------------------------------------------
896 static void ImplDbgPrintFile( const sal_Char* pLine )
898 FILETYPE pDebugFile = ImplDbgInitFile();
900 if ( pDebugFile )
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 )
912 int nPos = 0;
913 while ( nPos+nSearchLen <= nLen )
915 if ( strncmp( pStr+nPos, pSearchStr, nSearchLen ) == 0 )
916 return 1;
917 nPos++;
920 return 0;
923 // -----------------------------------------------------------------------
925 static int ImplDbgFilter( const sal_Char* pFilter, const sal_Char* pMsg,
926 int bEmpty )
928 int nStrLen = strlen( pFilter );
929 if ( !nStrLen )
930 return bEmpty;
932 int nMsgLen = strlen( pMsg );
933 const sal_Char* pTok = pFilter;
934 int nTok = 0;
935 while ( pTok[nTok] )
937 if ( pTok[nTok] == ';' )
939 if ( nTok && ImplStrSearch( pTok, nTok, pMsg, nMsgLen ) )
940 return TRUE;
942 pTok += nTok+1;
943 nTok = 0;
946 nTok++;
949 if ( nTok && ImplStrSearch( pTok, nTok, pMsg, nMsgLen ) )
950 return TRUE;
951 else
952 return FALSE;
955 // -----------------------------------------------------------------------
957 extern "C"
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;
968 ImplDbgInitLock();
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();
983 ULONG i;
984 ULONG nCount;
985 ULONG nOldOut;
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( "==============================================================================" );
1026 // Aufraeumen
1027 if ( pData->pXtorList )
1029 for( i = 0, nCount = pData->pXtorList->Count(); i < nCount; i++ )
1031 XtorType* pXtorData = (XtorType*)pData->pXtorList->Get( i );
1032 delete pXtorData;
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
1042 // funktioniert
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();
1059 ULONG i;
1060 ULONG nCount;
1061 ULONG nOldOut;
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( "==============================================================================" );
1088 // Aufraeumen
1089 if ( pData->pProfList )
1091 for( i = 0, nCount = pData->pProfList->Count(); i < nCount; i++ )
1093 ProfType* pProfData = (ProfType*)pData->pProfList->Get( i );
1094 delete pProfData;
1096 delete pData->pProfList;
1097 pData->pProfList = NULL;
1100 #ifdef SV_MEMMGR
1101 DbgImpCheckMemoryDeInit();
1102 #endif
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, ... )
1113 va_list pList;
1115 va_start( pList, pFStr );
1116 sal_Char aBuf[DBG_BUF_MAXLEN];
1117 vsprintf( aBuf, pFStr, pList );
1118 va_end( pList );
1120 strcat( pBuf, aBuf );
1121 strcat( pBuf, "\n" );
1124 // -----------------------------------------------------------------------
1126 static void DebugXTorInfo( sal_Char* pBuf )
1128 DebugData* pData = GetDebugData();
1129 ULONG i;
1130 ULONG nCount;
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 ) )
1163 return TRUE;
1164 if ( ImplDbgFilter( pData->aDbgData.aExclFilter, pMsg, FALSE ) )
1165 return TRUE;
1166 return 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 ) )
1181 return (void*) -1;
1182 else
1183 return (void*) 0; // aka NULL
1184 else
1187 switch ( nAction )
1189 case DBG_FUNC_DEBUGSTART:
1190 DebugInit();
1191 break;
1193 case DBG_FUNC_DEBUGEND:
1194 DebugDeInit();
1195 break;
1197 case DBG_FUNC_GLOBALDEBUGEND:
1198 DebugGlobalDeInit();
1199 break;
1201 case DBG_FUNC_SETPRINTMSGBOX:
1202 pDebugData->pDbgPrintMsgBox = (DbgPrintLine)(long)pParam;
1203 break;
1205 case DBG_FUNC_SETPRINTWINDOW:
1206 pDebugData->pDbgPrintWindow = (DbgPrintLine)(long)pParam;
1207 break;
1209 case DBG_FUNC_SETPRINTSHELL:
1210 pDebugData->pDbgPrintShell = (DbgPrintLine)(long)pParam;
1211 break;
1213 case DBG_FUNC_SETPRINTTESTTOOL:
1214 pDebugData->pDbgPrintTestTool = (DbgPrintLine)(long)pParam;
1215 break;
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 )
1225 break;
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 );
1278 break;
1280 case DBG_FUNC_MEMTEST:
1281 #ifdef SV_MEMMGR
1282 DbgImpCheckMemory( pParam );
1283 #endif
1284 break;
1286 case DBG_FUNC_XTORINFO:
1287 DebugXTorInfo( (sal_Char*)pParam );
1288 break;
1290 case DBG_FUNC_MEMINFO:
1291 #ifdef SV_MEMMGR
1292 DbgImpMemoryInfo( (sal_Char*)pParam );
1293 #endif
1294 break;
1296 case DBG_FUNC_COREDUMP:
1297 ImplCoreDump();
1298 break;
1300 case DBG_FUNC_ALLERROROUT:
1301 return (void*)(ULONG)TRUE;
1303 case DBG_FUNC_SETTESTSOLARMUTEX:
1304 pDebugData->pDbgTestSolarMutex = (DbgTestSolarMutexProc)(long)pParam;
1305 break;
1307 case DBG_FUNC_TESTSOLARMUTEX:
1308 if ( pDebugData->pDbgTestSolarMutex )
1309 pDebugData->pDbgTestSolarMutex();
1310 break;
1312 case DBG_FUNC_PRINTFILE:
1313 ImplDbgPrintFile( (const sal_Char*)pParam );
1314 break;
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;
1330 break;
1333 return NULL;
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) )
1354 return;
1356 sal_Char aBuf[DBG_BUF_MAXLEN];
1357 ProfType* pProfData = (ProfType*)pDbgData->pData;
1358 ULONG nTime;
1359 if ( (nAction != DBG_PROF_START) && !pProfData )
1361 strcpy( aBuf, DbgError_ProfEnd1 );
1362 strcat( aBuf, pDbgData->pName );
1363 DbgError( aBuf );
1364 return;
1367 switch ( nAction )
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++;
1391 break;
1393 case DBG_PROF_STOP:
1394 nTime = ImplGetPerfTime();
1396 if ( pProfData->nStart == 0xFFFFFFFF )
1398 DbgError( DbgError_ProfEnd1 );
1399 return;
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;
1422 break;
1424 case DBG_PROF_CONTINUE:
1425 if ( pProfData->nContinueStart != 0xFFFFFFFF )
1427 pProfData->nContinueTime += ImplGetPerfTime() - pProfData->nContinueStart;
1428 pProfData->nContinueStart = 0xFFFFFFFF;
1430 break;
1432 case DBG_PROF_PAUSE:
1433 if ( pProfData->nContinueStart == 0xFFFFFFFF )
1434 pProfData->nContinueStart = ImplGetPerfTime();
1435 break;
1439 // -----------------------------------------------------------------------
1441 void DbgXtor( DbgDataType* pDbgData, USHORT nAction, const void* pThis,
1442 DbgUsr fDbgUsr )
1444 DebugData* pData = ImplGetDebugData();
1446 // Verbindung zu Debug-Memory-Manager testen
1447 #ifdef SV_MEMMGR
1448 if ( pData->aDbgData.nTestFlags & DBG_TEST_MEM_XTOR )
1449 DbgImpCheckMemory();
1450 #endif
1452 // Schnell-Test
1453 if ( !(pData->aDbgData.nTestFlags & DBG_TEST_XTOR) )
1454 return;
1456 XtorType* pXtorData = (XtorType*)pDbgData->pData;
1457 if ( !pXtorData )
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 )
1476 return;
1478 sal_Char aBuf[DBG_BUF_MAXLEN];
1479 USHORT nAct = nAction & ~DBG_XTOR_DTOROBJ;
1481 // Trace (Enter)
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 );
1491 else
1492 strcpy( aBuf, DbgTrace_EnterMeth );
1493 strcat( aBuf, pDbgData->pName );
1494 DbgTrace( aBuf );
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 );
1506 DbgError( aBuf );
1507 return;
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
1517 if ( !pThis )
1519 strcpy( aBuf, DbgError_CtorDtor1 );
1520 strcat( aBuf, pDbgData->pName );
1521 DbgError( aBuf );
1522 return;
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 );
1531 DbgError( aBuf );
1537 // Function-Test durchfuehren und Verwaltungsdaten updaten
1538 const sal_Char* pMsg = NULL;
1539 switch ( nAction & ~DBG_XTOR_DTOROBJ )
1541 case DBG_XTOR_CTOR:
1542 if ( nAction & DBG_XTOR_DTOROBJ )
1544 if ( fDbgUsr &&
1545 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) &&
1546 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
1547 pMsg = fDbgUsr( pThis );
1549 else
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 );
1560 break;
1562 case DBG_XTOR_DTOR:
1563 if ( nAction & DBG_XTOR_DTOROBJ )
1565 pXtorData->nDtorCalls++;
1566 if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_THIS )
1567 pXtorData->aThisList.Remove( pThis );
1569 else
1571 if ( fDbgUsr &&
1572 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
1573 pMsg = fDbgUsr( pThis );
1575 break;
1577 case DBG_XTOR_CHKTHIS:
1578 case DBG_XTOR_CHKOBJ:
1579 if ( nAction & DBG_XTOR_DTOROBJ )
1581 if ( fDbgUsr &&
1582 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) &&
1583 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
1584 pMsg = fDbgUsr( pThis );
1586 else
1588 if ( fDbgUsr &&
1589 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
1590 pMsg = fDbgUsr( pThis );
1592 break;
1595 // Gegebenenfalls Fehlermeldung ausgeben
1596 if ( pMsg )
1598 sprintf( aBuf, DbgError_CtorDtor3, pThis );
1599 strcat( aBuf, pDbgData->pName );
1600 strcat( aBuf, ": \n" );
1601 strcat( aBuf, pMsg );
1602 DbgError( aBuf );
1606 // Trace (Leave)
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 );
1616 else
1617 strcpy( aBuf, DbgTrace_LeaveMeth );
1618 strcat( aBuf, pDbgData->pName );
1619 DbgTrace( aBuf );
1624 // -----------------------------------------------------------------------
1626 void DbgOut( const sal_Char* pMsg, USHORT nDbgOut, const sal_Char* pFile, USHORT nLine )
1628 static BOOL bIn = FALSE;
1629 if ( bIn )
1630 return;
1631 bIn = TRUE;
1633 DebugData* pData = GetDebugData();
1634 sal_Char const * pStr;
1635 ULONG nOut;
1636 int nBufLen = 0;
1638 if ( nDbgOut == DBG_OUT_ERROR )
1640 nOut = pData->aDbgData.nErrorOut;
1641 pStr = "Error: ";
1642 if ( pData->aDbgData.nErrorOut == DBG_OUT_FILE )
1643 DbgDebugBeep();
1645 else if ( nDbgOut == DBG_OUT_WARNING )
1647 nOut = pData->aDbgData.nWarningOut;
1648 pStr = "Warning: ";
1650 else
1652 nOut = pData->aDbgData.nTraceOut;
1653 pStr = NULL;
1656 if ( nOut == DBG_OUT_NULL )
1658 bIn = FALSE;
1659 return;
1662 if ( ImplDbgFilterMessage( pMsg ) )
1664 bIn = FALSE;
1665 return;
1668 ImplDbgLock();
1670 sal_Char aBufOut[DBG_BUF_MAXLEN];
1671 if ( pStr )
1673 strcpy( aBufOut, pStr );
1674 nBufLen = strlen( pStr );
1676 else
1677 aBufOut[0] = '\0';
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]), "..." );
1686 else
1687 strcpy( &(aBufOut[nBufLen]), pMsg );
1689 if ( pFile && nLine && (nBufLen+nMsgLen < DBG_BUF_MAXLEN) )
1691 if ( nOut == DBG_OUT_MSGBOX )
1692 strcat( aBufOut, "\n" );
1693 else
1694 strcat( aBufOut, " " );
1695 strcat( aBufOut, "From File " );
1696 strcat( aBufOut, pFile );
1697 strcat( aBufOut, " at Line " );
1699 // Line in String umwandeln und dranhaengen
1700 sal_Char aLine[9];
1701 sal_Char* pLine = &aLine[7];
1702 USHORT i;
1703 memset( aLine, 0, sizeof( aLine ) );
1706 i = nLine % 10;
1707 pLine--;
1708 *(pLine) = (sal_Char)i + 48;
1709 nLine /= 10;
1711 while ( nLine );
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 ];
1718 if ( pPrinter )
1719 pPrinter( aBufOut );
1720 else
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 );
1740 else
1741 nOut = DBG_OUT_MSGBOX;
1744 if ( nOut == DBG_OUT_MSGBOX )
1746 if ( pData->pDbgPrintMsgBox )
1747 pData->pDbgPrintMsgBox( aBufOut );
1748 else
1749 nOut = DBG_OUT_SHELL;
1752 if ( nOut == DBG_OUT_SHELL )
1754 if ( pData->pDbgPrintShell )
1755 pData->pDbgPrintShell( aBufOut );
1756 else
1757 nOut = DBG_OUT_WINDOW;
1760 if ( nOut == DBG_OUT_WINDOW )
1762 if ( pData->pDbgPrintWindow )
1763 pData->pDbgPrintWindow( aBufOut );
1764 else
1765 nOut = DBG_OUT_FILE;
1768 if ( nOut == DBG_OUT_FILE )
1769 ImplDbgPrintFile( aBufOut );
1771 ImplDbgUnlock();
1773 bIn = FALSE;
1776 // -----------------------------------------------------------------------
1778 void DbgOutTypef( USHORT nDbgOut, const sal_Char* pFStr, ... )
1780 va_list pList;
1782 va_start( pList, pFStr );
1783 sal_Char aBuf[DBG_BUF_MAXLEN];
1784 vsprintf( aBuf, pFStr, pList );
1785 va_end( pList );
1787 DbgOut( aBuf, nDbgOut );
1790 // -----------------------------------------------------------------------
1792 void DbgOutf( const sal_Char* pFStr, ... )
1794 va_list pList;
1796 va_start( pList, pFStr );
1797 sal_Char aBuf[DBG_BUF_MAXLEN];
1798 vsprintf( aBuf, pFStr, pList );
1799 va_end( pList );
1801 DbgOut( aBuf );
1804 // =======================================================================
1806 #else
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*, ... ) {}
1817 #endif