1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #if defined (UNX) || defined (__GNUC__)
37 #include <com/sun/star/task/ErrorCodeIOException.hpp>
38 #include <tools/debug.hxx>
39 #include <rtl/string.h>
40 #include <sal/log.hxx>
41 #include <sal/macros.h>
45 #include <osl/diagnose.h>
46 #include <tools/diagnose_ex.h>
54 DbgTestSolarMutexProc pDbgTestSolarMutex
;
58 ,pDbgTestSolarMutex( NULL
)
60 aDbgData
.nTestFlags
= DBG_TEST_RESOURCE
;
61 aDbgData
.aDbgWinState
[0] = 0;
65 static DebugData aDebugData
;
67 #define FILE_LINEEND "\n"
69 typedef FILE* FILETYPE
;
70 #define FileOpen fopen
71 #define FileRead fread
72 #define FilePrintF fprintf
73 #define FileClose fclose
85 void lcl_lineFeed( FILETYPE _pFile
)
87 FilePrintF( _pFile
, "%s", FILE_LINEEND
);
90 const sal_Char
* lcl_getSectionName( ConfigSection _eSection
)
92 const sal_Char
* pSectionName
= NULL
;
95 case eGUI
: pSectionName
= "gui"; break;
96 case eTest
: pSectionName
= "test"; break;
104 ConfigSection
lcl_getSectionFromName( const sal_Char
* _pSectionName
, size_t _nSectionNameLength
)
106 if ( strncmp( _pSectionName
, "gui", _nSectionNameLength
< 3 ? _nSectionNameLength
: 3 ) == 0 )
108 if ( strncmp( _pSectionName
, "test", _nSectionNameLength
< 4 ? _nSectionNameLength
: 4 ) == 0 )
113 void lcl_startSection( FILETYPE _pFile
, ConfigSection _eSection
)
115 FilePrintF( _pFile
, "[%s]%s", lcl_getSectionName( _eSection
), FILE_LINEEND
);
118 void lcl_writeConfigString( FILETYPE _pFile
, const sal_Char
* _pKeyName
, const sal_Char
* _pValue
)
120 FilePrintF( _pFile
, "%s=%s%s", _pKeyName
, _pValue
, FILE_LINEEND
);
123 void lcl_writeConfigBoolean( FILETYPE _pFile
, const sal_Char
* _pKeyName
, bool _bValue
)
125 lcl_writeConfigString( _pFile
, _pKeyName
, _bValue
? "1" : "0" );
128 void lcl_writeConfigFlag( FILETYPE _pFile
, const sal_Char
* _pKeyName
, sal_uIntPtr _nAllFlags
, sal_uIntPtr _nCheckFlag
)
130 lcl_writeConfigBoolean( _pFile
, _pKeyName
, ( _nAllFlags
& _nCheckFlag
) != 0 );
133 bool lcl_isConfigSection( const sal_Char
* _pLine
, size_t _nLineLen
)
136 // not even enough space for '[' and ']'
138 if ( ( _pLine
[0] == '[' ) && ( _pLine
[ _nLineLen
- 1 ] == ']' ) )
143 bool lcl_isConfigKey( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
)
145 size_t nKeyLength
= strlen( _pKeyName
);
146 if ( nKeyLength
+ 1 >= _nLineLen
)
147 // not even long enough for the key name plus "=" plus a one-character value
149 if ( ( strncmp( _pLine
, _pKeyName
, nKeyLength
) == 0 ) && ( _pLine
[ nKeyLength
] == '=' ) )
154 sal_Int32
lcl_tryReadConfigString( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, sal_Char
* _pValue
, size_t _nValueLen
)
156 if ( !lcl_isConfigKey( _pLine
, _nLineLen
, _pKeyName
) )
158 size_t nValuePos
= strlen( _pKeyName
) + 1;
159 size_t nValueLen
= _nLineLen
- nValuePos
;
160 const sal_Char
* pValue
= _pLine
+ nValuePos
;
161 strncpy( _pValue
, pValue
, ( _nValueLen
> nValueLen
) ? nValueLen
: _nValueLen
);
162 _pValue
[ ( _nValueLen
> nValueLen
) ? nValueLen
: _nValueLen
- 1 ] = 0;
163 return strlen( _pValue
);
166 void lcl_tryReadConfigFlag( const sal_Char
* _pLine
, size_t _nLineLen
, const sal_Char
* _pKeyName
, sal_uIntPtr
* _out_pnAllFlags
, sal_uIntPtr _nCheckFlag
)
169 size_t nValueLen
= lcl_tryReadConfigString( _pLine
, _nLineLen
, _pKeyName
, aBuf
, sizeof( aBuf
) );
172 if ( strcmp( aBuf
, "1" ) == 0 )
173 *_out_pnAllFlags
|= _nCheckFlag
;
175 *_out_pnAllFlags
&= ~_nCheckFlag
;
180 static void DbgGetDbgFileName( sal_Char
* pStr
, sal_Int32 nMaxLen
)
183 const sal_Char
* pName
= getenv("DBGSV_INIT");
185 pName
= ".dbgsv.init";
186 strncpy( pStr
, pName
, nMaxLen
);
188 const sal_Char
* pName
= getenv("DBGSV_INIT");
190 strncpy( pStr
, pName
, nMaxLen
);
192 GetProfileStringA( "sv", "dbgsv", "dbgsv.ini", pStr
, nMaxLen
);
194 strncpy( pStr
, "dbgsv.ini", nMaxLen
);
196 pStr
[ nMaxLen
- 1 ] = 0;
199 static DebugData
* GetDebugData()
201 if ( !aDebugData
.bInit
)
203 aDebugData
.bInit
= true;
206 sal_Char aBuf
[ 4096 ];
207 DbgGetDbgFileName( aBuf
, sizeof( aBuf
) );
208 FILETYPE pIniFile
= FileOpen( aBuf
, "r" );
209 if ( pIniFile
!= NULL
)
211 ConfigSection eCurrentSection
= eUnknown
;
213 // no sophisticated algorithm here, assume that the whole file fits into aBuf ...
214 sal_uIntPtr nReallyRead
= FileRead( aBuf
, 1, sizeof( aBuf
) / sizeof( sal_Char
) - 1, pIniFile
);
215 aBuf
[ nReallyRead
] = 0;
216 const sal_Char
* pLine
= aBuf
;
217 while ( const sal_Char
* pNextLine
= strstr( pLine
, FILE_LINEEND
) )
219 size_t nLineLength
= pNextLine
- pLine
;
221 if ( lcl_isConfigSection( pLine
, nLineLength
) )
222 eCurrentSection
= lcl_getSectionFromName( pLine
+ 1, nLineLength
- 2 );
224 // elements of the [gui] section
225 if ( eCurrentSection
== eGUI
)
227 lcl_tryReadConfigString( pLine
, nLineLength
, "debug_window_state", aDebugData
.aDbgData
.aDbgWinState
, sizeof( aDebugData
.aDbgData
.aDbgWinState
) );
230 // elements of the [test] section
231 if ( eCurrentSection
== eTest
)
233 lcl_tryReadConfigFlag( pLine
, nLineLength
, "resources", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_RESOURCE
);
234 lcl_tryReadConfigFlag( pLine
, nLineLength
, "dialog", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_DIALOG
);
235 lcl_tryReadConfigFlag( pLine
, nLineLength
, "bold_app_font", &aDebugData
.aDbgData
.nTestFlags
, DBG_TEST_BOLDAPPFONT
);
238 pLine
= pNextLine
+ strlen( FILE_LINEEND
);
241 FileClose( pIniFile
);
248 inline DebugData
* ImplGetDebugData()
250 if ( !aDebugData
.bInit
)
251 return GetDebugData();
256 void* DbgFunc( sal_uInt16 nAction
, void* pParam
)
258 DebugData
* pDebugData
= ImplGetDebugData();
260 if ( nAction
== DBG_FUNC_GETDATA
)
261 return (void*)&(pDebugData
->aDbgData
);
266 case DBG_FUNC_SAVEDATA
:
268 const DbgData
* pData
= static_cast< const DbgData
* >( pParam
);
270 sal_Char aBuf
[ 4096 ];
271 DbgGetDbgFileName( aBuf
, sizeof( aBuf
) );
272 FILETYPE pIniFile
= FileOpen( aBuf
, "w" );
273 if ( pIniFile
== NULL
)
276 lcl_lineFeed( pIniFile
);
277 lcl_startSection( pIniFile
, eGUI
);
278 lcl_writeConfigString( pIniFile
, "debug_window_state", pData
->aDbgWinState
);
280 lcl_lineFeed( pIniFile
);
281 lcl_startSection( pIniFile
, eTest
);
282 lcl_writeConfigFlag( pIniFile
, "resources", pData
->nTestFlags
, DBG_TEST_RESOURCE
);
283 lcl_writeConfigFlag( pIniFile
, "dialog", pData
->nTestFlags
, DBG_TEST_DIALOG
);
284 lcl_writeConfigFlag( pIniFile
, "bold_app_font", pData
->nTestFlags
, DBG_TEST_BOLDAPPFONT
);
286 FileClose( pIniFile
);
290 case DBG_FUNC_SETTESTSOLARMUTEX
:
291 pDebugData
->pDbgTestSolarMutex
= reinterpret_cast<DbgTestSolarMutexProc
>(reinterpret_cast<sal_uIntPtr
>(pParam
));
294 case DBG_FUNC_TESTSOLARMUTEX
:
296 pDebugData
->pDbgTestSolarMutex
== 0, "tools.debug",
297 "no DbgTestSolarMutex function set");
298 if ( pDebugData
->pDbgTestSolarMutex
)
299 pDebugData
->pDbgTestSolarMutex();
309 #if OSL_DEBUG_LEVEL > 0
311 void DbgUnhandledException(const css::uno::Any
& caught
, const char* currentFunction
, const char* fileAndLineNo
)
313 OString
sMessage( "caught an exception!" );
314 sMessage
+= "\nin function:";
315 sMessage
+= currentFunction
;
316 sMessage
+= "\ntype: ";
317 sMessage
+= OUStringToOString( caught
.getValueTypeName(), osl_getThreadTextEncoding() );
318 ::com::sun::star::uno::Exception exception
;
319 caught
>>= exception
;
320 if ( !exception
.Message
.isEmpty() )
322 sMessage
+= "\nmessage: ";
323 sMessage
+= OUStringToOString( exception
.Message
, osl_getThreadTextEncoding() );
325 if ( exception
.Context
.is() )
327 const char* pContext
= typeid( *exception
.Context
.get() ).name();
328 sMessage
+= "\ncontext: ";
329 sMessage
+= pContext
;
332 ::com::sun::star::configuration::CorruptedConfigurationException
334 if ( caught
>>= specialized
)
336 sMessage
+= "\ndetails: ";
337 sMessage
+= OUStringToOString(
338 specialized
.Details
, osl_getThreadTextEncoding() );
342 ::com::sun::star::task::ErrorCodeIOException specialized
;
343 if ( caught
>>= specialized
)
345 sMessage
+= "\ndetails: ";
346 sMessage
+= OString::number( specialized
.ErrCode
);
351 SAL_DETAIL_LOG_FORMAT(
352 SAL_DETAIL_ENABLE_LOG_WARN
, SAL_DETAIL_LOG_LEVEL_WARN
,
353 "legacy.osl", fileAndLineNo
, "%s", sMessage
.getStr());
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */