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:
PointerList()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;
Count() const114 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
DebugDataDebugData161 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
ImplDbgInitLock()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
ImplDbgDeInitLock()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
ImplDbgLock()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
ImplDbgUnlock()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
ImplActivateDebugger(const sal_Char * pMsg)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
ImplCoreDump()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
ImplGetPerfTime()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
lcl_lineFeed(FILETYPE _pFile)360 void lcl_lineFeed( FILETYPE _pFile )
361 {
362 FilePrintF( _pFile, "%s", FILE_LINEEND );
363 }
364
lcl_getSectionName(ConfigSection _eSection)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
lcl_getSectionFromName(const sal_Char * _pSectionName,size_t _nSectionNameLength)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
lcl_startSection(FILETYPE _pFile,ConfigSection _eSection)397 void lcl_startSection( FILETYPE _pFile, ConfigSection _eSection )
398 {
399 FilePrintF( _pFile, "[%s]%s", lcl_getSectionName( _eSection ), FILE_LINEEND );
400 }
401
lcl_writeConfigString(FILETYPE _pFile,const sal_Char * _pKeyName,const sal_Char * _pValue)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
lcl_writeConfigBoolean(FILETYPE _pFile,const sal_Char * _pKeyName,bool _bValue)407 void lcl_writeConfigBoolean( FILETYPE _pFile, const sal_Char* _pKeyName, bool _bValue )
408 {
409 lcl_writeConfigString( _pFile, _pKeyName, _bValue ? "1" : "0" );
410 }
411
lcl_writeConfigFlag(FILETYPE _pFile,const sal_Char * _pKeyName,sal_uIntPtr _nAllFlags,sal_uIntPtr _nCheckFlag)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
lcl_writeConfigOutChannel(FILETYPE _pFile,const sal_Char * _pKeyName,sal_uIntPtr _nValue)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 }
lcl_writeHexByte(FILETYPE _pFile,const sal_Char * _pKeyName,sal_uInt8 _nValue)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 }
lcl_isConfigSection(const sal_Char * _pLine,size_t _nLineLen)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 }
lcl_isConfigKey(const sal_Char * _pLine,size_t _nLineLen,const sal_Char * _pKeyName)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 }
lcl_tryReadConfigString(const sal_Char * _pLine,size_t _nLineLen,const sal_Char * _pKeyName,sal_Char * _pValue,size_t _nValueLen)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 }
lcl_tryReadConfigBoolean(const sal_Char * _pLine,size_t _nLineLen,const sal_Char * _pKeyName,sal_uIntPtr * _out_pnValue)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 }
lcl_matchOutputChannel(sal_Char const * i_buffer,sal_uIntPtr * o_value)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 }
lcl_tryReadOutputChannel(const sal_Char * _pLine,size_t _nLineLen,const sal_Char * _pKeyName,sal_uIntPtr * _out_pnValue)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 }
lcl_tryReadConfigFlag(const sal_Char * _pLine,size_t _nLineLen,const sal_Char * _pKeyName,sal_uIntPtr * _out_pnAllFlags,sal_uIntPtr _nCheckFlag)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 }
lcl_tryReadHexByte(const sal_Char * _pLine,size_t _nLineLen,const sal_Char * _pKeyName,sal_uInt8 * _out_pnValue)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
~PointerList()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
Add(const void * p)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
Remove(const void * p)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
Get(sal_uIntPtr nPos) const611 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
IsIn(const void * p) const641 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
DbgGetDbgFileName(sal_Char * pStr,sal_Int32 nMaxLen)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
DbgGetLogFileName(sal_Char * pStr)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
DbgDebugBeep()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
GetDebugData()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
ImplGetDebugData()838 inline DebugData* ImplGetDebugData()
839 {
840 if ( !aDebugData.bInit )
841 return GetDebugData();
842 else
843 return &aDebugData;
844 }
845
846 // -----------------------------------------------------------------------
847
ImplDbgInitFile()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
ImplDbgPrintFile(const sal_Char * pLine)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
ImplStrSearch(const sal_Char * pSearchStr,int nSearchLen,const sal_Char * pStr,int nLen)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
ImplDbgFilter(const sal_Char * pFilter,const sal_Char * pMsg,int bEmpty)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"
dbg_printOslDebugMessage(const sal_Char * pszFileName,sal_Int32 nLine,const sal_Char * pszMessage)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
DebugInit()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
DebugDeInit()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
DebugGlobalDeInit()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
ImpDbgOutfBuf(sal_Char * pBuf,const sal_Char * pFStr,...)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
DebugXTorInfo(sal_Char * pBuf)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 // -----------------------------------------------------------------------
ImplDbgFilterMessage(const sal_Char * pMsg)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
DbgFunc(sal_uInt16 nAction,void * pParam)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*)(sal_IntPtr)(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)(sal_IntPtr)pParam;
1201 break;
1202
1203 case DBG_FUNC_SETPRINTWINDOW:
1204 pDebugData->pDbgPrintWindow = (DbgPrintLine)(sal_IntPtr)pParam;
1205 break;
1206
1207 case DBG_FUNC_SETPRINTTESTTOOL:
1208 pDebugData->pDbgPrintTestTool = (DbgPrintLine)(sal_IntPtr)pParam;
1209 break;
1210
1211 case DBG_FUNC_SET_ABORT:
1212 pDebugData->pDbgAbort = (DbgPrintLine)(sal_IntPtr)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)(sal_IntPtr)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
DbgRegisterUserChannel(DbgPrintLine pProc)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
DbgProf(sal_uInt16 nAction,DbgDataType * pDbgData)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
DbgXtor(DbgDataType * pDbgData,sal_uInt16 nAction,const void * pThis,DbgUsr fDbgUsr)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
DbgOut(const sal_Char * pMsg,sal_uInt16 nDbgOut,const sal_Char * pFile,sal_uInt16 nLine)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
DbgPrintShell(char const * message)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
DbgOutTypef(sal_uInt16 nDbgOut,const sal_Char * pFStr,...)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
DbgOutf(const sal_Char * pFStr,...)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
DbgFunc(sal_uInt16,void *)1813 void* DbgFunc( sal_uInt16, void* ) { return NULL; }
1814
DbgProf(sal_uInt16,DbgDataType *)1815 void DbgProf( sal_uInt16, DbgDataType* ) {}
DbgXtor(DbgDataType *,sal_uInt16,const void *,DbgUsr)1816 void DbgXtor( DbgDataType*, sal_uInt16, const void*, DbgUsr ) {}
1817
DbgOut(const sal_Char *,sal_uInt16,const sal_Char *,sal_uInt16)1818 void DbgOut( const sal_Char*, sal_uInt16, const sal_Char*, sal_uInt16 ) {}
DbgOutTypef(sal_uInt16,const sal_Char *,...)1819 void DbgOutTypef( sal_uInt16, const sal_Char*, ... ) {}
DbgOutf(const sal_Char *,...)1820 void DbgOutf( const sal_Char*, ... ) {}
1821
1822 #endif
1823