2010-10-14 08:27:31 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2012-07-11 09:51:50 +01:00
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following license notice:
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
|
|
* with this work for additional information regarding copyright
|
|
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
|
|
*/
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2012-12-27 13:37:20 +02:00
|
|
|
#if defined (UNX) || defined (__GNUC__)
|
2000-09-18 16:07:07 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#else
|
|
|
|
#include <direct.h>
|
|
|
|
#endif
|
|
|
|
|
2011-04-14 22:48:29 -07:00
|
|
|
#include <errno.h>
|
2000-09-18 16:07:07 +00:00
|
|
|
#include <time.h>
|
2002-03-18 17:46:56 +00:00
|
|
|
#include <cstdarg> // combinations
|
2000-09-18 16:07:07 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#if defined ( WNT )
|
2011-03-25 23:57:35 +01:00
|
|
|
#include <windows.h>
|
2007-09-06 13:14:46 +00:00
|
|
|
#endif
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2013-10-09 19:23:35 +02:00
|
|
|
#include "com/sun/star/task/ErrorCodeIOException.hpp"
|
2007-06-27 21:09:41 +00:00
|
|
|
#include <tools/debug.hxx>
|
2006-02-28 09:31:44 +00:00
|
|
|
#include <rtl/string.h>
|
2011-11-23 15:45:43 +01:00
|
|
|
#include <sal/log.hxx>
|
2010-10-18 12:28:33 +02:00
|
|
|
#include <sal/macros.h>
|
2006-02-28 09:31:44 +00:00
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <osl/diagnose.h>
|
2013-05-21 08:40:07 +02:00
|
|
|
#include <tools/diagnose_ex.h>
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
#ifdef DBG_UTIL
|
|
|
|
|
2012-08-19 21:19:29 +02:00
|
|
|
// PointerList
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
#define PBLOCKCOUNT 1024
|
|
|
|
|
|
|
|
struct PBlock
|
|
|
|
{
|
|
|
|
void* aData[PBLOCKCOUNT];
|
2012-08-18 18:33:10 +02:00
|
|
|
sal_uInt16 nCount;
|
2000-09-18 16:07:07 +00:00
|
|
|
PBlock* pPrev;
|
|
|
|
PBlock* pNext;
|
|
|
|
};
|
|
|
|
|
|
|
|
class PointerList
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
PBlock* pFirst;
|
|
|
|
PBlock* pLast;
|
2012-08-18 18:33:10 +02:00
|
|
|
sal_uIntPtr nCount;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
PointerList() { pFirst = NULL; pLast = NULL; nCount = 0; }
|
|
|
|
~PointerList();
|
|
|
|
|
|
|
|
void Add( const void* p );
|
2013-06-29 23:57:38 -05:00
|
|
|
bool Remove( const void* p );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2010-07-29 10:56:19 +08:00
|
|
|
const void* Get( sal_uIntPtr nPos ) const;
|
2013-06-29 23:57:38 -05:00
|
|
|
bool IsIn( const void* p ) const;
|
2012-08-18 18:33:10 +02:00
|
|
|
sal_uIntPtr Count() const { return nCount; }
|
2000-09-18 16:07:07 +00:00
|
|
|
};
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// data types
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
#define DBG_MAXNAME 28
|
|
|
|
|
|
|
|
struct ProfType
|
|
|
|
{
|
2012-08-18 18:33:10 +02:00
|
|
|
sal_uIntPtr nCount;
|
|
|
|
sal_uIntPtr nTime;
|
|
|
|
sal_uIntPtr nMinTime;
|
|
|
|
sal_uIntPtr nMaxTime;
|
|
|
|
sal_uIntPtr nStart;
|
|
|
|
sal_uIntPtr nContinueTime;
|
|
|
|
sal_uIntPtr nContinueStart;
|
2000-09-18 16:07:07 +00:00
|
|
|
sal_Char aName[DBG_MAXNAME+1];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct XtorType
|
|
|
|
{
|
2012-08-18 18:33:10 +02:00
|
|
|
sal_uIntPtr nCtorCalls;
|
|
|
|
sal_uIntPtr nDtorCalls;
|
|
|
|
sal_uIntPtr nMaxCount;
|
|
|
|
sal_uIntPtr nStatics;
|
2000-09-18 16:07:07 +00:00
|
|
|
sal_Char aName[DBG_MAXNAME+1];
|
2013-06-29 23:57:38 -05:00
|
|
|
bool bTest;
|
2000-09-18 16:07:07 +00:00
|
|
|
PointerList aThisList;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DebugData
|
|
|
|
{
|
|
|
|
DbgData aDbgData;
|
2012-08-18 18:33:10 +02:00
|
|
|
sal_uInt16 bInit;
|
2000-09-18 16:07:07 +00:00
|
|
|
DbgPrintLine pDbgPrintMsgBox;
|
|
|
|
DbgPrintLine pDbgPrintWindow;
|
|
|
|
DbgPrintLine pDbgPrintTestTool;
|
2011-02-20 23:09:20 +01:00
|
|
|
DbgPrintLine pDbgAbort;
|
2006-02-28 09:31:44 +00:00
|
|
|
::std::vector< DbgPrintLine >
|
|
|
|
aDbgPrintUserChannels;
|
2000-09-18 16:07:07 +00:00
|
|
|
PointerList* pProfList;
|
|
|
|
PointerList* pXtorList;
|
|
|
|
DbgTestSolarMutexProc pDbgTestSolarMutex;
|
2006-02-28 09:31:44 +00:00
|
|
|
pfunc_osl_printDetailedDebugMessage
|
|
|
|
pOldDebugMessageFunc;
|
|
|
|
bool bOslIsHooked;
|
|
|
|
|
|
|
|
DebugData()
|
2013-06-29 23:57:38 -05:00
|
|
|
:bInit( false )
|
2011-02-20 23:09:20 +01:00
|
|
|
,pDbgPrintMsgBox( NULL )
|
2006-02-28 09:31:44 +00:00
|
|
|
,pDbgPrintWindow( NULL )
|
|
|
|
,pDbgPrintTestTool( NULL )
|
2011-02-20 23:09:20 +01:00
|
|
|
,pDbgAbort( NULL )
|
2006-02-28 09:31:44 +00:00
|
|
|
,pProfList( NULL )
|
|
|
|
,pXtorList( NULL )
|
|
|
|
,pDbgTestSolarMutex( NULL )
|
|
|
|
,pOldDebugMessageFunc( NULL )
|
|
|
|
,bOslIsHooked( false )
|
|
|
|
{
|
2012-01-10 07:19:46 +01:00
|
|
|
aDbgData.nTestFlags = DBG_TEST_RESOURCE;
|
2013-06-29 23:57:38 -05:00
|
|
|
aDbgData.bOverwrite = true;
|
2006-02-28 09:31:44 +00:00
|
|
|
aDbgData.nTraceOut = DBG_OUT_NULL;
|
|
|
|
aDbgData.nWarningOut = DBG_OUT_NULL;
|
2010-08-27 14:29:51 +02:00
|
|
|
#ifdef UNX
|
|
|
|
aDbgData.nErrorOut = DBG_OUT_SHELL;
|
|
|
|
#else
|
2006-02-28 09:31:44 +00:00
|
|
|
aDbgData.nErrorOut = DBG_OUT_MSGBOX;
|
2010-08-27 14:29:51 +02:00
|
|
|
#endif
|
2013-06-29 23:57:38 -05:00
|
|
|
aDbgData.bHookOSLAssert = true;
|
2006-02-28 09:31:44 +00:00
|
|
|
aDbgData.aDebugName[0] = 0;
|
|
|
|
aDbgData.aInclFilter[0] = 0;
|
|
|
|
aDbgData.aExclFilter[0] = 0;
|
|
|
|
aDbgData.aInclClassFilter[0] = 0;
|
|
|
|
aDbgData.aExclClassFilter[0] = 0;
|
|
|
|
aDbgData.aDbgWinState[0] = 0;
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define DBG_TEST_XTOR_EXTRA (DBG_TEST_XTOR_THIS | DBG_TEST_XTOR_FUNC | \
|
|
|
|
DBG_TEST_XTOR_EXIT | DBG_TEST_XTOR_REPORT )
|
|
|
|
|
2012-08-18 18:12:35 +02:00
|
|
|
// static maintenance variables
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2006-02-28 09:31:44 +00:00
|
|
|
static DebugData aDebugData;
|
2000-09-18 16:07:07 +00:00
|
|
|
static sal_Char aCurPath[260];
|
2013-06-29 23:57:38 -05:00
|
|
|
static int bDbgImplInMain = false;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
#if defined( WNT )
|
|
|
|
static CRITICAL_SECTION aImplCritDbgSection;
|
|
|
|
#endif
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
static bool bImplCritDbgSectionInit = false;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
void ImplDbgInitLock()
|
|
|
|
{
|
|
|
|
#if defined( WNT )
|
|
|
|
InitializeCriticalSection( &aImplCritDbgSection );
|
|
|
|
#endif
|
2013-06-29 23:57:38 -05:00
|
|
|
bImplCritDbgSectionInit = true;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ImplDbgDeInitLock()
|
|
|
|
{
|
|
|
|
#if defined( WNT )
|
|
|
|
DeleteCriticalSection( &aImplCritDbgSection );
|
|
|
|
#endif
|
2013-06-29 23:57:38 -05:00
|
|
|
bImplCritDbgSectionInit = false;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ImplDbgLock()
|
|
|
|
{
|
|
|
|
if ( !bImplCritDbgSectionInit )
|
|
|
|
return;
|
|
|
|
|
|
|
|
#if defined( WNT )
|
|
|
|
EnterCriticalSection( &aImplCritDbgSection );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImplDbgUnlock()
|
|
|
|
{
|
|
|
|
if ( !bImplCritDbgSectionInit )
|
|
|
|
return;
|
|
|
|
|
|
|
|
#if defined( WNT )
|
|
|
|
LeaveCriticalSection( &aImplCritDbgSection );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FILE_LINEEND "\n"
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
static bool ImplActivateDebugger( const sal_Char* pMsg )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
#if defined( WNT )
|
|
|
|
static sal_Char aImplDbgOutBuf[DBG_BUF_MAXLEN];
|
|
|
|
strcpy( aImplDbgOutBuf, pMsg );
|
|
|
|
strcat( aImplDbgOutBuf, "\r\n" );
|
|
|
|
OutputDebugString( aImplDbgOutBuf );
|
|
|
|
DebugBreak();
|
2013-06-29 23:57:38 -05:00
|
|
|
return true;
|
2000-09-18 16:07:07 +00:00
|
|
|
#else
|
2006-06-19 12:37:51 +00:00
|
|
|
(void) pMsg; // avoid warning about unused parameter
|
2013-06-29 23:57:38 -05:00
|
|
|
return false;
|
2000-09-18 16:07:07 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
static bool ImplCoreDump()
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
#if defined( WNT )
|
|
|
|
DebugBreak();
|
|
|
|
#else
|
|
|
|
long* pTemp = 0;
|
|
|
|
*pTemp = 0xCCCC;
|
|
|
|
#endif
|
2013-06-29 23:57:38 -05:00
|
|
|
return true;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 10:56:19 +08:00
|
|
|
static sal_uIntPtr ImplGetPerfTime()
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
#if defined( WNT )
|
2010-07-29 10:56:19 +08:00
|
|
|
return (sal_uIntPtr)GetTickCount();
|
2000-09-18 16:07:07 +00:00
|
|
|
#else
|
2010-07-29 10:56:19 +08:00
|
|
|
static sal_uIntPtr nImplTicksPerSecond = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
static double dImplTicksPerSecond;
|
2010-07-29 10:56:19 +08:00
|
|
|
sal_uIntPtr nTicks = (sal_uIntPtr)clock();
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if ( !nImplTicksPerSecond )
|
|
|
|
{
|
|
|
|
nImplTicksPerSecond = CLOCKS_PER_SEC;
|
|
|
|
dImplTicksPerSecond = nImplTicksPerSecond;
|
|
|
|
}
|
|
|
|
|
|
|
|
double fTicks = nTicks;
|
|
|
|
fTicks *= 1000;
|
|
|
|
fTicks /= dImplTicksPerSecond;
|
2010-07-29 10:56:19 +08:00
|
|
|
return (sal_uIntPtr)fTicks;
|
2000-09-18 16:07:07 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef FILE* FILETYPE;
|
|
|
|
#define FileOpen fopen
|
|
|
|
#define FileRead fread
|
|
|
|
#define FilePrintF fprintf
|
|
|
|
#define FileClose fclose
|
|
|
|
|
2006-02-28 09:31:44 +00:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
enum ConfigSection
|
|
|
|
{
|
|
|
|
eOutput,
|
|
|
|
eMemory,
|
|
|
|
eGUI,
|
|
|
|
eObjects,
|
|
|
|
eTest,
|
|
|
|
|
|
|
|
eUnknown
|
|
|
|
};
|
|
|
|
|
|
|
|
void lcl_lineFeed( FILETYPE _pFile )
|
|
|
|
{
|
|
|
|
FilePrintF( _pFile, "%s", FILE_LINEEND );
|
|
|
|
}
|
|
|
|
|
|
|
|
const sal_Char* lcl_getSectionName( ConfigSection _eSection )
|
|
|
|
{
|
|
|
|
const sal_Char* pSectionName = NULL;
|
|
|
|
switch ( _eSection )
|
|
|
|
{
|
|
|
|
case eOutput : pSectionName = "output"; break;
|
|
|
|
case eMemory : pSectionName = "memory"; break;
|
|
|
|
case eGUI : pSectionName = "gui"; break;
|
|
|
|
case eObjects : pSectionName = "objects"; break;
|
|
|
|
case eTest : pSectionName = "test"; break;
|
2006-06-19 12:37:51 +00:00
|
|
|
case eUnknown:
|
|
|
|
OSL_ASSERT(false);
|
|
|
|
break;
|
2006-02-28 09:31:44 +00:00
|
|
|
}
|
|
|
|
return pSectionName;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConfigSection lcl_getSectionFromName( const sal_Char* _pSectionName, size_t _nSectionNameLength )
|
|
|
|
{
|
|
|
|
if ( strncmp( _pSectionName, "output", _nSectionNameLength < 6 ? _nSectionNameLength : 6 ) == 0 )
|
|
|
|
return eOutput;
|
|
|
|
if ( strncmp( _pSectionName, "memory", _nSectionNameLength < 6 ? _nSectionNameLength : 6 ) == 0 )
|
|
|
|
return eMemory;
|
|
|
|
if ( strncmp( _pSectionName, "gui", _nSectionNameLength < 3 ? _nSectionNameLength : 3 ) == 0 )
|
|
|
|
return eGUI;
|
|
|
|
if ( strncmp( _pSectionName, "objects", _nSectionNameLength < 7 ? _nSectionNameLength : 7 ) == 0 )
|
|
|
|
return eObjects;
|
|
|
|
if ( strncmp( _pSectionName, "test", _nSectionNameLength < 4 ? _nSectionNameLength : 4 ) == 0 )
|
|
|
|
return eTest;
|
|
|
|
return eUnknown;
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcl_startSection( FILETYPE _pFile, ConfigSection _eSection )
|
|
|
|
{
|
|
|
|
FilePrintF( _pFile, "[%s]%s", lcl_getSectionName( _eSection ), FILE_LINEEND );
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcl_writeConfigString( FILETYPE _pFile, const sal_Char* _pKeyName, const sal_Char* _pValue )
|
|
|
|
{
|
|
|
|
FilePrintF( _pFile, "%s=%s%s", _pKeyName, _pValue, FILE_LINEEND );
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcl_writeConfigBoolean( FILETYPE _pFile, const sal_Char* _pKeyName, bool _bValue )
|
|
|
|
{
|
|
|
|
lcl_writeConfigString( _pFile, _pKeyName, _bValue ? "1" : "0" );
|
|
|
|
}
|
|
|
|
|
2010-07-29 10:56:19 +08:00
|
|
|
void lcl_writeConfigFlag( FILETYPE _pFile, const sal_Char* _pKeyName, sal_uIntPtr _nAllFlags, sal_uIntPtr _nCheckFlag )
|
2006-02-28 09:31:44 +00:00
|
|
|
{
|
|
|
|
lcl_writeConfigBoolean( _pFile, _pKeyName, ( _nAllFlags & _nCheckFlag ) != 0 );
|
|
|
|
}
|
|
|
|
|
2010-07-29 10:56:19 +08:00
|
|
|
void lcl_writeConfigOutChannel( FILETYPE _pFile, const sal_Char* _pKeyName, sal_uIntPtr _nValue )
|
2006-02-28 09:31:44 +00:00
|
|
|
{
|
|
|
|
const sal_Char* names[ DBG_OUT_COUNT ] =
|
|
|
|
{
|
2011-02-20 23:09:20 +01:00
|
|
|
"dev/null", "file", "window", "shell", "messagebox", "testtool", "debugger", "abort"
|
2006-02-28 09:31:44 +00:00
|
|
|
};
|
|
|
|
lcl_writeConfigString( _pFile, _pKeyName, names[ _nValue ] );
|
|
|
|
}
|
2012-08-18 18:12:35 +02:00
|
|
|
|
2006-02-28 09:31:44 +00:00
|
|
|
bool lcl_isConfigSection( const sal_Char* _pLine, size_t _nLineLen )
|
|
|
|
{
|
|
|
|
if ( _nLineLen < 2 )
|
|
|
|
// not even enough space for '[' and ']'
|
|
|
|
return false;
|
|
|
|
if ( ( _pLine[0] == '[' ) && ( _pLine[ _nLineLen - 1 ] == ']' ) )
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
2012-08-18 18:12:35 +02:00
|
|
|
|
2006-02-28 09:31:44 +00:00
|
|
|
bool lcl_isConfigKey( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName )
|
|
|
|
{
|
|
|
|
size_t nKeyLength = strlen( _pKeyName );
|
|
|
|
if ( nKeyLength + 1 >= _nLineLen )
|
|
|
|
// not even long enough for the key name plus "=" plus a one-character value
|
|
|
|
return false;
|
|
|
|
if ( ( strncmp( _pLine, _pKeyName, nKeyLength ) == 0 ) && ( _pLine[ nKeyLength ] == '=' ) )
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
2012-08-18 18:12:35 +02:00
|
|
|
|
2006-02-28 09:31:44 +00:00
|
|
|
sal_Int32 lcl_tryReadConfigString( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, sal_Char* _pValue, size_t _nValueLen )
|
|
|
|
{
|
|
|
|
if ( !lcl_isConfigKey( _pLine, _nLineLen, _pKeyName ) )
|
|
|
|
return 0;
|
|
|
|
size_t nValuePos = strlen( _pKeyName ) + 1;
|
|
|
|
size_t nValueLen = _nLineLen - nValuePos;
|
|
|
|
const sal_Char* pValue = _pLine + nValuePos;
|
|
|
|
strncpy( _pValue, pValue, ( _nValueLen > nValueLen ) ? nValueLen : _nValueLen );
|
|
|
|
_pValue[ ( _nValueLen > nValueLen ) ? nValueLen : _nValueLen - 1 ] = 0;
|
|
|
|
return strlen( _pValue );
|
|
|
|
}
|
2012-08-18 18:12:35 +02:00
|
|
|
|
2010-07-29 10:56:19 +08:00
|
|
|
void lcl_tryReadConfigBoolean( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, sal_uIntPtr* _out_pnValue )
|
2006-02-28 09:31:44 +00:00
|
|
|
{
|
|
|
|
sal_Char aBuf[2];
|
|
|
|
size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) );
|
|
|
|
if ( nValueLen )
|
2013-06-29 23:57:38 -05:00
|
|
|
*_out_pnValue = strcmp( aBuf, "1" ) == 0 ? true : false;
|
2006-02-28 09:31:44 +00:00
|
|
|
}
|
2012-08-18 18:12:35 +02:00
|
|
|
|
debuglevels: simplify the build system, by complicating the OOo code ;)
Introduce DBGSV_(TRACE/WARNING/ERROR)_OUT, which controls the output channel for tools-level
traces/warnings/assertions, when no dbgsv.ini file is found (this is the increased OOo complexity).
Use this in installationtest.mk, instead of creating a dedicated dbgsv.ini file.
Yet to come: add support for DBGSV_ERROR_OUT to the GNU make build system. Which is the reason why
DBGSV_ERROR_OUT was introduced: Currently, running a GNU make based test pops up assertions as message
boxes. Before the change here, we would have needed to add dbgsv.ini support to the GNU make build system,
which sounds not like a funny a reasonable thing to do. So, instead, we will simply set DBGSV_ERROR_OUT,
which is much simpler and less error prone.
2011-02-24 17:39:47 +01:00
|
|
|
void lcl_matchOutputChannel( sal_Char const * i_buffer, sal_uIntPtr* o_value )
|
2006-02-28 09:31:44 +00:00
|
|
|
{
|
debuglevels: simplify the build system, by complicating the OOo code ;)
Introduce DBGSV_(TRACE/WARNING/ERROR)_OUT, which controls the output channel for tools-level
traces/warnings/assertions, when no dbgsv.ini file is found (this is the increased OOo complexity).
Use this in installationtest.mk, instead of creating a dedicated dbgsv.ini file.
Yet to come: add support for DBGSV_ERROR_OUT to the GNU make build system. Which is the reason why
DBGSV_ERROR_OUT was introduced: Currently, running a GNU make based test pops up assertions as message
boxes. Before the change here, we would have needed to add dbgsv.ini support to the GNU make build system,
which sounds not like a funny a reasonable thing to do. So, instead, we will simply set DBGSV_ERROR_OUT,
which is much simpler and less error prone.
2011-02-24 17:39:47 +01:00
|
|
|
if ( i_buffer == NULL )
|
|
|
|
return;
|
2006-02-28 09:31:44 +00:00
|
|
|
const sal_Char* names[ DBG_OUT_COUNT ] =
|
|
|
|
{
|
2011-02-20 23:09:20 +01:00
|
|
|
"dev/null", "file", "window", "shell", "messagebox", "testtool", "debugger", "abort"
|
2006-02-28 09:31:44 +00:00
|
|
|
};
|
2011-03-23 16:59:33 +01:00
|
|
|
for ( size_t name = 0; name < SAL_N_ELEMENTS( names ); ++name )
|
2006-02-28 09:31:44 +00:00
|
|
|
{
|
debuglevels: simplify the build system, by complicating the OOo code ;)
Introduce DBGSV_(TRACE/WARNING/ERROR)_OUT, which controls the output channel for tools-level
traces/warnings/assertions, when no dbgsv.ini file is found (this is the increased OOo complexity).
Use this in installationtest.mk, instead of creating a dedicated dbgsv.ini file.
Yet to come: add support for DBGSV_ERROR_OUT to the GNU make build system. Which is the reason why
DBGSV_ERROR_OUT was introduced: Currently, running a GNU make based test pops up assertions as message
boxes. Before the change here, we would have needed to add dbgsv.ini support to the GNU make build system,
which sounds not like a funny a reasonable thing to do. So, instead, we will simply set DBGSV_ERROR_OUT,
which is much simpler and less error prone.
2011-02-24 17:39:47 +01:00
|
|
|
if ( strcmp( i_buffer, names[ name ] ) == 0 )
|
2006-02-28 09:31:44 +00:00
|
|
|
{
|
debuglevels: simplify the build system, by complicating the OOo code ;)
Introduce DBGSV_(TRACE/WARNING/ERROR)_OUT, which controls the output channel for tools-level
traces/warnings/assertions, when no dbgsv.ini file is found (this is the increased OOo complexity).
Use this in installationtest.mk, instead of creating a dedicated dbgsv.ini file.
Yet to come: add support for DBGSV_ERROR_OUT to the GNU make build system. Which is the reason why
DBGSV_ERROR_OUT was introduced: Currently, running a GNU make based test pops up assertions as message
boxes. Before the change here, we would have needed to add dbgsv.ini support to the GNU make build system,
which sounds not like a funny a reasonable thing to do. So, instead, we will simply set DBGSV_ERROR_OUT,
which is much simpler and less error prone.
2011-02-24 17:39:47 +01:00
|
|
|
*o_value = name;
|
|
|
|
return;
|
2006-02-28 09:31:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-08-18 18:12:35 +02:00
|
|
|
|
debuglevels: simplify the build system, by complicating the OOo code ;)
Introduce DBGSV_(TRACE/WARNING/ERROR)_OUT, which controls the output channel for tools-level
traces/warnings/assertions, when no dbgsv.ini file is found (this is the increased OOo complexity).
Use this in installationtest.mk, instead of creating a dedicated dbgsv.ini file.
Yet to come: add support for DBGSV_ERROR_OUT to the GNU make build system. Which is the reason why
DBGSV_ERROR_OUT was introduced: Currently, running a GNU make based test pops up assertions as message
boxes. Before the change here, we would have needed to add dbgsv.ini support to the GNU make build system,
which sounds not like a funny a reasonable thing to do. So, instead, we will simply set DBGSV_ERROR_OUT,
which is much simpler and less error prone.
2011-02-24 17:39:47 +01:00
|
|
|
void lcl_tryReadOutputChannel( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, sal_uIntPtr* _out_pnValue )
|
|
|
|
{
|
|
|
|
sal_Char aBuf[20];
|
|
|
|
size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) );
|
|
|
|
if ( nValueLen )
|
|
|
|
lcl_matchOutputChannel( aBuf, _out_pnValue );
|
|
|
|
}
|
2012-08-18 18:12:35 +02:00
|
|
|
|
2010-07-29 10:56:19 +08:00
|
|
|
void lcl_tryReadConfigFlag( const sal_Char* _pLine, size_t _nLineLen, const sal_Char* _pKeyName, sal_uIntPtr* _out_pnAllFlags, sal_uIntPtr _nCheckFlag )
|
2006-02-28 09:31:44 +00:00
|
|
|
{
|
|
|
|
sal_Char aBuf[2];
|
|
|
|
size_t nValueLen = lcl_tryReadConfigString( _pLine, _nLineLen, _pKeyName, aBuf, sizeof( aBuf ) );
|
|
|
|
if ( nValueLen )
|
2010-12-23 11:19:55 +01:00
|
|
|
{
|
2006-02-28 09:31:44 +00:00
|
|
|
if ( strcmp( aBuf, "1" ) == 0 )
|
|
|
|
*_out_pnAllFlags |= _nCheckFlag;
|
|
|
|
else
|
|
|
|
*_out_pnAllFlags &= ~_nCheckFlag;
|
2010-12-23 11:19:55 +01:00
|
|
|
}
|
2006-02-28 09:31:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
PointerList::~PointerList()
|
|
|
|
{
|
|
|
|
PBlock* pBlock = pFirst;
|
|
|
|
while ( pBlock )
|
|
|
|
{
|
|
|
|
PBlock* pNextBlock = pBlock->pNext;
|
|
|
|
delete pBlock;
|
|
|
|
pBlock = pNextBlock;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PointerList::Add( const void* p )
|
|
|
|
{
|
|
|
|
if ( !pFirst )
|
|
|
|
{
|
|
|
|
pFirst = new PBlock;
|
|
|
|
memset( pFirst->aData, 0, PBLOCKCOUNT * sizeof( void* ) );
|
|
|
|
pFirst->nCount = 0;
|
|
|
|
pFirst->pPrev = NULL;
|
|
|
|
pFirst->pNext = NULL;
|
|
|
|
pLast = pFirst;
|
|
|
|
}
|
|
|
|
|
|
|
|
PBlock* pBlock = pFirst;
|
|
|
|
while ( pBlock && (pBlock->nCount == PBLOCKCOUNT) )
|
|
|
|
pBlock = pBlock->pNext;
|
|
|
|
|
|
|
|
if ( !pBlock )
|
|
|
|
{
|
|
|
|
pBlock = new PBlock;
|
|
|
|
memset( pBlock->aData, 0, PBLOCKCOUNT * sizeof( void* ) );
|
|
|
|
pBlock->nCount = 0;
|
|
|
|
pBlock->pPrev = pLast;
|
|
|
|
pBlock->pNext = NULL;
|
|
|
|
pLast->pNext = pBlock;
|
|
|
|
pLast = pBlock;
|
|
|
|
}
|
|
|
|
|
2011-01-21 13:06:20 +01:00
|
|
|
sal_uInt16 i = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
while ( pBlock->aData[i] )
|
|
|
|
i++;
|
|
|
|
|
|
|
|
pBlock->aData[i] = (void*)p;
|
|
|
|
pBlock->nCount++;
|
|
|
|
nCount++;
|
|
|
|
}
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
bool PointerList::Remove( const void* p )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
if ( !p )
|
2013-06-29 23:57:38 -05:00
|
|
|
return false;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
PBlock* pBlock = pFirst;
|
|
|
|
while ( pBlock )
|
|
|
|
{
|
2011-01-21 13:06:20 +01:00
|
|
|
sal_uInt16 i = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
while ( i < PBLOCKCOUNT )
|
|
|
|
{
|
2010-07-29 10:56:19 +08:00
|
|
|
if ( ((sal_uIntPtr)p) == ((sal_uIntPtr)pBlock->aData[i]) )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
pBlock->aData[i] = NULL;
|
|
|
|
pBlock->nCount--;
|
|
|
|
nCount--;
|
|
|
|
|
|
|
|
if ( !pBlock->nCount )
|
|
|
|
{
|
|
|
|
if ( pBlock->pPrev )
|
|
|
|
pBlock->pPrev->pNext = pBlock->pNext;
|
|
|
|
if ( pBlock->pNext )
|
|
|
|
pBlock->pNext->pPrev = pBlock->pPrev;
|
|
|
|
if ( pBlock == pFirst )
|
|
|
|
pFirst = pBlock->pNext;
|
|
|
|
if ( pBlock == pLast )
|
|
|
|
pLast = pBlock->pPrev;
|
|
|
|
delete pBlock;
|
|
|
|
}
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
return true;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
pBlock = pBlock->pNext;
|
|
|
|
}
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
return false;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 10:56:19 +08:00
|
|
|
const void* PointerList::Get( sal_uIntPtr nPos ) const
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
if ( nCount <= nPos )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
PBlock* pBlock = pFirst;
|
2010-07-29 10:56:19 +08:00
|
|
|
sal_uIntPtr nStart = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
while ( pBlock )
|
|
|
|
{
|
2011-01-21 13:06:20 +01:00
|
|
|
sal_uInt16 i = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
while ( i < PBLOCKCOUNT )
|
|
|
|
{
|
|
|
|
if ( pBlock->aData[i] )
|
|
|
|
{
|
|
|
|
nStart++;
|
|
|
|
if ( (nStart-1) == nPos )
|
|
|
|
return pBlock->aData[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
pBlock = pBlock->pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
bool PointerList::IsIn( const void* p ) const
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
if ( !p )
|
2013-06-29 23:57:38 -05:00
|
|
|
return false;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
PBlock* pBlock = pFirst;
|
|
|
|
while ( pBlock )
|
|
|
|
{
|
2011-01-21 13:06:20 +01:00
|
|
|
sal_uInt16 i = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
while ( i < PBLOCKCOUNT )
|
|
|
|
{
|
2010-07-29 10:56:19 +08:00
|
|
|
if ( ((sal_uIntPtr)p) == ((sal_uIntPtr)pBlock->aData[i]) )
|
2013-06-29 23:57:38 -05:00
|
|
|
return true;
|
2000-09-18 16:07:07 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
pBlock = pBlock->pNext;
|
|
|
|
}
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
return false;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2010-02-03 13:49:27 +01:00
|
|
|
static void DbgGetDbgFileName( sal_Char* pStr, sal_Int32 nMaxLen )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2010-02-03 13:49:27 +01:00
|
|
|
#if defined( UNX )
|
|
|
|
const sal_Char* pName = getenv("DBGSV_INIT");
|
|
|
|
if ( !pName )
|
|
|
|
pName = ".dbgsv.init";
|
|
|
|
strncpy( pStr, pName, nMaxLen );
|
|
|
|
#elif defined( WNT )
|
|
|
|
const sal_Char* pName = getenv("DBGSV_INIT");
|
|
|
|
if ( pName )
|
|
|
|
strncpy( pStr, pName, nMaxLen );
|
|
|
|
else
|
|
|
|
GetProfileStringA( "sv", "dbgsv", "dbgsv.ini", pStr, nMaxLen );
|
|
|
|
#else
|
|
|
|
strncpy( pStr, "dbgsv.ini", nMaxLen );
|
|
|
|
#endif
|
|
|
|
pStr[ nMaxLen - 1 ] = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void DbgGetLogFileName( sal_Char* pStr )
|
|
|
|
{
|
|
|
|
#if defined( UNX )
|
|
|
|
const sal_Char* pName = getenv("DBGSV_LOG");
|
|
|
|
if ( !pName )
|
|
|
|
pName = "dbgsv.log";
|
|
|
|
strcpy( pStr, pName );
|
|
|
|
#elif defined( WNT )
|
|
|
|
const sal_Char* pName = getenv("DBGSV_LOG");
|
|
|
|
if ( pName )
|
|
|
|
strcpy( pStr, pName );
|
|
|
|
else
|
|
|
|
GetProfileStringA( "sv", "dbgsvlog", "dbgsv.log", pStr, 200 );
|
|
|
|
#else
|
|
|
|
strcpy( pStr, "dbgsv.log" );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static DebugData* GetDebugData()
|
|
|
|
{
|
|
|
|
if ( !aDebugData.bInit )
|
|
|
|
{
|
2013-06-29 23:57:38 -05:00
|
|
|
aDebugData.bInit = true;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// set default debug names
|
2000-09-18 16:07:07 +00:00
|
|
|
DbgGetLogFileName( aDebugData.aDbgData.aDebugName );
|
|
|
|
|
|
|
|
// DEBUG.INI-File
|
2010-02-03 13:49:27 +01:00
|
|
|
sal_Char aBuf[ 4096 ];
|
|
|
|
DbgGetDbgFileName( aBuf, sizeof( aBuf ) );
|
|
|
|
FILETYPE pIniFile = FileOpen( aBuf, "r" );
|
2006-02-28 09:31:44 +00:00
|
|
|
if ( pIniFile != NULL )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2006-02-28 09:31:44 +00:00
|
|
|
ConfigSection eCurrentSection = eUnknown;
|
|
|
|
|
|
|
|
// no sophisticated algorithm here, assume that the whole file fits into aBuf ...
|
2010-07-29 10:56:19 +08:00
|
|
|
sal_uIntPtr nReallyRead = FileRead( aBuf, 1, sizeof( aBuf ) / sizeof( sal_Char ) - 1, pIniFile );
|
2006-02-28 09:31:44 +00:00
|
|
|
aBuf[ nReallyRead ] = 0;
|
|
|
|
const sal_Char* pLine = aBuf;
|
|
|
|
while ( const sal_Char* pNextLine = strstr( pLine, FILE_LINEEND ) )
|
|
|
|
{
|
|
|
|
size_t nLineLength = pNextLine - pLine;
|
|
|
|
|
|
|
|
if ( lcl_isConfigSection( pLine, nLineLength ) )
|
|
|
|
eCurrentSection = lcl_getSectionFromName( pLine + 1, nLineLength - 2 );
|
|
|
|
|
|
|
|
// elements of the [output] section
|
|
|
|
if ( eCurrentSection == eOutput )
|
|
|
|
{
|
|
|
|
lcl_tryReadConfigString( pLine, nLineLength, "log_file", aDebugData.aDbgData.aDebugName, sizeof( aDebugData.aDbgData.aDebugName ) );
|
|
|
|
lcl_tryReadConfigBoolean( pLine, nLineLength, "overwrite", &aDebugData.aDbgData.bOverwrite );
|
|
|
|
lcl_tryReadConfigString( pLine, nLineLength, "include", aDebugData.aDbgData.aInclFilter, sizeof( aDebugData.aDbgData.aInclFilter ) );
|
|
|
|
lcl_tryReadConfigString( pLine, nLineLength, "exclude", aDebugData.aDbgData.aExclFilter, sizeof( aDebugData.aDbgData.aExclFilter ) );
|
|
|
|
lcl_tryReadConfigString( pLine, nLineLength, "include_class", aDebugData.aDbgData.aInclClassFilter, sizeof( aDebugData.aDbgData.aInclClassFilter ) );
|
|
|
|
lcl_tryReadConfigString( pLine, nLineLength, "exclude_class", aDebugData.aDbgData.aExclClassFilter, sizeof( aDebugData.aDbgData.aExclClassFilter ) );
|
|
|
|
lcl_tryReadOutputChannel( pLine, nLineLength, "trace", &aDebugData.aDbgData.nTraceOut );
|
|
|
|
lcl_tryReadOutputChannel( pLine, nLineLength, "warning", &aDebugData.aDbgData.nWarningOut );
|
|
|
|
lcl_tryReadOutputChannel( pLine, nLineLength, "error", &aDebugData.aDbgData.nErrorOut );
|
|
|
|
lcl_tryReadConfigBoolean( pLine, nLineLength, "oslhook", &aDebugData.aDbgData.bHookOSLAssert );
|
|
|
|
}
|
|
|
|
|
|
|
|
// elements of the [gui] section
|
|
|
|
if ( eCurrentSection == eGUI )
|
|
|
|
{
|
|
|
|
lcl_tryReadConfigString( pLine, nLineLength, "debug_window_state", aDebugData.aDbgData.aDbgWinState, sizeof( aDebugData.aDbgData.aDbgWinState ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
// elements of the [objects] section
|
|
|
|
if ( eCurrentSection == eObjects )
|
|
|
|
{
|
|
|
|
lcl_tryReadConfigFlag( pLine, nLineLength, "check_this", &aDebugData.aDbgData.nTestFlags, DBG_TEST_XTOR_THIS );
|
|
|
|
lcl_tryReadConfigFlag( pLine, nLineLength, "check_function", &aDebugData.aDbgData.nTestFlags, DBG_TEST_XTOR_FUNC );
|
|
|
|
lcl_tryReadConfigFlag( pLine, nLineLength, "check_exit", &aDebugData.aDbgData.nTestFlags, DBG_TEST_XTOR_EXIT );
|
|
|
|
lcl_tryReadConfigFlag( pLine, nLineLength, "generate_report", &aDebugData.aDbgData.nTestFlags, DBG_TEST_XTOR_REPORT );
|
|
|
|
lcl_tryReadConfigFlag( pLine, nLineLength, "trace", &aDebugData.aDbgData.nTestFlags, DBG_TEST_XTOR_TRACE );
|
|
|
|
}
|
|
|
|
|
|
|
|
// elements of the [test] section
|
|
|
|
if ( eCurrentSection == eTest )
|
|
|
|
{
|
|
|
|
lcl_tryReadConfigFlag( pLine, nLineLength, "profiling", &aDebugData.aDbgData.nTestFlags, DBG_TEST_PROFILING );
|
|
|
|
lcl_tryReadConfigFlag( pLine, nLineLength, "resources", &aDebugData.aDbgData.nTestFlags, DBG_TEST_RESOURCE );
|
|
|
|
lcl_tryReadConfigFlag( pLine, nLineLength, "dialog", &aDebugData.aDbgData.nTestFlags, DBG_TEST_DIALOG );
|
|
|
|
lcl_tryReadConfigFlag( pLine, nLineLength, "bold_app_font", &aDebugData.aDbgData.nTestFlags, DBG_TEST_BOLDAPPFONT );
|
|
|
|
}
|
|
|
|
|
|
|
|
pLine = pNextLine + strlen( FILE_LINEEND );
|
|
|
|
}
|
|
|
|
|
|
|
|
FileClose( pIniFile );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
debuglevels: simplify the build system, by complicating the OOo code ;)
Introduce DBGSV_(TRACE/WARNING/ERROR)_OUT, which controls the output channel for tools-level
traces/warnings/assertions, when no dbgsv.ini file is found (this is the increased OOo complexity).
Use this in installationtest.mk, instead of creating a dedicated dbgsv.ini file.
Yet to come: add support for DBGSV_ERROR_OUT to the GNU make build system. Which is the reason why
DBGSV_ERROR_OUT was introduced: Currently, running a GNU make based test pops up assertions as message
boxes. Before the change here, we would have needed to add dbgsv.ini support to the GNU make build system,
which sounds not like a funny a reasonable thing to do. So, instead, we will simply set DBGSV_ERROR_OUT,
which is much simpler and less error prone.
2011-02-24 17:39:47 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
lcl_matchOutputChannel( getenv( "DBGSV_TRACE_OUT" ), &aDebugData.aDbgData.nTraceOut );
|
|
|
|
lcl_matchOutputChannel( getenv( "DBGSV_WARNING_OUT" ), &aDebugData.aDbgData.nWarningOut );
|
|
|
|
lcl_matchOutputChannel( getenv( "DBGSV_ERROR_OUT" ), &aDebugData.aDbgData.nErrorOut );
|
|
|
|
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-04-14 22:48:29 -07:00
|
|
|
sal_Char* getcwdResult = getcwd( aCurPath, sizeof( aCurPath ) );
|
|
|
|
if ( !getcwdResult )
|
|
|
|
{
|
|
|
|
OSL_TRACE( "getcwd failed with error %s", strerror(errno) );
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// initialize debug data
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( aDebugData.aDbgData.nTestFlags & DBG_TEST_XTOR )
|
|
|
|
aDebugData.pXtorList = new PointerList;
|
|
|
|
if ( aDebugData.aDbgData.nTestFlags & DBG_TEST_PROFILING )
|
|
|
|
aDebugData.pProfList = new PointerList;
|
|
|
|
}
|
|
|
|
|
|
|
|
return &aDebugData;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline DebugData* ImplGetDebugData()
|
|
|
|
{
|
|
|
|
if ( !aDebugData.bInit )
|
|
|
|
return GetDebugData();
|
|
|
|
else
|
|
|
|
return &aDebugData;
|
|
|
|
}
|
|
|
|
|
|
|
|
static FILETYPE ImplDbgInitFile()
|
|
|
|
{
|
2013-06-29 23:57:38 -05:00
|
|
|
static bool bFileInit = false;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2001-07-03 13:32:19 +00:00
|
|
|
sal_Char aBuf[4096];
|
2011-04-14 22:48:29 -07:00
|
|
|
sal_Char* getcwdResult = getcwd( aBuf, sizeof( aBuf ) );
|
|
|
|
if ( !getcwdResult ) {
|
|
|
|
OSL_TRACE( "getcwd failed with error = %s", strerror(errno) );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int chdirResult = chdir( aCurPath );
|
|
|
|
if ( !chdirResult ) {
|
|
|
|
OSL_TRACE ( "chdir failed with error = %s", strerror(errno) );
|
|
|
|
return NULL;
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
DebugData* pData = GetDebugData();
|
|
|
|
FILETYPE pDebugFile;
|
|
|
|
|
|
|
|
if ( !bFileInit )
|
|
|
|
{
|
2013-06-29 23:57:38 -05:00
|
|
|
bFileInit = true;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if ( pData->aDbgData.bOverwrite )
|
|
|
|
pDebugFile = FileOpen( pData->aDbgData.aDebugName, "w" );
|
|
|
|
else
|
|
|
|
pDebugFile = FileOpen( pData->aDbgData.aDebugName, "a" );
|
|
|
|
|
|
|
|
if ( pDebugFile )
|
|
|
|
{
|
|
|
|
time_t nTime = time( 0 );
|
|
|
|
tm* pTime;
|
|
|
|
#ifdef UNX
|
|
|
|
tm aTime;
|
|
|
|
pTime = localtime_r( &nTime, &aTime );
|
|
|
|
#else
|
|
|
|
pTime = localtime( &nTime );
|
|
|
|
#endif
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// print header
|
2000-09-18 16:07:07 +00:00
|
|
|
FilePrintF( pDebugFile, "******************************************************************************%s", FILE_LINEEND );
|
|
|
|
FilePrintF( pDebugFile, "%s%s", pData->aDbgData.aDebugName, FILE_LINEEND );
|
|
|
|
if ( pTime )
|
|
|
|
FilePrintF( pDebugFile, "%s%s", asctime( pTime ), FILE_LINEEND );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pDebugFile = FileOpen( pData->aDbgData.aDebugName, "a" );
|
|
|
|
|
2011-04-14 22:48:29 -07:00
|
|
|
chdirResult = chdir( aBuf );
|
|
|
|
if ( !chdirResult )
|
|
|
|
{
|
|
|
|
OSL_TRACE( "chdir failed with error = %s", strerror(errno) );
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
return pDebugFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ImplDbgPrintFile( const sal_Char* pLine )
|
|
|
|
{
|
|
|
|
FILETYPE pDebugFile = ImplDbgInitFile();
|
|
|
|
|
|
|
|
if ( pDebugFile )
|
|
|
|
{
|
|
|
|
FilePrintF( pDebugFile, "%s%s", pLine, FILE_LINEEND );
|
|
|
|
FileClose( pDebugFile );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ImplStrSearch( const sal_Char* pSearchStr, int nSearchLen,
|
|
|
|
const sal_Char* pStr, int nLen )
|
|
|
|
{
|
|
|
|
int nPos = 0;
|
|
|
|
while ( nPos+nSearchLen <= nLen )
|
|
|
|
{
|
|
|
|
if ( strncmp( pStr+nPos, pSearchStr, nSearchLen ) == 0 )
|
|
|
|
return 1;
|
|
|
|
nPos++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ImplDbgFilter( const sal_Char* pFilter, const sal_Char* pMsg,
|
|
|
|
int bEmpty )
|
|
|
|
{
|
|
|
|
int nStrLen = strlen( pFilter );
|
|
|
|
if ( !nStrLen )
|
|
|
|
return bEmpty;
|
|
|
|
|
|
|
|
int nMsgLen = strlen( pMsg );
|
|
|
|
const sal_Char* pTok = pFilter;
|
|
|
|
int nTok = 0;
|
|
|
|
while ( pTok[nTok] )
|
|
|
|
{
|
|
|
|
if ( pTok[nTok] == ';' )
|
|
|
|
{
|
|
|
|
if ( nTok && ImplStrSearch( pTok, nTok, pMsg, nMsgLen ) )
|
2013-06-29 23:57:38 -05:00
|
|
|
return true;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
pTok += nTok+1;
|
|
|
|
nTok = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
nTok++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( nTok && ImplStrSearch( pTok, nTok, pMsg, nMsgLen ) )
|
2013-06-29 23:57:38 -05:00
|
|
|
return true;
|
2000-09-18 16:07:07 +00:00
|
|
|
else
|
2013-06-29 23:57:38 -05:00
|
|
|
return false;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2006-06-19 12:37:51 +00:00
|
|
|
extern "C"
|
2006-02-28 09:31:44 +00:00
|
|
|
void SAL_CALL dbg_printOslDebugMessage( const sal_Char * pszFileName, sal_Int32 nLine, const sal_Char * pszMessage )
|
|
|
|
{
|
2011-01-21 13:06:20 +01:00
|
|
|
DbgOut( pszMessage ? pszMessage : "assertion failed!", DBG_OUT_ERROR, pszFileName, (sal_uInt16)nLine );
|
2006-02-28 09:31:44 +00:00
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
static void DebugInit()
|
|
|
|
{
|
2013-06-29 23:57:38 -05:00
|
|
|
bDbgImplInMain = true;
|
2000-09-18 16:07:07 +00:00
|
|
|
ImplDbgInitLock();
|
2006-02-28 09:31:44 +00:00
|
|
|
|
|
|
|
DebugData* pData = GetDebugData();
|
|
|
|
if( pData->aDbgData.bHookOSLAssert && ! pData->bOslIsHooked )
|
|
|
|
{
|
|
|
|
pData->pOldDebugMessageFunc = osl_setDetailedDebugMessageFunc( &dbg_printOslDebugMessage );
|
|
|
|
pData->bOslIsHooked = true;
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void DebugDeInit()
|
|
|
|
{
|
|
|
|
DebugData* pData = GetDebugData();
|
2010-07-29 10:56:19 +08:00
|
|
|
sal_uIntPtr i;
|
|
|
|
sal_uIntPtr nCount;
|
|
|
|
sal_uIntPtr nOldOut;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2006-02-28 09:31:44 +00:00
|
|
|
if( pData->bOslIsHooked )
|
|
|
|
{
|
|
|
|
osl_setDetailedDebugMessageFunc( pData->pOldDebugMessageFunc );
|
2013-06-29 23:57:38 -05:00
|
|
|
pData->bOslIsHooked = false;
|
2006-02-28 09:31:44 +00:00
|
|
|
}
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// Output statistics trace data to file
|
2000-09-18 16:07:07 +00:00
|
|
|
nOldOut = pData->aDbgData.nTraceOut;
|
|
|
|
pData->aDbgData.nTraceOut = DBG_OUT_FILE;
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// output Xtor list
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( pData->pXtorList && pData->pXtorList->Count() &&
|
|
|
|
(pData->aDbgData.nTestFlags & DBG_TEST_XTOR_REPORT) )
|
|
|
|
{
|
|
|
|
DbgOutf( "------------------------------------------------------------------------------" );
|
|
|
|
DbgOutf( "Object Report" );
|
|
|
|
DbgOutf( "------------------------------------------------------------------------------" );
|
|
|
|
DbgOutf( "%-27s : %-9s : %-9s : %-7s : %-3s : %-6s :",
|
|
|
|
"XTor-List", "Ctor", "Dtor", "MaxInst", "St.", "Diff." );
|
|
|
|
DbgOutf( "----------------------------:-----------:-----------:---------:----:---------:" );
|
|
|
|
for( i = 0, nCount = pData->pXtorList->Count(); i < nCount; i++ )
|
|
|
|
{
|
|
|
|
XtorType* pXtorData = (XtorType*)pData->pXtorList->Get( i );
|
|
|
|
if ( pXtorData->bTest )
|
|
|
|
{
|
2012-08-12 01:01:00 +02:00
|
|
|
// Add static objects
|
2000-09-18 16:07:07 +00:00
|
|
|
pXtorData->nDtorCalls += pXtorData->nStatics;
|
|
|
|
if ( pXtorData->nStatics && (pXtorData->nDtorCalls > pXtorData->nCtorCalls) )
|
|
|
|
pXtorData->nDtorCalls = pXtorData->nCtorCalls;
|
|
|
|
DbgOutf( "%-27s : %9lu : %9lu : %7lu : %3lu : %4lu %-1s :",
|
|
|
|
pXtorData->aName, pXtorData->nCtorCalls, pXtorData->nDtorCalls,
|
|
|
|
pXtorData->nMaxCount, pXtorData->nStatics,
|
|
|
|
pXtorData->nCtorCalls - pXtorData->nDtorCalls,
|
|
|
|
(pXtorData->nCtorCalls - pXtorData->nDtorCalls) ? "!" : " " );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DbgOutf( "==============================================================================" );
|
|
|
|
}
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// free XtorList
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( pData->pXtorList )
|
|
|
|
{
|
|
|
|
for( i = 0, nCount = pData->pXtorList->Count(); i < nCount; i++ )
|
|
|
|
{
|
|
|
|
XtorType* pXtorData = (XtorType*)pData->pXtorList->Get( i );
|
|
|
|
delete pXtorData;
|
|
|
|
}
|
|
|
|
delete pData->pXtorList;
|
|
|
|
pData->pXtorList = NULL;
|
|
|
|
}
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
// Set everything to false, as global variables
|
2012-08-12 01:01:00 +02:00
|
|
|
// may cause a system crash otherwise.
|
|
|
|
// Maintain memory flags, as otherwise new/delete calls
|
|
|
|
// for global variables will crash,
|
|
|
|
// as pointer alignment won't work then.
|
2000-09-18 16:07:07 +00:00
|
|
|
pData->aDbgData.nTraceOut = nOldOut;
|
2012-01-10 07:19:46 +01:00
|
|
|
pData->aDbgData.nTestFlags &= DBG_TEST_PROFILING;
|
2006-02-28 09:31:44 +00:00
|
|
|
pData->aDbgPrintUserChannels.clear();
|
2000-09-18 16:07:07 +00:00
|
|
|
pData->pDbgPrintTestTool = NULL;
|
|
|
|
pData->pDbgPrintWindow = NULL;
|
2006-02-28 09:31:44 +00:00
|
|
|
pData->pOldDebugMessageFunc = NULL;
|
2000-09-18 16:07:07 +00:00
|
|
|
ImplDbgDeInitLock();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DebugGlobalDeInit()
|
|
|
|
{
|
|
|
|
DebugData* pData = GetDebugData();
|
2010-07-29 10:56:19 +08:00
|
|
|
sal_uIntPtr i;
|
|
|
|
sal_uIntPtr nCount;
|
|
|
|
sal_uIntPtr nOldOut;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// Output statistics trace data to file
|
2000-09-18 16:07:07 +00:00
|
|
|
nOldOut = pData->aDbgData.nTraceOut;
|
|
|
|
pData->aDbgData.nTraceOut = DBG_OUT_FILE;
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// output profile liste
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( pData->pProfList && pData->pProfList->Count() )
|
|
|
|
{
|
|
|
|
DbgOutf( "------------------------------------------------------------------------------" );
|
|
|
|
DbgOutf( "Profiling Report" );
|
|
|
|
DbgOutf( "------------------------------------------------------------------------------" );
|
|
|
|
DbgOutf( "%-25s : %-9s : %-6s : %-6s : %-6s : %-9s :",
|
|
|
|
"Prof-List (ms)", "Time", "Min", "Max", "Ave", "Count" );
|
|
|
|
DbgOutf( "--------------------------:-----------:--------:--------:--------:-----------:" );
|
|
|
|
for( i = 0, nCount = pData->pProfList->Count(); i < nCount; i++ )
|
|
|
|
{
|
|
|
|
ProfType* pProfData = (ProfType*)pData->pProfList->Get( i );
|
2010-07-29 10:56:19 +08:00
|
|
|
sal_uIntPtr nAve = pProfData->nTime / pProfData->nCount;
|
2000-09-18 16:07:07 +00:00
|
|
|
DbgOutf( "%-25s : %9lu : %6lu : %6lu : %6lu : %9lu :",
|
|
|
|
pProfData->aName, pProfData->nTime,
|
|
|
|
pProfData->nMinTime, pProfData->nMaxTime, nAve,
|
|
|
|
pProfData->nCount );
|
|
|
|
}
|
|
|
|
DbgOutf( "==============================================================================" );
|
|
|
|
}
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// free profile list
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( pData->pProfList )
|
|
|
|
{
|
|
|
|
for( i = 0, nCount = pData->pProfList->Count(); i < nCount; i++ )
|
|
|
|
{
|
|
|
|
ProfType* pProfData = (ProfType*)pData->pProfList->Get( i );
|
|
|
|
delete pProfData;
|
|
|
|
}
|
|
|
|
delete pData->pProfList;
|
|
|
|
pData->pProfList = NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// disable profiling flags
|
2000-09-18 16:07:07 +00:00
|
|
|
pData->aDbgData.nTraceOut = nOldOut;
|
|
|
|
pData->aDbgData.nTestFlags &= ~DBG_TEST_PROFILING;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImpDbgOutfBuf( sal_Char* pBuf, const sal_Char* pFStr, ... )
|
|
|
|
{
|
|
|
|
va_list pList;
|
|
|
|
|
|
|
|
va_start( pList, pFStr );
|
2001-07-03 13:32:19 +00:00
|
|
|
sal_Char aBuf[DBG_BUF_MAXLEN];
|
2000-09-18 16:07:07 +00:00
|
|
|
vsprintf( aBuf, pFStr, pList );
|
|
|
|
va_end( pList );
|
|
|
|
|
|
|
|
strcat( pBuf, aBuf );
|
|
|
|
strcat( pBuf, "\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DebugXTorInfo( sal_Char* pBuf )
|
|
|
|
{
|
|
|
|
DebugData* pData = GetDebugData();
|
2010-07-29 10:56:19 +08:00
|
|
|
sal_uIntPtr i;
|
|
|
|
sal_uIntPtr nCount;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// output Xtor list
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( pData->pXtorList && pData->pXtorList->Count() &&
|
|
|
|
(pData->aDbgData.nTestFlags & DBG_TEST_XTOR_REPORT) )
|
|
|
|
{
|
|
|
|
ImpDbgOutfBuf( pBuf, "------------------------------------------------------------------------------" );
|
|
|
|
ImpDbgOutfBuf( pBuf, "Object Report" );
|
|
|
|
ImpDbgOutfBuf( pBuf, "------------------------------------------------------------------------------" );
|
|
|
|
ImpDbgOutfBuf( pBuf, "%-27s : %-9s : %-9s : %-7s : %-3s : %-6s :",
|
|
|
|
"XTor-List", "Ctor", "Dtor", "MaxInst", "St.", "Diff." );
|
|
|
|
ImpDbgOutfBuf( pBuf, "----------------------------:-----------:-----------:---------:----:---------:" );
|
|
|
|
for( i = 0, nCount = pData->pXtorList->Count(); i < nCount; i++ )
|
|
|
|
{
|
|
|
|
XtorType* pXtorData = (XtorType*)pData->pXtorList->Get( i );
|
|
|
|
if ( pXtorData->bTest )
|
|
|
|
{
|
|
|
|
ImpDbgOutfBuf( pBuf, "%-27s : %9lu : %9lu : %7lu : %3lu : %6lu :",
|
|
|
|
pXtorData->aName, pXtorData->nCtorCalls, pXtorData->nDtorCalls,
|
|
|
|
pXtorData->nMaxCount, pXtorData->nStatics,
|
|
|
|
pXtorData->nCtorCalls - pXtorData->nDtorCalls );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ImpDbgOutfBuf( pBuf, "==============================================================================" );
|
|
|
|
ImpDbgOutfBuf( pBuf, "" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
bool ImplDbgFilterMessage( const sal_Char* pMsg )
|
2005-03-23 14:52:01 +00:00
|
|
|
{
|
|
|
|
DebugData* pData = GetDebugData();
|
2013-06-29 23:57:38 -05:00
|
|
|
if ( !ImplDbgFilter( pData->aDbgData.aInclFilter, pMsg, true ) )
|
|
|
|
return true;
|
|
|
|
if ( ImplDbgFilter( pData->aDbgData.aExclFilter, pMsg, false ) )
|
|
|
|
return true;
|
|
|
|
return false;
|
2005-03-23 14:52:01 +00:00
|
|
|
}
|
|
|
|
|
2011-01-21 13:06:20 +01:00
|
|
|
void* DbgFunc( sal_uInt16 nAction, void* pParam )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2006-02-28 09:31:44 +00:00
|
|
|
DebugData* pDebugData = ImplGetDebugData();
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if ( nAction == DBG_FUNC_GETDATA )
|
2006-02-28 09:31:44 +00:00
|
|
|
return (void*)&(pDebugData->aDbgData);
|
2002-05-29 06:27:13 +00:00
|
|
|
else if ( nAction == DBG_FUNC_GETPRINTMSGBOX )
|
2006-06-19 12:37:51 +00:00
|
|
|
return (void*)(long)(pDebugData->pDbgPrintMsgBox);
|
2005-03-23 14:52:01 +00:00
|
|
|
else if ( nAction == DBG_FUNC_FILTERMESSAGE )
|
|
|
|
if ( ImplDbgFilterMessage( (const sal_Char*) pParam ) )
|
|
|
|
return (void*) -1;
|
|
|
|
else
|
|
|
|
return (void*) 0; // aka NULL
|
2000-09-18 16:07:07 +00:00
|
|
|
else
|
2002-05-29 06:27:13 +00:00
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
switch ( nAction )
|
|
|
|
{
|
|
|
|
case DBG_FUNC_DEBUGSTART:
|
|
|
|
DebugInit();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_FUNC_DEBUGEND:
|
|
|
|
DebugDeInit();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_FUNC_GLOBALDEBUGEND:
|
|
|
|
DebugGlobalDeInit();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_FUNC_SETPRINTMSGBOX:
|
2006-06-19 12:37:51 +00:00
|
|
|
pDebugData->pDbgPrintMsgBox = (DbgPrintLine)(long)pParam;
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_FUNC_SETPRINTWINDOW:
|
2006-06-19 12:37:51 +00:00
|
|
|
pDebugData->pDbgPrintWindow = (DbgPrintLine)(long)pParam;
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_FUNC_SETPRINTTESTTOOL:
|
2006-06-19 12:37:51 +00:00
|
|
|
pDebugData->pDbgPrintTestTool = (DbgPrintLine)(long)pParam;
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
|
2011-02-20 23:09:20 +01:00
|
|
|
case DBG_FUNC_SET_ABORT:
|
|
|
|
pDebugData->pDbgAbort = (DbgPrintLine)(long)pParam;
|
|
|
|
break;
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
case DBG_FUNC_SAVEDATA:
|
|
|
|
{
|
2006-02-28 09:31:44 +00:00
|
|
|
const DbgData* pData = static_cast< const DbgData* >( pParam );
|
|
|
|
|
2010-02-03 13:49:27 +01:00
|
|
|
sal_Char aBuf[ 4096 ];
|
|
|
|
DbgGetDbgFileName( aBuf, sizeof( aBuf ) );
|
|
|
|
FILETYPE pIniFile = FileOpen( aBuf, "w" );
|
2006-02-28 09:31:44 +00:00
|
|
|
if ( pIniFile == NULL )
|
|
|
|
break;
|
|
|
|
|
|
|
|
lcl_startSection( pIniFile, eOutput );
|
|
|
|
lcl_writeConfigString( pIniFile, "log_file", pData->aDebugName );
|
|
|
|
lcl_writeConfigBoolean( pIniFile, "overwrite", pData->bOverwrite );
|
|
|
|
lcl_writeConfigString( pIniFile, "include", pData->aInclFilter );
|
|
|
|
lcl_writeConfigString( pIniFile, "exclude", pData->aExclFilter );
|
|
|
|
lcl_writeConfigString( pIniFile, "include_class", pData->aInclClassFilter );
|
|
|
|
lcl_writeConfigString( pIniFile, "exclude_class", pData->aExclClassFilter );
|
|
|
|
lcl_writeConfigOutChannel( pIniFile, "trace", pData->nTraceOut );
|
|
|
|
lcl_writeConfigOutChannel( pIniFile, "warning", pData->nWarningOut );
|
|
|
|
lcl_writeConfigOutChannel( pIniFile, "error", pData->nErrorOut );
|
|
|
|
lcl_writeConfigBoolean( pIniFile, "oslhook", pData->bHookOSLAssert );
|
|
|
|
|
|
|
|
lcl_lineFeed( pIniFile );
|
|
|
|
lcl_startSection( pIniFile, eGUI );
|
|
|
|
lcl_writeConfigString( pIniFile, "debug_window_state", pData->aDbgWinState );
|
|
|
|
|
|
|
|
lcl_lineFeed( pIniFile );
|
|
|
|
lcl_startSection( pIniFile, eObjects );
|
|
|
|
lcl_writeConfigFlag( pIniFile, "check_this", pData->nTestFlags, DBG_TEST_XTOR_THIS );
|
|
|
|
lcl_writeConfigFlag( pIniFile, "check_function", pData->nTestFlags, DBG_TEST_XTOR_FUNC );
|
|
|
|
lcl_writeConfigFlag( pIniFile, "check_exit", pData->nTestFlags, DBG_TEST_XTOR_EXIT );
|
|
|
|
lcl_writeConfigFlag( pIniFile, "generate_report", pData->nTestFlags, DBG_TEST_XTOR_REPORT );
|
|
|
|
lcl_writeConfigFlag( pIniFile, "trace", pData->nTestFlags, DBG_TEST_XTOR_TRACE );
|
|
|
|
|
|
|
|
lcl_lineFeed( pIniFile );
|
|
|
|
lcl_startSection( pIniFile, eTest );
|
|
|
|
lcl_writeConfigFlag( pIniFile, "profiling", pData->nTestFlags, DBG_TEST_PROFILING );
|
|
|
|
lcl_writeConfigFlag( pIniFile, "resources", pData->nTestFlags, DBG_TEST_RESOURCE );
|
|
|
|
lcl_writeConfigFlag( pIniFile, "dialog", pData->nTestFlags, DBG_TEST_DIALOG );
|
|
|
|
lcl_writeConfigFlag( pIniFile, "bold_app_font", pData->nTestFlags, DBG_TEST_BOLDAPPFONT );
|
|
|
|
|
|
|
|
FileClose( pIniFile );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_FUNC_XTORINFO:
|
|
|
|
DebugXTorInfo( (sal_Char*)pParam );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_FUNC_COREDUMP:
|
2006-06-19 12:37:51 +00:00
|
|
|
ImplCoreDump();
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_FUNC_ALLERROROUT:
|
2011-01-21 13:06:20 +01:00
|
|
|
return (void*)(sal_uIntPtr)sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
case DBG_FUNC_SETTESTSOLARMUTEX:
|
2006-06-19 12:37:51 +00:00
|
|
|
pDebugData->pDbgTestSolarMutex = (DbgTestSolarMutexProc)(long)pParam;
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_FUNC_TESTSOLARMUTEX:
|
2006-02-28 09:31:44 +00:00
|
|
|
if ( pDebugData->pDbgTestSolarMutex )
|
|
|
|
pDebugData->pDbgTestSolarMutex();
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_FUNC_PRINTFILE:
|
|
|
|
ImplDbgPrintFile( (const sal_Char*)pParam );
|
|
|
|
break;
|
2006-02-28 09:31:44 +00:00
|
|
|
case DBG_FUNC_UPDATEOSLHOOK:
|
|
|
|
{
|
|
|
|
const DbgData* pData = static_cast< const DbgData* >( pParam );
|
|
|
|
pDebugData->aDbgData.bHookOSLAssert = pData->bHookOSLAssert;
|
|
|
|
if( pDebugData->bOslIsHooked && ! pData->bHookOSLAssert )
|
|
|
|
{
|
|
|
|
osl_setDetailedDebugMessageFunc( pDebugData->pOldDebugMessageFunc );
|
2013-06-29 23:57:38 -05:00
|
|
|
pDebugData->bOslIsHooked = false;
|
2006-02-28 09:31:44 +00:00
|
|
|
}
|
|
|
|
else if( ! pDebugData->bOslIsHooked && pData->bHookOSLAssert )
|
|
|
|
{
|
|
|
|
pDebugData->pOldDebugMessageFunc = osl_setDetailedDebugMessageFunc( &dbg_printOslDebugMessage );
|
2013-06-29 23:57:38 -05:00
|
|
|
pDebugData->bOslIsHooked = true;
|
2006-02-28 09:31:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-28 09:31:44 +00:00
|
|
|
DbgChannelId DbgRegisterUserChannel( DbgPrintLine pProc )
|
|
|
|
{
|
|
|
|
DebugData* pData = ImplGetDebugData();
|
|
|
|
pData->aDbgPrintUserChannels.push_back( pProc );
|
|
|
|
return (DbgChannelId)( pData->aDbgPrintUserChannels.size() - 1 + DBG_OUT_USER_CHANNEL_0 );
|
|
|
|
}
|
|
|
|
|
2011-01-21 13:06:20 +01:00
|
|
|
void DbgProf( sal_uInt16 nAction, DbgDataType* pDbgData )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2001-07-03 13:32:19 +00:00
|
|
|
DebugData* pData = ImplGetDebugData();
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if ( !(pData->aDbgData.nTestFlags & DBG_TEST_PROFILING) )
|
|
|
|
return;
|
|
|
|
|
2001-07-03 13:32:19 +00:00
|
|
|
ProfType* pProfData = (ProfType*)pDbgData->pData;
|
2010-07-29 10:56:19 +08:00
|
|
|
sal_uIntPtr nTime;
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( (nAction != DBG_PROF_START) && !pProfData )
|
|
|
|
{
|
2011-11-23 15:45:43 +01:00
|
|
|
SAL_WARN(
|
2011-11-22 09:34:46 +01:00
|
|
|
"tools.debug",
|
|
|
|
"DBG_PROF...() without DBG_PROFSTART(): " << pDbgData->pName);
|
2000-09-18 16:07:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ( nAction )
|
|
|
|
{
|
|
|
|
case DBG_PROF_START:
|
|
|
|
if ( !pDbgData->pData )
|
|
|
|
{
|
|
|
|
pDbgData->pData = (void*)new ProfType;
|
|
|
|
pProfData = (ProfType*)pDbgData->pData;
|
|
|
|
strncpy( pProfData->aName, pDbgData->pName, DBG_MAXNAME );
|
|
|
|
pProfData->aName[DBG_MAXNAME] = '\0';
|
|
|
|
pProfData->nCount = 0;
|
|
|
|
pProfData->nTime = 0;
|
|
|
|
pProfData->nMinTime = 0xFFFFFFFF;
|
|
|
|
pProfData->nMaxTime = 0;
|
|
|
|
pProfData->nStart = 0xFFFFFFFF;
|
|
|
|
pProfData->nContinueTime = 0;
|
|
|
|
pProfData->nContinueStart = 0xFFFFFFFF;
|
|
|
|
pData->pProfList->Add( (void*)pProfData );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( pProfData->nStart == 0xFFFFFFFF )
|
|
|
|
{
|
|
|
|
pProfData->nStart = ImplGetPerfTime();
|
|
|
|
pProfData->nCount++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_PROF_STOP:
|
|
|
|
nTime = ImplGetPerfTime();
|
|
|
|
|
|
|
|
if ( pProfData->nStart == 0xFFFFFFFF )
|
|
|
|
{
|
2011-11-22 09:34:46 +01:00
|
|
|
SAL_WARN(
|
|
|
|
"tools.debug", "DBG_PROF...() without DBG_PROFSTART()");
|
2000-09-18 16:07:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( pProfData->nContinueStart != 0xFFFFFFFF )
|
|
|
|
{
|
|
|
|
pProfData->nContinueTime += ImplGetPerfTime() - pProfData->nContinueStart;
|
|
|
|
pProfData->nContinueStart = 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
nTime -= pProfData->nStart;
|
|
|
|
nTime -= pProfData->nContinueTime;
|
|
|
|
|
|
|
|
if ( nTime < pProfData->nMinTime )
|
|
|
|
pProfData->nMinTime = nTime;
|
|
|
|
|
|
|
|
if ( nTime > pProfData->nMaxTime )
|
|
|
|
pProfData->nMaxTime = nTime;
|
|
|
|
|
|
|
|
pProfData->nTime += nTime;
|
|
|
|
|
|
|
|
pProfData->nStart = 0xFFFFFFFF;
|
|
|
|
pProfData->nContinueTime = 0;
|
|
|
|
pProfData->nContinueStart = 0xFFFFFFFF;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_PROF_CONTINUE:
|
|
|
|
if ( pProfData->nContinueStart != 0xFFFFFFFF )
|
|
|
|
{
|
|
|
|
pProfData->nContinueTime += ImplGetPerfTime() - pProfData->nContinueStart;
|
|
|
|
pProfData->nContinueStart = 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_PROF_PAUSE:
|
|
|
|
if ( pProfData->nContinueStart == 0xFFFFFFFF )
|
|
|
|
pProfData->nContinueStart = ImplGetPerfTime();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-21 13:06:20 +01:00
|
|
|
void DbgXtor( DbgDataType* pDbgData, sal_uInt16 nAction, const void* pThis,
|
2000-09-18 16:07:07 +00:00
|
|
|
DbgUsr fDbgUsr )
|
|
|
|
{
|
|
|
|
DebugData* pData = ImplGetDebugData();
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// quick test
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( !(pData->aDbgData.nTestFlags & DBG_TEST_XTOR) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
XtorType* pXtorData = (XtorType*)pDbgData->pData;
|
|
|
|
if ( !pXtorData )
|
|
|
|
{
|
|
|
|
pDbgData->pData = (void*)new XtorType;
|
|
|
|
pXtorData = (XtorType*)pDbgData->pData;
|
|
|
|
strncpy( pXtorData->aName, pDbgData->pName, DBG_MAXNAME );
|
|
|
|
pXtorData->aName[DBG_MAXNAME] = '\0';
|
|
|
|
pXtorData->nCtorCalls = 0;
|
|
|
|
pXtorData->nDtorCalls = 0;
|
|
|
|
pXtorData->nMaxCount = 0;
|
|
|
|
pXtorData->nStatics = 0;
|
2013-06-29 23:57:38 -05:00
|
|
|
pXtorData->bTest = true;
|
2000-09-18 16:07:07 +00:00
|
|
|
pData->pXtorList->Add( (void*)pXtorData );
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
if ( !ImplDbgFilter( pData->aDbgData.aInclClassFilter, pXtorData->aName, true ) )
|
|
|
|
pXtorData->bTest = false;
|
|
|
|
if ( ImplDbgFilter( pData->aDbgData.aExclClassFilter, pXtorData->aName, false ) )
|
|
|
|
pXtorData->bTest = false;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
if ( !pXtorData->bTest )
|
|
|
|
return;
|
|
|
|
|
2011-01-21 13:06:20 +01:00
|
|
|
sal_uInt16 nAct = nAction & ~DBG_XTOR_DTOROBJ;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-11-23 15:45:43 +01:00
|
|
|
SAL_INFO_IF(
|
2011-11-22 09:34:46 +01:00
|
|
|
((pData->aDbgData.nTestFlags & DBG_TEST_XTOR_TRACE)
|
|
|
|
&& !(nAction & DBG_XTOR_DTOROBJ) && nAct != DBG_XTOR_CHKOBJ),
|
|
|
|
"tools.debug",
|
|
|
|
(nAct == DBG_XTOR_CTOR ? "Enter Ctor from class "
|
|
|
|
: nAct == DBG_XTOR_DTOR ? "Enter Dtor from class "
|
|
|
|
: "Enter method from class ") << pDbgData->pName);
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// If some Xtor-tests are still tracing
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXTRA )
|
|
|
|
{
|
2012-08-12 01:01:00 +02:00
|
|
|
// call DBG_CTOR before all other DBG_XTOR calls
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( ((nAction & ~DBG_XTOR_DTOROBJ) != DBG_XTOR_CTOR) && !pDbgData->pData )
|
|
|
|
{
|
2011-11-23 15:45:43 +01:00
|
|
|
SAL_WARN(
|
2011-11-22 09:34:46 +01:00
|
|
|
"tools.debug",
|
|
|
|
"DBG_DTOR() or DBG_CHKTHIS() without DBG_CTOR(): "
|
|
|
|
<< pDbgData->pName);
|
2000-09-18 16:07:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// Test if the pointer is still valid
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_THIS )
|
|
|
|
{
|
|
|
|
if ( (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) ||
|
|
|
|
!(nAction & DBG_XTOR_DTOROBJ) )
|
|
|
|
{
|
|
|
|
// This-Pointer == NULL
|
|
|
|
if ( !pThis )
|
|
|
|
{
|
2011-11-23 15:45:43 +01:00
|
|
|
SAL_WARN(
|
2011-11-22 09:34:46 +01:00
|
|
|
"tools.debug",
|
|
|
|
"this == NULL in class " << pDbgData->pName);
|
2000-09-18 16:07:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( (nAction & ~DBG_XTOR_DTOROBJ) != DBG_XTOR_CTOR )
|
|
|
|
{
|
2011-11-23 15:45:43 +01:00
|
|
|
SAL_WARN_IF(
|
2011-11-22 09:34:46 +01:00
|
|
|
!pXtorData->aThisList.IsIn(pThis), "tools.debug",
|
|
|
|
"invalid this-Pointer %p in class " << pDbgData->pName);
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// execute function test and update maintenance data
|
2000-09-18 16:07:07 +00:00
|
|
|
const sal_Char* pMsg = NULL;
|
|
|
|
switch ( nAction & ~DBG_XTOR_DTOROBJ )
|
|
|
|
{
|
|
|
|
case DBG_XTOR_CTOR:
|
|
|
|
if ( nAction & DBG_XTOR_DTOROBJ )
|
|
|
|
{
|
|
|
|
if ( fDbgUsr &&
|
|
|
|
(pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) &&
|
|
|
|
(pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
|
|
|
|
pMsg = fDbgUsr( pThis );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pXtorData->nCtorCalls++;
|
|
|
|
if ( !bDbgImplInMain )
|
|
|
|
pXtorData->nStatics++;
|
|
|
|
if ( (pXtorData->nCtorCalls-pXtorData->nDtorCalls) > pXtorData->nMaxCount )
|
|
|
|
pXtorData->nMaxCount = pXtorData->nCtorCalls - pXtorData->nDtorCalls;
|
|
|
|
|
|
|
|
if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_THIS )
|
|
|
|
pXtorData->aThisList.Add( pThis );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_XTOR_DTOR:
|
|
|
|
if ( nAction & DBG_XTOR_DTOROBJ )
|
|
|
|
{
|
|
|
|
pXtorData->nDtorCalls++;
|
|
|
|
if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_THIS )
|
|
|
|
pXtorData->aThisList.Remove( pThis );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( fDbgUsr &&
|
|
|
|
(pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
|
|
|
|
pMsg = fDbgUsr( pThis );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBG_XTOR_CHKTHIS:
|
|
|
|
case DBG_XTOR_CHKOBJ:
|
|
|
|
if ( nAction & DBG_XTOR_DTOROBJ )
|
|
|
|
{
|
|
|
|
if ( fDbgUsr &&
|
|
|
|
(pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) &&
|
|
|
|
(pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
|
|
|
|
pMsg = fDbgUsr( pThis );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( fDbgUsr &&
|
|
|
|
(pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
|
|
|
|
pMsg = fDbgUsr( pThis );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-11-23 15:45:43 +01:00
|
|
|
SAL_WARN_IF(
|
2011-11-22 09:34:46 +01:00
|
|
|
pMsg, "tools.debug",
|
|
|
|
"Error-Msg from Object " << pThis << " in class "
|
|
|
|
<< pDbgData->pName << ": " << pMsg);
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-11-23 15:45:43 +01:00
|
|
|
SAL_INFO_IF(
|
2011-11-22 09:34:46 +01:00
|
|
|
((pData->aDbgData.nTestFlags & DBG_TEST_XTOR_TRACE)
|
|
|
|
&& (nAction & DBG_XTOR_DTOROBJ) && nAct != DBG_XTOR_CHKOBJ),
|
|
|
|
"tools.debug",
|
|
|
|
(nAct == DBG_XTOR_CTOR
|
|
|
|
? "Leave Ctor from class "
|
|
|
|
: nAct == DBG_XTOR_DTOR
|
|
|
|
? "Leave Dtor from class "
|
|
|
|
: "Leave method from class ") << pDbgData->pName);
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-01-21 13:06:20 +01:00
|
|
|
void DbgOut( const sal_Char* pMsg, sal_uInt16 nDbgOut, const sal_Char* pFile, sal_uInt16 nLine )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2013-06-29 23:57:38 -05:00
|
|
|
static bool bIn = false;
|
2001-07-03 13:32:19 +00:00
|
|
|
if ( bIn )
|
|
|
|
return;
|
2013-06-29 23:57:38 -05:00
|
|
|
bIn = true;
|
2001-07-03 13:32:19 +00:00
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
DebugData* pData = GetDebugData();
|
2006-06-19 12:37:51 +00:00
|
|
|
sal_Char const * pStr;
|
2010-07-29 10:56:19 +08:00
|
|
|
sal_uIntPtr nOut;
|
2000-09-18 16:07:07 +00:00
|
|
|
int nBufLen = 0;
|
|
|
|
|
|
|
|
if ( nDbgOut == DBG_OUT_ERROR )
|
|
|
|
{
|
|
|
|
nOut = pData->aDbgData.nErrorOut;
|
|
|
|
pStr = "Error: ";
|
|
|
|
}
|
|
|
|
else if ( nDbgOut == DBG_OUT_WARNING )
|
|
|
|
{
|
|
|
|
nOut = pData->aDbgData.nWarningOut;
|
|
|
|
pStr = "Warning: ";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nOut = pData->aDbgData.nTraceOut;
|
|
|
|
pStr = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( nOut == DBG_OUT_NULL )
|
|
|
|
{
|
2013-06-29 23:57:38 -05:00
|
|
|
bIn = false;
|
2000-09-18 16:07:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-02-28 09:31:44 +00:00
|
|
|
if ( ImplDbgFilterMessage( pMsg ) )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2013-06-29 23:57:38 -05:00
|
|
|
bIn = false;
|
2006-02-28 09:31:44 +00:00
|
|
|
return;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ImplDbgLock();
|
|
|
|
|
2001-07-03 13:32:19 +00:00
|
|
|
sal_Char aBufOut[DBG_BUF_MAXLEN];
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( pStr )
|
|
|
|
{
|
|
|
|
strcpy( aBufOut, pStr );
|
|
|
|
nBufLen = strlen( pStr );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
aBufOut[0] = '\0';
|
|
|
|
|
|
|
|
int nMsgLen = strlen( pMsg );
|
|
|
|
if ( nBufLen+nMsgLen > DBG_BUF_MAXLEN )
|
|
|
|
{
|
2011-04-14 22:52:46 -07:00
|
|
|
int nCopyLen = DBG_BUF_MAXLEN-nBufLen-4;
|
2000-09-18 16:07:07 +00:00
|
|
|
strncpy( &(aBufOut[nBufLen]), pMsg, nCopyLen );
|
|
|
|
strcpy( &(aBufOut[nBufLen+nCopyLen]), "..." );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strcpy( &(aBufOut[nBufLen]), pMsg );
|
|
|
|
|
|
|
|
if ( pFile && nLine && (nBufLen+nMsgLen < DBG_BUF_MAXLEN) )
|
|
|
|
{
|
|
|
|
if ( nOut == DBG_OUT_MSGBOX )
|
|
|
|
strcat( aBufOut, "\n" );
|
|
|
|
else
|
|
|
|
strcat( aBufOut, " " );
|
|
|
|
strcat( aBufOut, "From File " );
|
|
|
|
strcat( aBufOut, pFile );
|
|
|
|
strcat( aBufOut, " at Line " );
|
|
|
|
|
2012-08-12 01:01:00 +02:00
|
|
|
// Convert line to String and append
|
2001-07-03 13:32:19 +00:00
|
|
|
sal_Char aLine[9];
|
|
|
|
sal_Char* pLine = &aLine[7];
|
2011-01-21 13:06:20 +01:00
|
|
|
sal_uInt16 i;
|
2000-09-18 16:07:07 +00:00
|
|
|
memset( aLine, 0, sizeof( aLine ) );
|
|
|
|
do
|
|
|
|
{
|
|
|
|
i = nLine % 10;
|
|
|
|
pLine--;
|
|
|
|
*(pLine) = (sal_Char)i + 48;
|
|
|
|
nLine /= 10;
|
|
|
|
}
|
|
|
|
while ( nLine );
|
|
|
|
strcat( aBufOut, pLine );
|
|
|
|
}
|
|
|
|
|
2006-02-28 09:31:44 +00:00
|
|
|
if ( ( nOut >= DBG_OUT_USER_CHANNEL_0 ) && ( nOut - DBG_OUT_USER_CHANNEL_0 < pData->aDbgPrintUserChannels.size() ) )
|
|
|
|
{
|
|
|
|
DbgPrintLine pPrinter = pData->aDbgPrintUserChannels[ nOut - DBG_OUT_USER_CHANNEL_0 ];
|
|
|
|
if ( pPrinter )
|
|
|
|
pPrinter( aBufOut );
|
|
|
|
else
|
|
|
|
nOut = DBG_OUT_DEBUGGER;
|
|
|
|
}
|
|
|
|
|
2011-02-20 23:09:20 +01:00
|
|
|
if ( nOut == DBG_OUT_ABORT )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2011-02-20 23:09:20 +01:00
|
|
|
if ( pData->pDbgAbort != NULL )
|
|
|
|
pData->pDbgAbort( aBufOut );
|
|
|
|
abort();
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( nOut == DBG_OUT_DEBUGGER )
|
|
|
|
{
|
|
|
|
if ( !ImplActivateDebugger( aBufOut ) )
|
|
|
|
nOut = DBG_OUT_TESTTOOL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( nOut == DBG_OUT_TESTTOOL )
|
|
|
|
{
|
|
|
|
if ( pData->pDbgPrintTestTool )
|
|
|
|
pData->pDbgPrintTestTool( aBufOut );
|
|
|
|
else
|
|
|
|
nOut = DBG_OUT_MSGBOX;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( nOut == DBG_OUT_MSGBOX )
|
|
|
|
{
|
|
|
|
if ( pData->pDbgPrintMsgBox )
|
|
|
|
pData->pDbgPrintMsgBox( aBufOut );
|
|
|
|
else
|
|
|
|
nOut = DBG_OUT_WINDOW;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( nOut == DBG_OUT_WINDOW )
|
|
|
|
{
|
|
|
|
if ( pData->pDbgPrintWindow )
|
|
|
|
pData->pDbgPrintWindow( aBufOut );
|
|
|
|
else
|
|
|
|
nOut = DBG_OUT_FILE;
|
|
|
|
}
|
|
|
|
|
2010-01-27 16:23:59 +01:00
|
|
|
switch ( nOut )
|
|
|
|
{
|
|
|
|
case DBG_OUT_SHELL:
|
|
|
|
DbgPrintShell( aBufOut );
|
|
|
|
break;
|
|
|
|
case DBG_OUT_FILE:
|
2000-09-18 16:07:07 +00:00
|
|
|
ImplDbgPrintFile( aBufOut );
|
2010-01-27 16:23:59 +01:00
|
|
|
break;
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
ImplDbgUnlock();
|
|
|
|
|
2013-06-29 23:57:38 -05:00
|
|
|
bIn = false;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2010-01-27 16:23:59 +01:00
|
|
|
void DbgPrintShell(char const * message) {
|
|
|
|
fprintf(stderr, "%s\n", message);
|
|
|
|
#if defined WNT
|
|
|
|
OutputDebugStringA(message);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-01-21 13:06:20 +01:00
|
|
|
void DbgOutTypef( sal_uInt16 nDbgOut, const sal_Char* pFStr, ... )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
va_list pList;
|
|
|
|
|
|
|
|
va_start( pList, pFStr );
|
2001-07-03 13:32:19 +00:00
|
|
|
sal_Char aBuf[DBG_BUF_MAXLEN];
|
2000-09-18 16:07:07 +00:00
|
|
|
vsprintf( aBuf, pFStr, pList );
|
|
|
|
va_end( pList );
|
|
|
|
|
|
|
|
DbgOut( aBuf, nDbgOut );
|
|
|
|
}
|
|
|
|
|
|
|
|
void DbgOutf( const sal_Char* pFStr, ... )
|
|
|
|
{
|
|
|
|
va_list pList;
|
|
|
|
|
|
|
|
va_start( pList, pFStr );
|
2001-07-03 13:32:19 +00:00
|
|
|
sal_Char aBuf[DBG_BUF_MAXLEN];
|
2000-09-18 16:07:07 +00:00
|
|
|
vsprintf( aBuf, pFStr, pList );
|
|
|
|
va_end( pList );
|
|
|
|
|
|
|
|
DbgOut( aBuf );
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2011-01-07 15:13:58 +01:00
|
|
|
void* DbgFunc( sal_uInt16, void* ) { return NULL; }
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-01-07 15:13:58 +01:00
|
|
|
void DbgProf( sal_uInt16, DbgDataType* ) {}
|
|
|
|
void DbgXtor( DbgDataType*, sal_uInt16, const void*, DbgUsr ) {}
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-01-07 15:13:58 +01:00
|
|
|
void DbgOut( const sal_Char*, sal_uInt16, const sal_Char*, sal_uInt16 ) {}
|
|
|
|
void DbgOutTypef( sal_uInt16, const sal_Char*, ... ) {}
|
2000-09-18 16:07:07 +00:00
|
|
|
void DbgOutf( const sal_Char*, ... ) {}
|
|
|
|
|
|
|
|
#endif
|
2010-10-14 08:27:31 +02:00
|
|
|
|
2013-05-21 08:40:07 +02:00
|
|
|
|
|
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
|
|
|
2013-06-07 14:44:48 +02:00
|
|
|
TOOLS_DLLPUBLIC void DbgUnhandledException(const css::uno::Any & caught, const char* currentFunction, const char* fileAndLineNo)
|
2013-05-21 08:40:07 +02:00
|
|
|
{
|
|
|
|
OString sMessage( "caught an exception!" );
|
|
|
|
sMessage += "\nin function:";
|
|
|
|
sMessage += currentFunction;
|
|
|
|
sMessage += "\ntype: ";
|
|
|
|
sMessage += OUStringToOString( caught.getValueTypeName(), osl_getThreadTextEncoding() );
|
|
|
|
::com::sun::star::uno::Exception exception;
|
|
|
|
caught >>= exception;
|
|
|
|
if ( !exception.Message.isEmpty() )
|
|
|
|
{
|
|
|
|
sMessage += "\nmessage: ";
|
|
|
|
sMessage += OUStringToOString( exception.Message, osl_getThreadTextEncoding() );
|
|
|
|
}
|
|
|
|
if ( exception.Context.is() )
|
|
|
|
{
|
|
|
|
const char* pContext = typeid( *exception.Context.get() ).name();
|
|
|
|
sMessage += "\ncontext: ";
|
|
|
|
sMessage += pContext;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
::com::sun::star::configuration::CorruptedConfigurationException
|
|
|
|
specialized;
|
|
|
|
if ( caught >>= specialized )
|
|
|
|
{
|
|
|
|
sMessage += "\ndetails: ";
|
|
|
|
sMessage += OUStringToOString(
|
|
|
|
specialized.Details, osl_getThreadTextEncoding() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
::com::sun::star::task::ErrorCodeIOException specialized;
|
|
|
|
if ( caught >>= specialized )
|
|
|
|
{
|
|
|
|
sMessage += "\ndetails: ";
|
2013-08-21 15:07:31 +02:00
|
|
|
sMessage += OString::number( specialized.ErrCode );
|
2013-05-21 08:40:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
sMessage += "\n";
|
2013-06-07 14:44:48 +02:00
|
|
|
|
|
|
|
SAL_DETAIL_LOG_FORMAT(
|
|
|
|
SAL_DETAIL_ENABLE_LOG_WARN, SAL_DETAIL_LOG_LEVEL_WARN,
|
|
|
|
"legacy.osl", fileAndLineNo, "%s", sMessage.getStr());
|
2013-05-21 08:40:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // OSL_DEBUG_LEVEL
|
|
|
|
|
|
|
|
|
2010-10-14 08:27:31 +02:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|