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