1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_tools.hxx" 30 31 #define _TOOLS_DEBUG_CXX 32 33 #if defined (UNX) || defined (GCC) 34 #include <unistd.h> 35 #else 36 #include <direct.h> 37 #endif 38 39 #include <time.h> 40 #include <cstdarg> // combinations 41 #include <stdlib.h> 42 #include <string.h> 43 #include <stdio.h> 44 45 #ifdef OS2 46 #define INCL_DOSSEMAPHORES 47 #define INCL_DOSMISC 48 #define INCL_WINDIALOGS 49 #define INCL_WINSHELLDATA 50 #include <svpm.h> 51 #endif 52 53 #if defined ( WNT ) 54 #ifdef _MSC_VER 55 #pragma warning (push,1) 56 #endif 57 #include <tools/svwin.h> 58 #ifdef _MSC_VER 59 #pragma warning (pop) 60 #endif 61 #endif 62 63 #include <tools/debug.hxx> 64 #include <rtl/string.h> 65 66 #include <vector> 67 68 #include <osl/diagnose.h> 69 70 // ======================================================================= 71 72 #ifdef DBG_UTIL 73 74 // --- DbgErrors --- 75 76 static sal_Char const DbgError_ProfEnd1[] = "DBG_PROF...() without DBG_PROFSTART(): "; 77 static sal_Char const DbgError_Xtor1[] = "DBG_DTOR() or DBG_CHKTHIS() without DBG_CTOR(): "; 78 79 static sal_Char const DbgError_CtorDtor1[] = "this == NULL in class "; 80 static sal_Char const DbgError_CtorDtor2[] = "invalid this-Pointer %p in class "; 81 static sal_Char const DbgError_CtorDtor3[] = "Error-Msg from Object %p in class "; 82 83 static sal_Char const DbgTrace_EnterCtor[] = "Enter Ctor from class "; 84 static sal_Char const DbgTrace_LeaveCtor[] = "Leave Ctor from class "; 85 static sal_Char const DbgTrace_EnterDtor[] = "Enter Dtor from class "; 86 static sal_Char const DbgTrace_LeaveDtor[] = "Leave Dtor from class "; 87 static sal_Char const DbgTrace_EnterMeth[] = "Enter method from class "; 88 static sal_Char const DbgTrace_LeaveMeth[] = "Leave method from class "; 89 90 // --- PointerList --- 91 92 #define PBLOCKCOUNT 1024 93 94 struct PBlock 95 { 96 void* aData[PBLOCKCOUNT]; 97 sal_uInt16 nCount; 98 PBlock* pPrev; 99 PBlock* pNext; 100 }; 101 102 class PointerList 103 { 104 private: 105 PBlock* pFirst; 106 PBlock* pLast; 107 sal_uIntPtr nCount; 108 109 public: 110 PointerList() { pFirst = NULL; pLast = NULL; nCount = 0; } 111 ~PointerList(); 112 113 void Add( const void* p ); 114 sal_Bool Remove( const void* p ); 115 116 const void* Get( sal_uIntPtr nPos ) const; 117 sal_Bool IsIn( const void* p ) const; 118 sal_uIntPtr Count() const { return nCount; } 119 }; 120 121 // --- Datentypen --- 122 123 #define DBG_MAXNAME 28 124 125 struct ProfType 126 { 127 sal_uIntPtr nCount; 128 sal_uIntPtr nTime; 129 sal_uIntPtr nMinTime; 130 sal_uIntPtr nMaxTime; 131 sal_uIntPtr nStart; 132 sal_uIntPtr nContinueTime; 133 sal_uIntPtr nContinueStart; 134 sal_Char aName[DBG_MAXNAME+1]; 135 }; 136 137 struct XtorType 138 { 139 sal_uIntPtr nCtorCalls; 140 sal_uIntPtr nDtorCalls; 141 sal_uIntPtr nMaxCount; 142 sal_uIntPtr nStatics; 143 sal_Char aName[DBG_MAXNAME+1]; 144 sal_Bool bTest; 145 PointerList aThisList; 146 }; 147 148 struct DebugData 149 { 150 DbgData aDbgData; 151 sal_uInt16 bInit; 152 DbgPrintLine pDbgPrintMsgBox; 153 DbgPrintLine pDbgPrintWindow; 154 DbgPrintLine pDbgPrintTestTool; 155 DbgPrintLine pDbgAbort; 156 ::std::vector< DbgPrintLine > 157 aDbgPrintUserChannels; 158 PointerList* pProfList; 159 PointerList* pXtorList; 160 DbgTestSolarMutexProc pDbgTestSolarMutex; 161 pfunc_osl_printDetailedDebugMessage 162 pOldDebugMessageFunc; 163 bool bOslIsHooked; 164 165 DebugData() 166 :bInit( sal_False ) 167 ,pDbgPrintMsgBox( NULL ) 168 ,pDbgPrintWindow( NULL ) 169 ,pDbgPrintTestTool( NULL ) 170 ,pDbgAbort( NULL ) 171 ,pProfList( NULL ) 172 ,pXtorList( NULL ) 173 ,pDbgTestSolarMutex( NULL ) 174 ,pOldDebugMessageFunc( NULL ) 175 ,bOslIsHooked( false ) 176 { 177 aDbgData.nTestFlags = DBG_TEST_RESOURCE | DBG_TEST_MEM_INIT; 178 aDbgData.bOverwrite = sal_True; 179 aDbgData.nTraceOut = DBG_OUT_NULL; 180 aDbgData.nWarningOut = DBG_OUT_NULL; 181 aDbgData.nErrorOut = DBG_OUT_MSGBOX; 182 aDbgData.bMemInit = 0x77; 183 aDbgData.bMemBound = 0x55; 184 aDbgData.bMemFree = 0x33; 185 aDbgData.bHookOSLAssert = sal_True; 186 aDbgData.aDebugName[0] = 0; 187 aDbgData.aInclFilter[0] = 0; 188 aDbgData.aExclFilter[0] = 0; 189 aDbgData.aInclClassFilter[0] = 0; 190 aDbgData.aExclClassFilter[0] = 0; 191 aDbgData.aDbgWinState[0] = 0; 192 } 193 }; 194 195 #define DBG_TEST_XTOR_EXTRA (DBG_TEST_XTOR_THIS | DBG_TEST_XTOR_FUNC | \ 196 DBG_TEST_XTOR_EXIT | DBG_TEST_XTOR_REPORT ) 197 198 // ------------------------------ 199 // - statische Verwaltungsdaten - 200 // ------------------------------ 201 202 static DebugData aDebugData; 203 204 static sal_Char aCurPath[260]; 205 206 static int bDbgImplInMain = sal_False; 207 208 // ======================================================================= 209 210 #if defined( WNT ) 211 static CRITICAL_SECTION aImplCritDbgSection; 212 #elif defined( OS2 ) 213 static HMTX hImplCritDbgSection = 0; 214 #endif 215 static sal_Bool bImplCritDbgSectionInit = sal_False; 216 217 // ----------------------------------------------------------------------- 218 219 void ImplDbgInitLock() 220 { 221 #if defined( WNT ) 222 InitializeCriticalSection( &aImplCritDbgSection ); 223 #elif defined( OS2 ) 224 DosCreateMutexSem( NULL, &hImplCritDbgSection, 0, sal_False ); 225 #endif 226 bImplCritDbgSectionInit = sal_True; 227 } 228 229 // ----------------------------------------------------------------------- 230 231 void ImplDbgDeInitLock() 232 { 233 #if defined( WNT ) 234 DeleteCriticalSection( &aImplCritDbgSection ); 235 #elif defined( OS2 ) 236 DosCloseMutexSem( hImplCritDbgSection ); 237 #endif 238 bImplCritDbgSectionInit = sal_False; 239 } 240 241 // ----------------------------------------------------------------------- 242 243 void ImplDbgLock() 244 { 245 if ( !bImplCritDbgSectionInit ) 246 return; 247 248 #if defined( WNT ) 249 EnterCriticalSection( &aImplCritDbgSection ); 250 #elif defined( OS2 ) 251 DosRequestMutexSem( hImplCritDbgSection, SEM_INDEFINITE_WAIT ); 252 #endif 253 } 254 255 // ----------------------------------------------------------------------- 256 257 void ImplDbgUnlock() 258 { 259 if ( !bImplCritDbgSectionInit ) 260 return; 261 262 #if defined( WNT ) 263 LeaveCriticalSection( &aImplCritDbgSection ); 264 #elif defined( OS2 ) 265 DosReleaseMutexSem( hImplCritDbgSection ); 266 #endif 267 } 268 269 // ======================================================================= 270 271 #if (defined WNT || defined OS2) && !defined SVX_LIGHT 272 //#define SV_MEMMGR // 273 #endif 274 #ifdef SV_MEMMGR 275 void DbgImpCheckMemory( void* p = NULL ); 276 void DbgImpCheckMemoryDeInit(); 277 void DbgImpMemoryInfo( sal_Char* pBuf ); 278 #endif 279 280 #define FILE_LINEEND "\n" 281 282 // ======================================================================= 283 284 static sal_Bool ImplActivateDebugger( const sal_Char* pMsg ) 285 { 286 #if defined( WNT ) 287 static sal_Char aImplDbgOutBuf[DBG_BUF_MAXLEN]; 288 strcpy( aImplDbgOutBuf, pMsg ); 289 strcat( aImplDbgOutBuf, "\r\n" ); 290 OutputDebugString( aImplDbgOutBuf ); 291 DebugBreak(); 292 return sal_True; 293 #else 294 (void) pMsg; // avoid warning about unused parameter 295 return sal_False; 296 #endif 297 } 298 299 // ----------------------------------------------------------------------- 300 301 static sal_Bool ImplCoreDump() 302 { 303 #if defined( WNT ) 304 DebugBreak(); 305 #else 306 long* pTemp = 0; 307 *pTemp = 0xCCCC; 308 #endif 309 return sal_True; 310 } 311 312 // ======================================================================= 313 314 static sal_uIntPtr ImplGetPerfTime() 315 { 316 #if defined( WNT ) 317 return (sal_uIntPtr)GetTickCount(); 318 #elif defined( OS2 ) 319 sal_uIntPtr nClock; 320 DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) ); 321 return (sal_uIntPtr)nClock; 322 #else 323 static sal_uIntPtr nImplTicksPerSecond = 0; 324 static double dImplTicksPerSecond; 325 sal_uIntPtr nTicks = (sal_uIntPtr)clock(); 326 327 if ( !nImplTicksPerSecond ) 328 { 329 nImplTicksPerSecond = CLOCKS_PER_SEC; 330 dImplTicksPerSecond = nImplTicksPerSecond; 331 } 332 333 double fTicks = nTicks; 334 fTicks *= 1000; 335 fTicks /= dImplTicksPerSecond; 336 return (sal_uIntPtr)fTicks; 337 #endif 338 } 339 340 // ----------------------------------------------------------------------- 341 342 typedef FILE* FILETYPE; 343 #define FileOpen fopen 344 #define FileRead fread 345 #define FileWrite fwrite 346 #define FilePrintF fprintf 347 #define FileClose fclose 348 349 // ======================================================================= 350 351 namespace 352 { 353 enum ConfigSection 354 { 355 eOutput, 356 eMemory, 357 eGUI, 358 eObjects, 359 eTest, 360 361 eUnknown 362 }; 363 364 void lcl_lineFeed( FILETYPE _pFile ) 365 { 366 FilePrintF( _pFile, "%s", FILE_LINEEND ); 367 } 368 369 const sal_Char* lcl_getSectionName( ConfigSection _eSection ) 370 { 371 const sal_Char* pSectionName = NULL; 372 switch ( _eSection ) 373 { 374 case eOutput : pSectionName = "output"; break; 375 case eMemory : pSectionName = "memory"; break; 376 case eGUI : pSectionName = "gui"; break; 377 case eObjects : pSectionName = "objects"; break; 378 case eTest : pSectionName = "test"; break; 379 case eUnknown: 380 OSL_ASSERT(false); 381 break; 382 } 383 return pSectionName; 384 } 385 386 ConfigSection lcl_getSectionFromName( const sal_Char* _pSectionName, size_t _nSectionNameLength ) 387 { 388 if ( strncmp( _pSectionName, "output", _nSectionNameLength < 6 ? _nSectionNameLength : 6 ) == 0 ) 389 return eOutput; 390 if ( strncmp( _pSectionName, "memory", _nSectionNameLength < 6 ? _nSectionNameLength : 6 ) == 0 ) 391 return eMemory; 392 if ( strncmp( _pSectionName, "gui", _nSectionNameLength < 3 ? _nSectionNameLength : 3 ) == 0 ) 393 return eGUI; 394 if ( strncmp( _pSectionName, "objects", _nSectionNameLength < 7 ? _nSectionNameLength : 7 ) == 0 ) 395 return eObjects; 396 if ( strncmp( _pSectionName, "test", _nSectionNameLength < 4 ? _nSectionNameLength : 4 ) == 0 ) 397 return eTest; 398 return eUnknown; 399 } 400 401 void lcl_startSection( FILETYPE _pFile, ConfigSection _eSection ) 402 { 403 FilePrintF( _pFile, "[%s]%s", lcl_getSectionName( _eSection ), FILE_LINEEND ); 404 } 405 406 void lcl_writeConfigString( FILETYPE _pFile, const sal_Char* _pKeyName, const sal_Char* _pValue ) 407 { 408 FilePrintF( _pFile, "%s=%s%s", _pKeyName, _pValue, FILE_LINEEND ); 409 } 410 411 void lcl_writeConfigBoolean( FILETYPE _pFile, const sal_Char* _pKeyName, bool _bValue ) 412 { 413 lcl_writeConfigString( _pFile, _pKeyName, _bValue ? "1" : "0" ); 414 } 415 416 void lcl_writeConfigFlag( FILETYPE _pFile, const sal_Char* _pKeyName, sal_uIntPtr _nAllFlags, sal_uIntPtr _nCheckFlag ) 417 { 418 lcl_writeConfigBoolean( _pFile, _pKeyName, ( _nAllFlags & _nCheckFlag ) != 0 ); 419 } 420 421 void lcl_writeConfigOutChannel( FILETYPE _pFile, const sal_Char* _pKeyName, sal_uIntPtr _nValue ) 422 { 423 const sal_Char* names[ DBG_OUT_COUNT ] = 424 { 425 "dev/null", "file", "window", "shell", "messagebox", "testtool", "debugger", "abort" 426 }; 427 lcl_writeConfigString( _pFile, _pKeyName, names[ _nValue ] ); 428 } 429 void lcl_writeHexByte( FILETYPE _pFile, const sal_Char* _pKeyName, sal_uInt8 _nValue ) 430 { 431 sal_Char buf[RTL_STR_MAX_VALUEOFINT32]; 432 rtl_String* stringData = NULL; 433 rtl_string_newFromStr_WithLength( &stringData, buf, rtl_str_valueOfInt32( buf, _nValue, 16 ) ); 434 435 lcl_writeConfigString( _pFile, _pKeyName, stringData->buffer ); 436 437 rtl_string_release( stringData ); 438 } 439 bool lcl_isConfigSection( const sal_Char* _pLine, size_t _nLineLen ) 440 { 441 if ( _nLineLen < 2 ) 442 // not even enough space for '[' and ']' 443 return false; 444 if ( ( _pLine[0] == '[' ) && ( _pLine[ _nLineLen - 1 ] == ']' ) ) 445 return true; 446 return false; 447 } 448 bool lcl_isConfigKey( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName ) 449 { 450 size_t nKeyLength = strlen( _pKeyName ); 451 if ( nKeyLength + 1 >= _nLineLen ) 452 // not even long enough for the key name plus "=" plus a one-character value 453 return false; 454 if ( ( strncmp( _pLine, _pKeyName, nKeyLength ) == 0 ) && ( _pLine[ nKeyLength ] == '=' ) ) 455 return true; 456 return false; 457 } 458 sal_Int32 lcl_tryReadConfigString( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, sal_Char* _pValue, size_t _nValueLen ) 459 { 460 if ( !lcl_isConfigKey( _pLine, _nLineLen, _pKeyName ) ) 461 return 0; 462 size_t nValuePos = strlen( _pKeyName ) + 1; 463 size_t nValueLen = _nLineLen - nValuePos; 464 const sal_Char* pValue = _pLine + nValuePos; 465 strncpy( _pValue, pValue, ( _nValueLen > nValueLen ) ? nValueLen : _nValueLen ); 466 _pValue[ ( _nValueLen > nValueLen ) ? nValueLen : _nValueLen - 1 ] = 0; 467 return strlen( _pValue ); 468 } 469 void lcl_tryReadConfigBoolean( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, sal_uIntPtr* _out_pnValue ) 470 { 471 sal_Char aBuf[2]; 472 size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) ); 473 if ( nValueLen ) 474 *_out_pnValue = strcmp( aBuf, "1" ) == 0 ? sal_True : sal_False; 475 } 476 void lcl_matchOutputChannel( sal_Char const * i_buffer, sal_uIntPtr* o_value ) 477 { 478 if ( i_buffer == NULL ) 479 return; 480 const sal_Char* names[ DBG_OUT_COUNT ] = 481 { 482 "dev/null", "file", "window", "shell", "messagebox", "testtool", "debugger", "abort" 483 }; 484 for ( sal_uIntPtr name = 0; name < sizeof( names ) / sizeof( names[0] ); ++name ) 485 { 486 if ( strcmp( i_buffer, names[ name ] ) == 0 ) 487 { 488 *o_value = name; 489 return; 490 } 491 } 492 } 493 void lcl_tryReadOutputChannel( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, sal_uIntPtr* _out_pnValue ) 494 { 495 sal_Char aBuf[20]; 496 size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) ); 497 if ( nValueLen ) 498 lcl_matchOutputChannel( aBuf, _out_pnValue ); 499 } 500 void lcl_tryReadConfigFlag( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, sal_uIntPtr* _out_pnAllFlags, sal_uIntPtr _nCheckFlag ) 501 { 502 sal_Char aBuf[2]; 503 size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) ); 504 if ( nValueLen ) 505 if ( strcmp( aBuf, "1" ) == 0 ) 506 *_out_pnAllFlags |= _nCheckFlag; 507 else 508 *_out_pnAllFlags &= ~_nCheckFlag; 509 } 510 void lcl_tryReadHexByte( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, sal_uInt8* _out_pnValue ) 511 { 512 sal_Char aBuf[3]; 513 size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) ); 514 if ( nValueLen ) 515 *_out_pnValue = (sal_uInt8)rtl_str_toInt32( aBuf, 16 ); 516 } 517 } 518 519 // ======================================================================= 520 521 PointerList::~PointerList() 522 { 523 PBlock* pBlock = pFirst; 524 while ( pBlock ) 525 { 526 PBlock* pNextBlock = pBlock->pNext; 527 delete pBlock; 528 pBlock = pNextBlock; 529 } 530 } 531 532 // ----------------------------------------------------------------------- 533 534 void PointerList::Add( const void* p ) 535 { 536 if ( !pFirst ) 537 { 538 pFirst = new PBlock; 539 memset( pFirst->aData, 0, PBLOCKCOUNT * sizeof( void* ) ); 540 pFirst->nCount = 0; 541 pFirst->pPrev = NULL; 542 pFirst->pNext = NULL; 543 pLast = pFirst; 544 } 545 546 PBlock* pBlock = pFirst; 547 while ( pBlock && (pBlock->nCount == PBLOCKCOUNT) ) 548 pBlock = pBlock->pNext; 549 550 if ( !pBlock ) 551 { 552 pBlock = new PBlock; 553 memset( pBlock->aData, 0, PBLOCKCOUNT * sizeof( void* ) ); 554 pBlock->nCount = 0; 555 pBlock->pPrev = pLast; 556 pBlock->pNext = NULL; 557 pLast->pNext = pBlock; 558 pLast = pBlock; 559 } 560 561 sal_uInt16 i = 0; 562 while ( pBlock->aData[i] ) 563 i++; 564 565 pBlock->aData[i] = (void*)p; 566 pBlock->nCount++; 567 nCount++; 568 } 569 570 // ----------------------------------------------------------------------- 571 572 sal_Bool PointerList::Remove( const void* p ) 573 { 574 if ( !p ) 575 return sal_False; 576 577 PBlock* pBlock = pFirst; 578 while ( pBlock ) 579 { 580 sal_uInt16 i = 0; 581 while ( i < PBLOCKCOUNT ) 582 { 583 if ( ((sal_uIntPtr)p) == ((sal_uIntPtr)pBlock->aData[i]) ) 584 { 585 pBlock->aData[i] = NULL; 586 pBlock->nCount--; 587 nCount--; 588 589 if ( !pBlock->nCount ) 590 { 591 if ( pBlock->pPrev ) 592 pBlock->pPrev->pNext = pBlock->pNext; 593 if ( pBlock->pNext ) 594 pBlock->pNext->pPrev = pBlock->pPrev; 595 if ( pBlock == pFirst ) 596 pFirst = pBlock->pNext; 597 if ( pBlock == pLast ) 598 pLast = pBlock->pPrev; 599 delete pBlock; 600 } 601 602 return sal_True; 603 } 604 i++; 605 } 606 607 pBlock = pBlock->pNext; 608 } 609 610 return sal_False; 611 } 612 613 // ----------------------------------------------------------------------- 614 615 const void* PointerList::Get( sal_uIntPtr nPos ) const 616 { 617 if ( nCount <= nPos ) 618 return NULL; 619 620 PBlock* pBlock = pFirst; 621 sal_uIntPtr nStart = 0; 622 while ( pBlock ) 623 { 624 sal_uInt16 i = 0; 625 while ( i < PBLOCKCOUNT ) 626 { 627 if ( pBlock->aData[i] ) 628 { 629 nStart++; 630 if ( (nStart-1) == nPos ) 631 return pBlock->aData[i]; 632 } 633 634 i++; 635 } 636 637 pBlock = pBlock->pNext; 638 } 639 640 return NULL; 641 } 642 643 // ----------------------------------------------------------------------- 644 645 sal_Bool PointerList::IsIn( const void* p ) const 646 { 647 if ( !p ) 648 return sal_False; 649 650 PBlock* pBlock = pFirst; 651 while ( pBlock ) 652 { 653 sal_uInt16 i = 0; 654 while ( i < PBLOCKCOUNT ) 655 { 656 if ( ((sal_uIntPtr)p) == ((sal_uIntPtr)pBlock->aData[i]) ) 657 return sal_True; 658 i++; 659 } 660 661 pBlock = pBlock->pNext; 662 } 663 664 return sal_False; 665 } 666 667 668 // ======================================================================= 669 670 static void DbgGetDbgFileName( sal_Char* pStr, sal_Int32 nMaxLen ) 671 { 672 #if defined( UNX ) 673 const sal_Char* pName = getenv("DBGSV_INIT"); 674 if ( !pName ) 675 pName = ".dbgsv.init"; 676 strncpy( pStr, pName, nMaxLen ); 677 #elif defined( WNT ) 678 const sal_Char* pName = getenv("DBGSV_INIT"); 679 if ( pName ) 680 strncpy( pStr, pName, nMaxLen ); 681 else 682 GetProfileStringA( "sv", "dbgsv", "dbgsv.ini", pStr, nMaxLen ); 683 #elif defined( OS2 ) 684 PrfQueryProfileString( HINI_PROFILE, (PSZ)"SV", (PSZ)"DBGSV", 685 "dbgsv.ini", (PSZ)pStr, nMaxLen ); 686 #else 687 strncpy( pStr, "dbgsv.ini", nMaxLen ); 688 #endif 689 pStr[ nMaxLen - 1 ] = 0; 690 } 691 692 // ----------------------------------------------------------------------- 693 694 static void DbgGetLogFileName( sal_Char* pStr ) 695 { 696 #if defined( UNX ) 697 const sal_Char* pName = getenv("DBGSV_LOG"); 698 if ( !pName ) 699 pName = "dbgsv.log"; 700 strcpy( pStr, pName ); 701 #elif defined( WNT ) 702 const sal_Char* pName = getenv("DBGSV_LOG"); 703 if ( pName ) 704 strcpy( pStr, pName ); 705 else 706 GetProfileStringA( "sv", "dbgsvlog", "dbgsv.log", pStr, 200 ); 707 #elif defined( OS2 ) 708 PrfQueryProfileString( HINI_PROFILE, (PSZ)"SV", (PSZ)"DBGSVLOG", 709 "dbgsv.log", (PSZ)pStr, 200 ); 710 #else 711 strcpy( pStr, "dbgsv.log" ); 712 #endif 713 } 714 715 // ----------------------------------------------------------------------- 716 717 static void DbgDebugBeep() 718 { 719 #if defined( WNT ) 720 MessageBeep( MB_ICONHAND ); 721 #elif defined( OS2 ) 722 WinAlarm( HWND_DESKTOP, WA_ERROR ); 723 #endif 724 } 725 726 // ----------------------------------------------------------------------- 727 728 static DebugData* GetDebugData() 729 { 730 if ( !aDebugData.bInit ) 731 { 732 aDebugData.bInit = sal_True; 733 734 // Default Debug-Namen setzen 735 DbgGetLogFileName( aDebugData.aDbgData.aDebugName ); 736 737 // DEBUG.INI-File 738 sal_Char aBuf[ 4096 ]; 739 DbgGetDbgFileName( aBuf, sizeof( aBuf ) ); 740 FILETYPE pIniFile = FileOpen( aBuf, "r" ); 741 if ( pIniFile != NULL ) 742 { 743 ConfigSection eCurrentSection = eUnknown; 744 745 // no sophisticated algorithm here, assume that the whole file fits into aBuf ... 746 sal_uIntPtr nReallyRead = FileRead( aBuf, 1, sizeof( aBuf ) / sizeof( sal_Char ) - 1, pIniFile ); 747 aBuf[ nReallyRead ] = 0; 748 const sal_Char* pLine = aBuf; 749 while ( const sal_Char* pNextLine = strstr( pLine, FILE_LINEEND ) ) 750 { 751 size_t nLineLength = pNextLine - pLine; 752 753 if ( lcl_isConfigSection( pLine, nLineLength ) ) 754 eCurrentSection = lcl_getSectionFromName( pLine + 1, nLineLength - 2 ); 755 756 // elements of the [output] section 757 if ( eCurrentSection == eOutput ) 758 { 759 lcl_tryReadConfigString( pLine, nLineLength, "log_file", aDebugData.aDbgData.aDebugName, sizeof( aDebugData.aDbgData.aDebugName ) ); 760 lcl_tryReadConfigBoolean( pLine, nLineLength, "overwrite", &aDebugData.aDbgData.bOverwrite ); 761 lcl_tryReadConfigString( pLine, nLineLength, "include", aDebugData.aDbgData.aInclFilter, sizeof( aDebugData.aDbgData.aInclFilter ) ); 762 lcl_tryReadConfigString( pLine, nLineLength, "exclude", aDebugData.aDbgData.aExclFilter, sizeof( aDebugData.aDbgData.aExclFilter ) ); 763 lcl_tryReadConfigString( pLine, nLineLength, "include_class", aDebugData.aDbgData.aInclClassFilter, sizeof( aDebugData.aDbgData.aInclClassFilter ) ); 764 lcl_tryReadConfigString( pLine, nLineLength, "exclude_class", aDebugData.aDbgData.aExclClassFilter, sizeof( aDebugData.aDbgData.aExclClassFilter ) ); 765 lcl_tryReadOutputChannel( pLine, nLineLength, "trace", &aDebugData.aDbgData.nTraceOut ); 766 lcl_tryReadOutputChannel( pLine, nLineLength, "warning", &aDebugData.aDbgData.nWarningOut ); 767 lcl_tryReadOutputChannel( pLine, nLineLength, "error", &aDebugData.aDbgData.nErrorOut ); 768 lcl_tryReadConfigBoolean( pLine, nLineLength, "oslhook", &aDebugData.aDbgData.bHookOSLAssert ); 769 } 770 771 // elements of the [memory] section 772 if ( eCurrentSection == eMemory ) 773 { 774 lcl_tryReadConfigFlag( pLine, nLineLength, "initialize", &aDebugData.aDbgData.nTestFlags, DBG_TEST_MEM_INIT ); 775 lcl_tryReadConfigFlag( pLine, nLineLength, "overwrite", &aDebugData.aDbgData.nTestFlags, DBG_TEST_MEM_OVERWRITE ); 776 lcl_tryReadConfigFlag( pLine, nLineLength, "overwrite_free", &aDebugData.aDbgData.nTestFlags, DBG_TEST_MEM_OVERWRITEFREE ); 777 lcl_tryReadConfigFlag( pLine, nLineLength, "pointer", &aDebugData.aDbgData.nTestFlags, DBG_TEST_MEM_POINTER ); 778 lcl_tryReadConfigFlag( pLine, nLineLength, "report", &aDebugData.aDbgData.nTestFlags, DBG_TEST_MEM_REPORT ); 779 lcl_tryReadConfigFlag( pLine, nLineLength, "trace", &aDebugData.aDbgData.nTestFlags, DBG_TEST_MEM_TRACE ); 780 lcl_tryReadConfigFlag( pLine, nLineLength, "new_and_delete", &aDebugData.aDbgData.nTestFlags, DBG_TEST_MEM_NEWDEL ); 781 lcl_tryReadConfigFlag( pLine, nLineLength, "object_test", &aDebugData.aDbgData.nTestFlags, DBG_TEST_MEM_XTOR ); 782 lcl_tryReadConfigFlag( pLine, nLineLength, "sys_alloc", &aDebugData.aDbgData.nTestFlags, DBG_TEST_MEM_SYSALLOC ); 783 lcl_tryReadConfigFlag( pLine, nLineLength, "leak_report", &aDebugData.aDbgData.nTestFlags, DBG_TEST_MEM_LEAKREPORT ); 784 785 lcl_tryReadHexByte( pLine, nLineLength, "init_byte", &aDebugData.aDbgData.bMemInit ); 786 lcl_tryReadHexByte( pLine, nLineLength, "bound_byte", &aDebugData.aDbgData.bMemBound ); 787 lcl_tryReadHexByte( pLine, nLineLength, "free_byte", &aDebugData.aDbgData.bMemFree ); 788 } 789 790 // elements of the [gui] section 791 if ( eCurrentSection == eGUI ) 792 { 793 lcl_tryReadConfigString( pLine, nLineLength, "debug_window_state", aDebugData.aDbgData.aDbgWinState, sizeof( aDebugData.aDbgData.aDbgWinState ) ); 794 } 795 796 // elements of the [objects] section 797 if ( eCurrentSection == eObjects ) 798 { 799 lcl_tryReadConfigFlag( pLine, nLineLength, "check_this", &aDebugData.aDbgData.nTestFlags, DBG_TEST_XTOR_THIS ); 800 lcl_tryReadConfigFlag( pLine, nLineLength, "check_function", &aDebugData.aDbgData.nTestFlags, DBG_TEST_XTOR_FUNC ); 801 lcl_tryReadConfigFlag( pLine, nLineLength, "check_exit", &aDebugData.aDbgData.nTestFlags, DBG_TEST_XTOR_EXIT ); 802 lcl_tryReadConfigFlag( pLine, nLineLength, "generate_report", &aDebugData.aDbgData.nTestFlags, DBG_TEST_XTOR_REPORT ); 803 lcl_tryReadConfigFlag( pLine, nLineLength, "trace", &aDebugData.aDbgData.nTestFlags, DBG_TEST_XTOR_TRACE ); 804 } 805 806 // elements of the [test] section 807 if ( eCurrentSection == eTest ) 808 { 809 lcl_tryReadConfigFlag( pLine, nLineLength, "profiling", &aDebugData.aDbgData.nTestFlags, DBG_TEST_PROFILING ); 810 lcl_tryReadConfigFlag( pLine, nLineLength, "resources", &aDebugData.aDbgData.nTestFlags, DBG_TEST_RESOURCE ); 811 lcl_tryReadConfigFlag( pLine, nLineLength, "dialog", &aDebugData.aDbgData.nTestFlags, DBG_TEST_DIALOG ); 812 lcl_tryReadConfigFlag( pLine, nLineLength, "bold_app_font", &aDebugData.aDbgData.nTestFlags, DBG_TEST_BOLDAPPFONT ); 813 } 814 815 pLine = pNextLine + strlen( FILE_LINEEND ); 816 } 817 818 FileClose( pIniFile ); 819 } 820 else 821 { 822 lcl_matchOutputChannel( getenv( "DBGSV_TRACE_OUT" ), &aDebugData.aDbgData.nTraceOut ); 823 lcl_matchOutputChannel( getenv( "DBGSV_WARNING_OUT" ), &aDebugData.aDbgData.nWarningOut ); 824 lcl_matchOutputChannel( getenv( "DBGSV_ERROR_OUT" ), &aDebugData.aDbgData.nErrorOut ); 825 826 } 827 828 getcwd( aCurPath, sizeof( aCurPath ) ); 829 830 // Daten initialisieren 831 if ( aDebugData.aDbgData.nTestFlags & DBG_TEST_XTOR ) 832 aDebugData.pXtorList = new PointerList; 833 if ( aDebugData.aDbgData.nTestFlags & DBG_TEST_PROFILING ) 834 aDebugData.pProfList = new PointerList; 835 } 836 837 return &aDebugData; 838 } 839 840 // ----------------------------------------------------------------------- 841 842 inline DebugData* ImplGetDebugData() 843 { 844 if ( !aDebugData.bInit ) 845 return GetDebugData(); 846 else 847 return &aDebugData; 848 } 849 850 // ----------------------------------------------------------------------- 851 852 static FILETYPE ImplDbgInitFile() 853 { 854 static sal_Bool bFileInit = sal_False; 855 856 sal_Char aBuf[4096]; 857 getcwd( aBuf, sizeof( aBuf ) ); 858 chdir( aCurPath ); 859 860 DebugData* pData = GetDebugData(); 861 FILETYPE pDebugFile; 862 863 if ( !bFileInit ) 864 { 865 bFileInit = sal_True; 866 867 if ( pData->aDbgData.bOverwrite ) 868 pDebugFile = FileOpen( pData->aDbgData.aDebugName, "w" ); 869 else 870 pDebugFile = FileOpen( pData->aDbgData.aDebugName, "a" ); 871 872 if ( pDebugFile ) 873 { 874 time_t nTime = time( 0 ); 875 tm* pTime; 876 #ifdef UNX 877 tm aTime; 878 pTime = localtime_r( &nTime, &aTime ); 879 #else 880 pTime = localtime( &nTime ); 881 #endif 882 883 // Header ausgeben 884 FilePrintF( pDebugFile, "******************************************************************************%s", FILE_LINEEND ); 885 FilePrintF( pDebugFile, "%s%s", pData->aDbgData.aDebugName, FILE_LINEEND ); 886 if ( pTime ) 887 FilePrintF( pDebugFile, "%s%s", asctime( pTime ), FILE_LINEEND ); 888 } 889 } 890 else 891 pDebugFile = FileOpen( pData->aDbgData.aDebugName, "a" ); 892 893 chdir( aBuf ); 894 895 return pDebugFile; 896 } 897 898 // ----------------------------------------------------------------------- 899 900 static void ImplDbgPrintFile( const sal_Char* pLine ) 901 { 902 FILETYPE pDebugFile = ImplDbgInitFile(); 903 904 if ( pDebugFile ) 905 { 906 FilePrintF( pDebugFile, "%s%s", pLine, FILE_LINEEND ); 907 FileClose( pDebugFile ); 908 } 909 } 910 911 // ----------------------------------------------------------------------- 912 913 static int ImplStrSearch( const sal_Char* pSearchStr, int nSearchLen, 914 const sal_Char* pStr, int nLen ) 915 { 916 int nPos = 0; 917 while ( nPos+nSearchLen <= nLen ) 918 { 919 if ( strncmp( pStr+nPos, pSearchStr, nSearchLen ) == 0 ) 920 return 1; 921 nPos++; 922 } 923 924 return 0; 925 } 926 927 // ----------------------------------------------------------------------- 928 929 static int ImplDbgFilter( const sal_Char* pFilter, const sal_Char* pMsg, 930 int bEmpty ) 931 { 932 int nStrLen = strlen( pFilter ); 933 if ( !nStrLen ) 934 return bEmpty; 935 936 int nMsgLen = strlen( pMsg ); 937 const sal_Char* pTok = pFilter; 938 int nTok = 0; 939 while ( pTok[nTok] ) 940 { 941 if ( pTok[nTok] == ';' ) 942 { 943 if ( nTok && ImplStrSearch( pTok, nTok, pMsg, nMsgLen ) ) 944 return sal_True; 945 946 pTok += nTok+1; 947 nTok = 0; 948 } 949 950 nTok++; 951 } 952 953 if ( nTok && ImplStrSearch( pTok, nTok, pMsg, nMsgLen ) ) 954 return sal_True; 955 else 956 return sal_False; 957 } 958 959 // ----------------------------------------------------------------------- 960 961 extern "C" 962 void SAL_CALL dbg_printOslDebugMessage( const sal_Char * pszFileName, sal_Int32 nLine, const sal_Char * pszMessage ) 963 { 964 DbgOut( pszMessage ? pszMessage : "assertion failed!", DBG_OUT_ERROR, pszFileName, (sal_uInt16)nLine ); 965 } 966 967 // ----------------------------------------------------------------------- 968 969 static void DebugInit() 970 { 971 bDbgImplInMain = sal_True; 972 ImplDbgInitLock(); 973 974 DebugData* pData = GetDebugData(); 975 if( pData->aDbgData.bHookOSLAssert && ! pData->bOslIsHooked ) 976 { 977 pData->pOldDebugMessageFunc = osl_setDetailedDebugMessageFunc( &dbg_printOslDebugMessage ); 978 pData->bOslIsHooked = true; 979 } 980 } 981 982 // ----------------------------------------------------------------------- 983 984 static void DebugDeInit() 985 { 986 DebugData* pData = GetDebugData(); 987 sal_uIntPtr i; 988 sal_uIntPtr nCount; 989 sal_uIntPtr nOldOut; 990 991 if( pData->bOslIsHooked ) 992 { 993 osl_setDetailedDebugMessageFunc( pData->pOldDebugMessageFunc ); 994 pData->bOslIsHooked = sal_False; 995 } 996 997 // Statistik-Ausgaben immer in File 998 nOldOut = pData->aDbgData.nTraceOut; 999 pData->aDbgData.nTraceOut = DBG_OUT_FILE; 1000 1001 // Xtor-Liste ausgeben 1002 if ( pData->pXtorList && pData->pXtorList->Count() && 1003 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_REPORT) ) 1004 { 1005 DbgOutf( "------------------------------------------------------------------------------" ); 1006 DbgOutf( "Object Report" ); 1007 DbgOutf( "------------------------------------------------------------------------------" ); 1008 DbgOutf( "%-27s : %-9s : %-9s : %-7s : %-3s : %-6s :", 1009 "XTor-List", "Ctor", "Dtor", "MaxInst", "St.", "Diff." ); 1010 DbgOutf( "----------------------------:-----------:-----------:---------:----:---------:" ); 1011 for( i = 0, nCount = pData->pXtorList->Count(); i < nCount; i++ ) 1012 { 1013 XtorType* pXtorData = (XtorType*)pData->pXtorList->Get( i ); 1014 if ( pXtorData->bTest ) 1015 { 1016 // Static-Objekte dazurechnen 1017 pXtorData->nDtorCalls += pXtorData->nStatics; 1018 if ( pXtorData->nStatics && (pXtorData->nDtorCalls > pXtorData->nCtorCalls) ) 1019 pXtorData->nDtorCalls = pXtorData->nCtorCalls; 1020 DbgOutf( "%-27s : %9lu : %9lu : %7lu : %3lu : %4lu %-1s :", 1021 pXtorData->aName, pXtorData->nCtorCalls, pXtorData->nDtorCalls, 1022 pXtorData->nMaxCount, pXtorData->nStatics, 1023 pXtorData->nCtorCalls - pXtorData->nDtorCalls, 1024 (pXtorData->nCtorCalls - pXtorData->nDtorCalls) ? "!" : " " ); 1025 } 1026 } 1027 DbgOutf( "==============================================================================" ); 1028 } 1029 1030 // Aufraeumen 1031 if ( pData->pXtorList ) 1032 { 1033 for( i = 0, nCount = pData->pXtorList->Count(); i < nCount; i++ ) 1034 { 1035 XtorType* pXtorData = (XtorType*)pData->pXtorList->Get( i ); 1036 delete pXtorData; 1037 } 1038 delete pData->pXtorList; 1039 pData->pXtorList = NULL; 1040 } 1041 1042 // Alles auf sal_False setzen, damit globale Variablen nicht das 1043 // System zum Abstuerzen bringt. Dabei muessen aber die 1044 // Memory-Flags erhalten bleiben, da sonst new/delete in globalen 1045 // Variablen abstuerzen, da die Pointeranpassung dann nicht mehr richtig 1046 // funktioniert 1047 pData->aDbgData.nTraceOut = nOldOut; 1048 pData->aDbgData.nTestFlags &= (DBG_TEST_MEM | DBG_TEST_PROFILING); 1049 pData->aDbgPrintUserChannels.clear(); 1050 pData->pDbgPrintTestTool = NULL; 1051 pData->pDbgPrintWindow = NULL; 1052 pData->pOldDebugMessageFunc = NULL; 1053 ImplDbgDeInitLock(); 1054 } 1055 1056 // ----------------------------------------------------------------------- 1057 1058 static void DebugGlobalDeInit() 1059 { 1060 DebugData* pData = GetDebugData(); 1061 sal_uIntPtr i; 1062 sal_uIntPtr nCount; 1063 sal_uIntPtr nOldOut; 1064 1065 // Statistik-Ausgaben immer in File 1066 nOldOut = pData->aDbgData.nTraceOut; 1067 pData->aDbgData.nTraceOut = DBG_OUT_FILE; 1068 1069 // Profileliste ausgeben 1070 if ( pData->pProfList && pData->pProfList->Count() ) 1071 { 1072 DbgOutf( "------------------------------------------------------------------------------" ); 1073 DbgOutf( "Profiling Report" ); 1074 DbgOutf( "------------------------------------------------------------------------------" ); 1075 DbgOutf( "%-25s : %-9s : %-6s : %-6s : %-6s : %-9s :", 1076 "Prof-List (ms)", "Time", "Min", "Max", "Ave", "Count" ); 1077 DbgOutf( "--------------------------:-----------:--------:--------:--------:-----------:" ); 1078 for( i = 0, nCount = pData->pProfList->Count(); i < nCount; i++ ) 1079 { 1080 ProfType* pProfData = (ProfType*)pData->pProfList->Get( i ); 1081 sal_uIntPtr nAve = pProfData->nTime / pProfData->nCount; 1082 DbgOutf( "%-25s : %9lu : %6lu : %6lu : %6lu : %9lu :", 1083 pProfData->aName, pProfData->nTime, 1084 pProfData->nMinTime, pProfData->nMaxTime, nAve, 1085 pProfData->nCount ); 1086 } 1087 DbgOutf( "==============================================================================" ); 1088 } 1089 1090 // Aufraeumen 1091 if ( pData->pProfList ) 1092 { 1093 for( i = 0, nCount = pData->pProfList->Count(); i < nCount; i++ ) 1094 { 1095 ProfType* pProfData = (ProfType*)pData->pProfList->Get( i ); 1096 delete pProfData; 1097 } 1098 delete pData->pProfList; 1099 pData->pProfList = NULL; 1100 } 1101 1102 #ifdef SV_MEMMGR 1103 DbgImpCheckMemoryDeInit(); 1104 #endif 1105 1106 // Profiling-Flags ausschalten 1107 pData->aDbgData.nTraceOut = nOldOut; 1108 pData->aDbgData.nTestFlags &= ~DBG_TEST_PROFILING; 1109 } 1110 1111 // ----------------------------------------------------------------------- 1112 1113 void ImpDbgOutfBuf( sal_Char* pBuf, const sal_Char* pFStr, ... ) 1114 { 1115 va_list pList; 1116 1117 va_start( pList, pFStr ); 1118 sal_Char aBuf[DBG_BUF_MAXLEN]; 1119 vsprintf( aBuf, pFStr, pList ); 1120 va_end( pList ); 1121 1122 strcat( pBuf, aBuf ); 1123 strcat( pBuf, "\n" ); 1124 } 1125 1126 // ----------------------------------------------------------------------- 1127 1128 static void DebugXTorInfo( sal_Char* pBuf ) 1129 { 1130 DebugData* pData = GetDebugData(); 1131 sal_uIntPtr i; 1132 sal_uIntPtr nCount; 1133 1134 // Xtor-Liste ausgeben 1135 if ( pData->pXtorList && pData->pXtorList->Count() && 1136 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_REPORT) ) 1137 { 1138 ImpDbgOutfBuf( pBuf, "------------------------------------------------------------------------------" ); 1139 ImpDbgOutfBuf( pBuf, "Object Report" ); 1140 ImpDbgOutfBuf( pBuf, "------------------------------------------------------------------------------" ); 1141 ImpDbgOutfBuf( pBuf, "%-27s : %-9s : %-9s : %-7s : %-3s : %-6s :", 1142 "XTor-List", "Ctor", "Dtor", "MaxInst", "St.", "Diff." ); 1143 ImpDbgOutfBuf( pBuf, "----------------------------:-----------:-----------:---------:----:---------:" ); 1144 for( i = 0, nCount = pData->pXtorList->Count(); i < nCount; i++ ) 1145 { 1146 XtorType* pXtorData = (XtorType*)pData->pXtorList->Get( i ); 1147 if ( pXtorData->bTest ) 1148 { 1149 ImpDbgOutfBuf( pBuf, "%-27s : %9lu : %9lu : %7lu : %3lu : %6lu :", 1150 pXtorData->aName, pXtorData->nCtorCalls, pXtorData->nDtorCalls, 1151 pXtorData->nMaxCount, pXtorData->nStatics, 1152 pXtorData->nCtorCalls - pXtorData->nDtorCalls ); 1153 } 1154 } 1155 ImpDbgOutfBuf( pBuf, "==============================================================================" ); 1156 ImpDbgOutfBuf( pBuf, "" ); 1157 } 1158 } 1159 1160 // ----------------------------------------------------------------------- 1161 sal_Bool ImplDbgFilterMessage( const sal_Char* pMsg ) 1162 { 1163 DebugData* pData = GetDebugData(); 1164 if ( !ImplDbgFilter( pData->aDbgData.aInclFilter, pMsg, sal_True ) ) 1165 return sal_True; 1166 if ( ImplDbgFilter( pData->aDbgData.aExclFilter, pMsg, sal_False ) ) 1167 return sal_True; 1168 return sal_False; 1169 } 1170 1171 // ----------------------------------------------------------------------- 1172 1173 void* DbgFunc( sal_uInt16 nAction, void* pParam ) 1174 { 1175 DebugData* pDebugData = ImplGetDebugData(); 1176 1177 if ( nAction == DBG_FUNC_GETDATA ) 1178 return (void*)&(pDebugData->aDbgData); 1179 else if ( nAction == DBG_FUNC_GETPRINTMSGBOX ) 1180 return (void*)(long)(pDebugData->pDbgPrintMsgBox); 1181 else if ( nAction == DBG_FUNC_FILTERMESSAGE ) 1182 if ( ImplDbgFilterMessage( (const sal_Char*) pParam ) ) 1183 return (void*) -1; 1184 else 1185 return (void*) 0; // aka NULL 1186 else 1187 1188 { 1189 switch ( nAction ) 1190 { 1191 case DBG_FUNC_DEBUGSTART: 1192 DebugInit(); 1193 break; 1194 1195 case DBG_FUNC_DEBUGEND: 1196 DebugDeInit(); 1197 break; 1198 1199 case DBG_FUNC_GLOBALDEBUGEND: 1200 DebugGlobalDeInit(); 1201 break; 1202 1203 case DBG_FUNC_SETPRINTMSGBOX: 1204 pDebugData->pDbgPrintMsgBox = (DbgPrintLine)(long)pParam; 1205 break; 1206 1207 case DBG_FUNC_SETPRINTWINDOW: 1208 pDebugData->pDbgPrintWindow = (DbgPrintLine)(long)pParam; 1209 break; 1210 1211 case DBG_FUNC_SETPRINTTESTTOOL: 1212 pDebugData->pDbgPrintTestTool = (DbgPrintLine)(long)pParam; 1213 break; 1214 1215 case DBG_FUNC_SET_ABORT: 1216 pDebugData->pDbgAbort = (DbgPrintLine)(long)pParam; 1217 break; 1218 1219 case DBG_FUNC_SAVEDATA: 1220 { 1221 const DbgData* pData = static_cast< const DbgData* >( pParam ); 1222 1223 sal_Char aBuf[ 4096 ]; 1224 DbgGetDbgFileName( aBuf, sizeof( aBuf ) ); 1225 FILETYPE pIniFile = FileOpen( aBuf, "w" ); 1226 if ( pIniFile == NULL ) 1227 break; 1228 1229 lcl_startSection( pIniFile, eOutput ); 1230 lcl_writeConfigString( pIniFile, "log_file", pData->aDebugName ); 1231 lcl_writeConfigBoolean( pIniFile, "overwrite", pData->bOverwrite ); 1232 lcl_writeConfigString( pIniFile, "include", pData->aInclFilter ); 1233 lcl_writeConfigString( pIniFile, "exclude", pData->aExclFilter ); 1234 lcl_writeConfigString( pIniFile, "include_class", pData->aInclClassFilter ); 1235 lcl_writeConfigString( pIniFile, "exclude_class", pData->aExclClassFilter ); 1236 lcl_writeConfigOutChannel( pIniFile, "trace", pData->nTraceOut ); 1237 lcl_writeConfigOutChannel( pIniFile, "warning", pData->nWarningOut ); 1238 lcl_writeConfigOutChannel( pIniFile, "error", pData->nErrorOut ); 1239 lcl_writeConfigBoolean( pIniFile, "oslhook", pData->bHookOSLAssert ); 1240 1241 lcl_lineFeed( pIniFile ); 1242 lcl_startSection( pIniFile, eMemory ); 1243 lcl_writeConfigFlag( pIniFile, "initialize", pData->nTestFlags, DBG_TEST_MEM_INIT ); 1244 lcl_writeConfigFlag( pIniFile, "overwrite", pData->nTestFlags, DBG_TEST_MEM_OVERWRITE ); 1245 lcl_writeConfigFlag( pIniFile, "overwrite_free", pData->nTestFlags, DBG_TEST_MEM_OVERWRITEFREE ); 1246 lcl_writeConfigFlag( pIniFile, "pointer", pData->nTestFlags, DBG_TEST_MEM_POINTER ); 1247 lcl_writeConfigFlag( pIniFile, "report", pData->nTestFlags, DBG_TEST_MEM_REPORT ); 1248 lcl_writeConfigFlag( pIniFile, "trace", pData->nTestFlags, DBG_TEST_MEM_TRACE ); 1249 lcl_writeConfigFlag( pIniFile, "new_and_delete", pData->nTestFlags, DBG_TEST_MEM_NEWDEL ); 1250 lcl_writeConfigFlag( pIniFile, "object_test", pData->nTestFlags, DBG_TEST_MEM_XTOR ); 1251 lcl_writeConfigFlag( pIniFile, "sys_alloc", pData->nTestFlags, DBG_TEST_MEM_SYSALLOC ); 1252 lcl_writeConfigFlag( pIniFile, "leak_report", pData->nTestFlags, DBG_TEST_MEM_LEAKREPORT ); 1253 1254 lcl_lineFeed( pIniFile ); 1255 lcl_writeHexByte( pIniFile, "init_byte", pData->bMemInit ); 1256 lcl_writeHexByte( pIniFile, "bound_byte", pData->bMemBound ); 1257 lcl_writeHexByte( pIniFile, "free_byte", pData->bMemFree ); 1258 1259 lcl_lineFeed( pIniFile ); 1260 lcl_startSection( pIniFile, eGUI ); 1261 lcl_writeConfigString( pIniFile, "debug_window_state", pData->aDbgWinState ); 1262 1263 lcl_lineFeed( pIniFile ); 1264 lcl_startSection( pIniFile, eObjects ); 1265 lcl_writeConfigFlag( pIniFile, "check_this", pData->nTestFlags, DBG_TEST_XTOR_THIS ); 1266 lcl_writeConfigFlag( pIniFile, "check_function", pData->nTestFlags, DBG_TEST_XTOR_FUNC ); 1267 lcl_writeConfigFlag( pIniFile, "check_exit", pData->nTestFlags, DBG_TEST_XTOR_EXIT ); 1268 lcl_writeConfigFlag( pIniFile, "generate_report", pData->nTestFlags, DBG_TEST_XTOR_REPORT ); 1269 lcl_writeConfigFlag( pIniFile, "trace", pData->nTestFlags, DBG_TEST_XTOR_TRACE ); 1270 1271 lcl_lineFeed( pIniFile ); 1272 lcl_startSection( pIniFile, eTest ); 1273 lcl_writeConfigFlag( pIniFile, "profiling", pData->nTestFlags, DBG_TEST_PROFILING ); 1274 lcl_writeConfigFlag( pIniFile, "resources", pData->nTestFlags, DBG_TEST_RESOURCE ); 1275 lcl_writeConfigFlag( pIniFile, "dialog", pData->nTestFlags, DBG_TEST_DIALOG ); 1276 lcl_writeConfigFlag( pIniFile, "bold_app_font", pData->nTestFlags, DBG_TEST_BOLDAPPFONT ); 1277 1278 FileClose( pIniFile ); 1279 } 1280 break; 1281 1282 case DBG_FUNC_MEMTEST: 1283 #ifdef SV_MEMMGR 1284 DbgImpCheckMemory( pParam ); 1285 #endif 1286 break; 1287 1288 case DBG_FUNC_XTORINFO: 1289 DebugXTorInfo( (sal_Char*)pParam ); 1290 break; 1291 1292 case DBG_FUNC_MEMINFO: 1293 #ifdef SV_MEMMGR 1294 DbgImpMemoryInfo( (sal_Char*)pParam ); 1295 #endif 1296 break; 1297 1298 case DBG_FUNC_COREDUMP: 1299 ImplCoreDump(); 1300 break; 1301 1302 case DBG_FUNC_ALLERROROUT: 1303 return (void*)(sal_uIntPtr)sal_True; 1304 1305 case DBG_FUNC_SETTESTSOLARMUTEX: 1306 pDebugData->pDbgTestSolarMutex = (DbgTestSolarMutexProc)(long)pParam; 1307 break; 1308 1309 case DBG_FUNC_TESTSOLARMUTEX: 1310 if ( pDebugData->pDbgTestSolarMutex ) 1311 pDebugData->pDbgTestSolarMutex(); 1312 break; 1313 1314 case DBG_FUNC_PRINTFILE: 1315 ImplDbgPrintFile( (const sal_Char*)pParam ); 1316 break; 1317 case DBG_FUNC_UPDATEOSLHOOK: 1318 { 1319 const DbgData* pData = static_cast< const DbgData* >( pParam ); 1320 pDebugData->aDbgData.bHookOSLAssert = pData->bHookOSLAssert; 1321 if( pDebugData->bOslIsHooked && ! pData->bHookOSLAssert ) 1322 { 1323 osl_setDetailedDebugMessageFunc( pDebugData->pOldDebugMessageFunc ); 1324 pDebugData->bOslIsHooked = sal_False; 1325 } 1326 else if( ! pDebugData->bOslIsHooked && pData->bHookOSLAssert ) 1327 { 1328 pDebugData->pOldDebugMessageFunc = osl_setDetailedDebugMessageFunc( &dbg_printOslDebugMessage ); 1329 pDebugData->bOslIsHooked = sal_True; 1330 } 1331 } 1332 break; 1333 } 1334 1335 return NULL; 1336 } 1337 } 1338 1339 // ----------------------------------------------------------------------- 1340 1341 DbgChannelId DbgRegisterUserChannel( DbgPrintLine pProc ) 1342 { 1343 DebugData* pData = ImplGetDebugData(); 1344 pData->aDbgPrintUserChannels.push_back( pProc ); 1345 return (DbgChannelId)( pData->aDbgPrintUserChannels.size() - 1 + DBG_OUT_USER_CHANNEL_0 ); 1346 } 1347 1348 // ----------------------------------------------------------------------- 1349 1350 void DbgProf( sal_uInt16 nAction, DbgDataType* pDbgData ) 1351 { 1352 // Ueberhaupt Profiling-Test an 1353 DebugData* pData = ImplGetDebugData(); 1354 1355 if ( !(pData->aDbgData.nTestFlags & DBG_TEST_PROFILING) ) 1356 return; 1357 1358 sal_Char aBuf[DBG_BUF_MAXLEN]; 1359 ProfType* pProfData = (ProfType*)pDbgData->pData; 1360 sal_uIntPtr nTime; 1361 if ( (nAction != DBG_PROF_START) && !pProfData ) 1362 { 1363 strcpy( aBuf, DbgError_ProfEnd1 ); 1364 strcat( aBuf, pDbgData->pName ); 1365 DbgError( aBuf ); 1366 return; 1367 } 1368 1369 switch ( nAction ) 1370 { 1371 case DBG_PROF_START: 1372 if ( !pDbgData->pData ) 1373 { 1374 pDbgData->pData = (void*)new ProfType; 1375 pProfData = (ProfType*)pDbgData->pData; 1376 strncpy( pProfData->aName, pDbgData->pName, DBG_MAXNAME ); 1377 pProfData->aName[DBG_MAXNAME] = '\0'; 1378 pProfData->nCount = 0; 1379 pProfData->nTime = 0; 1380 pProfData->nMinTime = 0xFFFFFFFF; 1381 pProfData->nMaxTime = 0; 1382 pProfData->nStart = 0xFFFFFFFF; 1383 pProfData->nContinueTime = 0; 1384 pProfData->nContinueStart = 0xFFFFFFFF; 1385 pData->pProfList->Add( (void*)pProfData ); 1386 } 1387 1388 if ( pProfData->nStart == 0xFFFFFFFF ) 1389 { 1390 pProfData->nStart = ImplGetPerfTime(); 1391 pProfData->nCount++; 1392 } 1393 break; 1394 1395 case DBG_PROF_STOP: 1396 nTime = ImplGetPerfTime(); 1397 1398 if ( pProfData->nStart == 0xFFFFFFFF ) 1399 { 1400 DbgError( DbgError_ProfEnd1 ); 1401 return; 1402 } 1403 1404 if ( pProfData->nContinueStart != 0xFFFFFFFF ) 1405 { 1406 pProfData->nContinueTime += ImplGetPerfTime() - pProfData->nContinueStart; 1407 pProfData->nContinueStart = 0xFFFFFFFF; 1408 } 1409 1410 nTime -= pProfData->nStart; 1411 nTime -= pProfData->nContinueTime; 1412 1413 if ( nTime < pProfData->nMinTime ) 1414 pProfData->nMinTime = nTime; 1415 1416 if ( nTime > pProfData->nMaxTime ) 1417 pProfData->nMaxTime = nTime; 1418 1419 pProfData->nTime += nTime; 1420 1421 pProfData->nStart = 0xFFFFFFFF; 1422 pProfData->nContinueTime = 0; 1423 pProfData->nContinueStart = 0xFFFFFFFF; 1424 break; 1425 1426 case DBG_PROF_CONTINUE: 1427 if ( pProfData->nContinueStart != 0xFFFFFFFF ) 1428 { 1429 pProfData->nContinueTime += ImplGetPerfTime() - pProfData->nContinueStart; 1430 pProfData->nContinueStart = 0xFFFFFFFF; 1431 } 1432 break; 1433 1434 case DBG_PROF_PAUSE: 1435 if ( pProfData->nContinueStart == 0xFFFFFFFF ) 1436 pProfData->nContinueStart = ImplGetPerfTime(); 1437 break; 1438 } 1439 } 1440 1441 // ----------------------------------------------------------------------- 1442 1443 void DbgXtor( DbgDataType* pDbgData, sal_uInt16 nAction, const void* pThis, 1444 DbgUsr fDbgUsr ) 1445 { 1446 DebugData* pData = ImplGetDebugData(); 1447 1448 // Verbindung zu Debug-Memory-Manager testen 1449 #ifdef SV_MEMMGR 1450 if ( pData->aDbgData.nTestFlags & DBG_TEST_MEM_XTOR ) 1451 DbgImpCheckMemory(); 1452 #endif 1453 1454 // Schnell-Test 1455 if ( !(pData->aDbgData.nTestFlags & DBG_TEST_XTOR) ) 1456 return; 1457 1458 XtorType* pXtorData = (XtorType*)pDbgData->pData; 1459 if ( !pXtorData ) 1460 { 1461 pDbgData->pData = (void*)new XtorType; 1462 pXtorData = (XtorType*)pDbgData->pData; 1463 strncpy( pXtorData->aName, pDbgData->pName, DBG_MAXNAME ); 1464 pXtorData->aName[DBG_MAXNAME] = '\0'; 1465 pXtorData->nCtorCalls = 0; 1466 pXtorData->nDtorCalls = 0; 1467 pXtorData->nMaxCount = 0; 1468 pXtorData->nStatics = 0; 1469 pXtorData->bTest = sal_True; 1470 pData->pXtorList->Add( (void*)pXtorData ); 1471 1472 if ( !ImplDbgFilter( pData->aDbgData.aInclClassFilter, pXtorData->aName, sal_True ) ) 1473 pXtorData->bTest = sal_False; 1474 if ( ImplDbgFilter( pData->aDbgData.aExclClassFilter, pXtorData->aName, sal_False ) ) 1475 pXtorData->bTest = sal_False; 1476 } 1477 if ( !pXtorData->bTest ) 1478 return; 1479 1480 sal_Char aBuf[DBG_BUF_MAXLEN]; 1481 sal_uInt16 nAct = nAction & ~DBG_XTOR_DTOROBJ; 1482 1483 // Trace (Enter) 1484 if ( (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_TRACE) && 1485 !(nAction & DBG_XTOR_DTOROBJ) ) 1486 { 1487 if ( nAct != DBG_XTOR_CHKOBJ ) 1488 { 1489 if ( nAct == DBG_XTOR_CTOR ) 1490 strcpy( aBuf, DbgTrace_EnterCtor ); 1491 else if ( nAct == DBG_XTOR_DTOR ) 1492 strcpy( aBuf, DbgTrace_EnterDtor ); 1493 else 1494 strcpy( aBuf, DbgTrace_EnterMeth ); 1495 strcat( aBuf, pDbgData->pName ); 1496 DbgTrace( aBuf ); 1497 } 1498 } 1499 1500 // Sind noch Xtor-Tests als Trace an 1501 if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXTRA ) 1502 { 1503 // DBG_CTOR-Aufruf vor allen anderen DBG_XTOR-Aufrufen 1504 if ( ((nAction & ~DBG_XTOR_DTOROBJ) != DBG_XTOR_CTOR) && !pDbgData->pData ) 1505 { 1506 strcpy( aBuf, DbgError_Xtor1 ); 1507 strcat( aBuf, pDbgData->pName ); 1508 DbgError( aBuf ); 1509 return; 1510 } 1511 1512 // Testen, ob This-Pointer gueltig 1513 if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_THIS ) 1514 { 1515 if ( (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) || 1516 !(nAction & DBG_XTOR_DTOROBJ) ) 1517 { 1518 // This-Pointer == NULL 1519 if ( !pThis ) 1520 { 1521 strcpy( aBuf, DbgError_CtorDtor1 ); 1522 strcat( aBuf, pDbgData->pName ); 1523 DbgError( aBuf ); 1524 return; 1525 } 1526 1527 if ( (nAction & ~DBG_XTOR_DTOROBJ) != DBG_XTOR_CTOR ) 1528 { 1529 if ( !pXtorData->aThisList.IsIn( pThis ) ) 1530 { 1531 sprintf( aBuf, DbgError_CtorDtor2, pThis ); 1532 strcat( aBuf, pDbgData->pName ); 1533 DbgError( aBuf ); 1534 } 1535 } 1536 } 1537 } 1538 1539 // Function-Test durchfuehren und Verwaltungsdaten updaten 1540 const sal_Char* pMsg = NULL; 1541 switch ( nAction & ~DBG_XTOR_DTOROBJ ) 1542 { 1543 case DBG_XTOR_CTOR: 1544 if ( nAction & DBG_XTOR_DTOROBJ ) 1545 { 1546 if ( fDbgUsr && 1547 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) && 1548 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) ) 1549 pMsg = fDbgUsr( pThis ); 1550 } 1551 else 1552 { 1553 pXtorData->nCtorCalls++; 1554 if ( !bDbgImplInMain ) 1555 pXtorData->nStatics++; 1556 if ( (pXtorData->nCtorCalls-pXtorData->nDtorCalls) > pXtorData->nMaxCount ) 1557 pXtorData->nMaxCount = pXtorData->nCtorCalls - pXtorData->nDtorCalls; 1558 1559 if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_THIS ) 1560 pXtorData->aThisList.Add( pThis ); 1561 } 1562 break; 1563 1564 case DBG_XTOR_DTOR: 1565 if ( nAction & DBG_XTOR_DTOROBJ ) 1566 { 1567 pXtorData->nDtorCalls++; 1568 if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_THIS ) 1569 pXtorData->aThisList.Remove( pThis ); 1570 } 1571 else 1572 { 1573 if ( fDbgUsr && 1574 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) ) 1575 pMsg = fDbgUsr( pThis ); 1576 } 1577 break; 1578 1579 case DBG_XTOR_CHKTHIS: 1580 case DBG_XTOR_CHKOBJ: 1581 if ( nAction & DBG_XTOR_DTOROBJ ) 1582 { 1583 if ( fDbgUsr && 1584 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) && 1585 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) ) 1586 pMsg = fDbgUsr( pThis ); 1587 } 1588 else 1589 { 1590 if ( fDbgUsr && 1591 (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) ) 1592 pMsg = fDbgUsr( pThis ); 1593 } 1594 break; 1595 } 1596 1597 // Gegebenenfalls Fehlermeldung ausgeben 1598 if ( pMsg ) 1599 { 1600 sprintf( aBuf, DbgError_CtorDtor3, pThis ); 1601 strcat( aBuf, pDbgData->pName ); 1602 strcat( aBuf, ": \n" ); 1603 strcat( aBuf, pMsg ); 1604 DbgError( aBuf ); 1605 } 1606 } 1607 1608 // Trace (Leave) 1609 if ( (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_TRACE) && 1610 (nAction & DBG_XTOR_DTOROBJ) ) 1611 { 1612 if ( nAct != DBG_XTOR_CHKOBJ ) 1613 { 1614 if ( nAct == DBG_XTOR_CTOR ) 1615 strcpy( aBuf, DbgTrace_LeaveCtor ); 1616 else if ( nAct == DBG_XTOR_DTOR ) 1617 strcpy( aBuf, DbgTrace_LeaveDtor ); 1618 else 1619 strcpy( aBuf, DbgTrace_LeaveMeth ); 1620 strcat( aBuf, pDbgData->pName ); 1621 DbgTrace( aBuf ); 1622 } 1623 } 1624 } 1625 1626 // ----------------------------------------------------------------------- 1627 1628 void DbgOut( const sal_Char* pMsg, sal_uInt16 nDbgOut, const sal_Char* pFile, sal_uInt16 nLine ) 1629 { 1630 static sal_Bool bIn = sal_False; 1631 if ( bIn ) 1632 return; 1633 bIn = sal_True; 1634 1635 DebugData* pData = GetDebugData(); 1636 sal_Char const * pStr; 1637 sal_uIntPtr nOut; 1638 int nBufLen = 0; 1639 1640 if ( nDbgOut == DBG_OUT_ERROR ) 1641 { 1642 nOut = pData->aDbgData.nErrorOut; 1643 pStr = "Error: "; 1644 if ( pData->aDbgData.nErrorOut == DBG_OUT_FILE ) 1645 DbgDebugBeep(); 1646 } 1647 else if ( nDbgOut == DBG_OUT_WARNING ) 1648 { 1649 nOut = pData->aDbgData.nWarningOut; 1650 pStr = "Warning: "; 1651 } 1652 else 1653 { 1654 nOut = pData->aDbgData.nTraceOut; 1655 pStr = NULL; 1656 } 1657 1658 if ( nOut == DBG_OUT_NULL ) 1659 { 1660 bIn = sal_False; 1661 return; 1662 } 1663 1664 if ( ImplDbgFilterMessage( pMsg ) ) 1665 { 1666 bIn = sal_False; 1667 return; 1668 } 1669 1670 ImplDbgLock(); 1671 1672 sal_Char aBufOut[DBG_BUF_MAXLEN]; 1673 if ( pStr ) 1674 { 1675 strcpy( aBufOut, pStr ); 1676 nBufLen = strlen( pStr ); 1677 } 1678 else 1679 aBufOut[0] = '\0'; 1680 1681 int nMsgLen = strlen( pMsg ); 1682 if ( nBufLen+nMsgLen > DBG_BUF_MAXLEN ) 1683 { 1684 int nCopyLen = DBG_BUF_MAXLEN-nBufLen-3; 1685 strncpy( &(aBufOut[nBufLen]), pMsg, nCopyLen ); 1686 strcpy( &(aBufOut[nBufLen+nCopyLen]), "..." ); 1687 } 1688 else 1689 strcpy( &(aBufOut[nBufLen]), pMsg ); 1690 1691 if ( pFile && nLine && (nBufLen+nMsgLen < DBG_BUF_MAXLEN) ) 1692 { 1693 if ( nOut == DBG_OUT_MSGBOX ) 1694 strcat( aBufOut, "\n" ); 1695 else 1696 strcat( aBufOut, " " ); 1697 strcat( aBufOut, "From File " ); 1698 strcat( aBufOut, pFile ); 1699 strcat( aBufOut, " at Line " ); 1700 1701 // Line in String umwandeln und dranhaengen 1702 sal_Char aLine[9]; 1703 sal_Char* pLine = &aLine[7]; 1704 sal_uInt16 i; 1705 memset( aLine, 0, sizeof( aLine ) ); 1706 do 1707 { 1708 i = nLine % 10; 1709 pLine--; 1710 *(pLine) = (sal_Char)i + 48; 1711 nLine /= 10; 1712 } 1713 while ( nLine ); 1714 strcat( aBufOut, pLine ); 1715 } 1716 1717 if ( ( nOut >= DBG_OUT_USER_CHANNEL_0 ) && ( nOut - DBG_OUT_USER_CHANNEL_0 < pData->aDbgPrintUserChannels.size() ) ) 1718 { 1719 DbgPrintLine pPrinter = pData->aDbgPrintUserChannels[ nOut - DBG_OUT_USER_CHANNEL_0 ]; 1720 if ( pPrinter ) 1721 pPrinter( aBufOut ); 1722 else 1723 nOut = DBG_OUT_DEBUGGER; 1724 } 1725 1726 if ( nOut == DBG_OUT_ABORT ) 1727 { 1728 if ( pData->pDbgAbort != NULL ) 1729 pData->pDbgAbort( aBufOut ); 1730 abort(); 1731 } 1732 1733 if ( nOut == DBG_OUT_DEBUGGER ) 1734 { 1735 if ( !ImplActivateDebugger( aBufOut ) ) 1736 nOut = DBG_OUT_TESTTOOL; 1737 } 1738 1739 if ( nOut == DBG_OUT_TESTTOOL ) 1740 { 1741 if ( pData->pDbgPrintTestTool ) 1742 pData->pDbgPrintTestTool( aBufOut ); 1743 else 1744 nOut = DBG_OUT_MSGBOX; 1745 } 1746 1747 if ( nOut == DBG_OUT_MSGBOX ) 1748 { 1749 if ( pData->pDbgPrintMsgBox ) 1750 pData->pDbgPrintMsgBox( aBufOut ); 1751 else 1752 nOut = DBG_OUT_WINDOW; 1753 } 1754 1755 if ( nOut == DBG_OUT_WINDOW ) 1756 { 1757 if ( pData->pDbgPrintWindow ) 1758 pData->pDbgPrintWindow( aBufOut ); 1759 else 1760 nOut = DBG_OUT_FILE; 1761 } 1762 1763 switch ( nOut ) 1764 { 1765 case DBG_OUT_SHELL: 1766 DbgPrintShell( aBufOut ); 1767 break; 1768 case DBG_OUT_FILE: 1769 ImplDbgPrintFile( aBufOut ); 1770 break; 1771 } 1772 1773 ImplDbgUnlock(); 1774 1775 bIn = sal_False; 1776 } 1777 1778 void DbgPrintShell(char const * message) { 1779 fprintf(stderr, "%s\n", message); 1780 #if defined WNT 1781 OutputDebugStringA(message); 1782 #endif 1783 } 1784 1785 // ----------------------------------------------------------------------- 1786 1787 void DbgOutTypef( sal_uInt16 nDbgOut, const sal_Char* pFStr, ... ) 1788 { 1789 va_list pList; 1790 1791 va_start( pList, pFStr ); 1792 sal_Char aBuf[DBG_BUF_MAXLEN]; 1793 vsprintf( aBuf, pFStr, pList ); 1794 va_end( pList ); 1795 1796 DbgOut( aBuf, nDbgOut ); 1797 } 1798 1799 // ----------------------------------------------------------------------- 1800 1801 void DbgOutf( const sal_Char* pFStr, ... ) 1802 { 1803 va_list pList; 1804 1805 va_start( pList, pFStr ); 1806 sal_Char aBuf[DBG_BUF_MAXLEN]; 1807 vsprintf( aBuf, pFStr, pList ); 1808 va_end( pList ); 1809 1810 DbgOut( aBuf ); 1811 } 1812 1813 // ======================================================================= 1814 1815 #else 1816 1817 void* DbgFunc( sal_uInt16, void* ) { return NULL; } 1818 1819 void DbgProf( sal_uInt16, DbgDataType* ) {} 1820 void DbgXtor( DbgDataType*, sal_uInt16, const void*, DbgUsr ) {} 1821 1822 void DbgOut( const sal_Char*, sal_uInt16, const sal_Char*, sal_uInt16 ) {} 1823 void DbgOutTypef( sal_uInt16, const sal_Char*, ... ) {} 1824 void DbgOutf( const sal_Char*, ... ) {} 1825 1826 #endif 1827