xref: /trunk/main/tools/source/debug/debug.cxx (revision f419839f)
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