diff options
author | Andreas Bregas <ab@openoffice.org> | 2010-08-23 11:16:00 +0200 |
---|---|---|
committer | Andreas Bregas <ab@openoffice.org> | 2010-08-23 11:16:00 +0200 |
commit | fadc14f47bd7f355523357ff961ac3eaf47f34ba (patch) | |
tree | cea67a8666b6cfb1289a4a26d9fdde374d97db51 /basic | |
parent | mib19: #163377# Support procedure properties for UserForm modules (diff) | |
download | core-fadc14f47bd7f355523357ff961ac3eaf47f34ba.tar.gz core-fadc14f47bd7f355523357ff961ac3eaf47f34ba.zip |
mib19: #163377# Enhanced trace functionality
Diffstat (limited to 'basic')
-rwxr-xr-x | basic/source/classes/sbxmod.cxx | 4 | ||||
-rwxr-xr-x | basic/source/comp/sbcomp.cxx | 238 | ||||
-rwxr-xr-x | basic/source/inc/sbtrace.hxx | 4 | ||||
-rwxr-xr-x | basic/source/runtime/methods1.cxx | 6 | ||||
-rw-r--r-- | basic/source/runtime/rtlproto.hxx | 5 | ||||
-rw-r--r-- | basic/source/runtime/stdobj.cxx | 4 |
6 files changed, 249 insertions, 12 deletions
diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx index bdbdde57cc1b..9bc512adaab5 100755 --- a/basic/source/classes/sbxmod.cxx +++ b/basic/source/classes/sbxmod.cxx @@ -1188,6 +1188,10 @@ USHORT SbModule::Run( SbMethod* pMeth ) SendHint( GetParent(), SBX_HINT_BASICSTOP, pMeth ); GlobalRunDeInit(); + +#ifdef DBG_TRACE_BASIC + dbg_DeInitTrace(); +#endif } } else diff --git a/basic/source/comp/sbcomp.cxx b/basic/source/comp/sbcomp.cxx index 5b7e5c70591d..27f68ed069ee 100755 --- a/basic/source/comp/sbcomp.cxx +++ b/basic/source/comp/sbcomp.cxx @@ -42,11 +42,145 @@ #include <hash_map> -// Trace Settings -static const char* GpTraceFileName = "d:\\zBasic.Asm\\BasicTrace.txt"; -static const bool GbIncludePCodes = false; -static const int GnIndentPerCallLevel = 4; -static const int GnIndentForPCode = 2; +// Trace ini file (set NULL to ignore) +static char GpTraceIniFile[] = "d:\\zBasic.Asm\\BasicTrace.ini"; +//static char* GpTraceIniFile = NULL; + + +// Trace Settings, used if no ini file / not found in ini file +static char GpTraceFileNameDefault[] = "d:\\zBasic.Asm\\BasicTrace.txt"; +static char* GpTraceFileName = GpTraceFileNameDefault; + +// GbTraceOn: +// true = tracing is active, false = tracing is disabled, default = true +// Set to false initially if you want to activate tracing on demand with +// TraceCommand( "TraceOn" ), see below +static bool GbTraceOn = true; + +// GbIncludePCodes: +// true = PCodes are written to trace, default = false, correspondents +// with TraceCommand( "PCodeOn" / "PCodeOff" ), see below +static bool GbIncludePCodes = false; + +static int GnIndentPerCallLevel = 4; +static int GnIndentForPCode = 2; + +/* + With trace enabled the runtime function TraceCommand + can be used to influence the trace functionality + from within the running Basic macro. + + Format: TraceCommand( command as String [, param as Variant] ) + + Supported commands (command is NOT case sensitive): + TraceCommand "TraceOn" sets GbTraceOn = true + TraceCommand "TraceOff" sets GbTraceOn = false + + TraceCommand "PCodeOn" sets GbIncludePCodes = true + TraceCommand "PCodeOff" sets GbIncludePCodes = false + + TraceCommand "Print", aVal writes aVal into the trace file as + long as it can be converted to string +*/ + +static void lcl_skipWhites( char*& rpc ) +{ + while( *rpc == ' ' || *rpc == '\t' ) + ++rpc; +} + +inline void lcl_findNextLine( char*& rpc, char* pe ) +{ + // Find line end + while( rpc < pe && *rpc != 13 && *rpc != 10 ) + ++rpc; + + // Read all + while( rpc < pe && (*rpc == 13 || *rpc == 10) ) + ++rpc; +} + +inline bool lcl_isAlpha( char c ) +{ + bool bRet = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); + return bRet; +} + +static void lcl_ReadIniFile( const char* pIniFileName ) +{ + const int BUF_SIZE = 1000; + static sal_Char TraceFileNameBuffer[BUF_SIZE]; + sal_Char Buffer[BUF_SIZE]; + sal_Char VarNameBuffer[BUF_SIZE]; + sal_Char ValBuffer[BUF_SIZE]; + + FILE* pFile = fopen( pIniFileName ,"rb" ); + if( pFile == NULL ) + return; + + size_t nRead = fread( Buffer, 1, BUF_SIZE, pFile ); + + // Scan + char* pc = Buffer; + char* pe = Buffer + nRead; + while( pc < pe ) + { + lcl_skipWhites( pc ); if( pc == pe ) break; + + // Read variable + char* pVarStart = pc; + while( pc < pe && lcl_isAlpha( *pc ) ) + ++pc; + int nVarLen = pc - pVarStart; + if( nVarLen == 0 ) + { + lcl_findNextLine( pc, pe ); + continue; + } + strncpy( VarNameBuffer, pVarStart, nVarLen ); + VarNameBuffer[nVarLen] = '\0'; + + // Check = + lcl_skipWhites( pc ); if( pc == pe ) break; + if( *pc != '=' ) + continue; + ++pc; + lcl_skipWhites( pc ); if( pc == pe ) break; + + // Read value + char* pValStart = pc; + while( pc < pe && *pc != 13 && *pc != 10 ) + ++pc; + int nValLen = pc - pValStart; + if( nValLen == 0 ) + { + lcl_findNextLine( pc, pe ); + continue; + } + strncpy( ValBuffer, pValStart, nValLen ); + ValBuffer[nValLen] = '\0'; + + // Match variables + if( strcmp( VarNameBuffer, "GpTraceFileName") == 0 ) + { + strcpy( TraceFileNameBuffer, ValBuffer ); + GpTraceFileName = TraceFileNameBuffer; + } + else + if( strcmp( VarNameBuffer, "GbTraceOn") == 0 ) + GbTraceOn = (strcmp( ValBuffer, "true" ) == 0); + else + if( strcmp( VarNameBuffer, "GbIncludePCodes") == 0 ) + GbIncludePCodes = (strcmp( ValBuffer, "true" ) == 0); + else + if( strcmp( VarNameBuffer, "GnIndentPerCallLevel") == 0 ) + GnIndentPerCallLevel = strtol( ValBuffer, NULL, 10 ); + else + if( strcmp( VarNameBuffer, "GnIndentForPCode") == 0 ) + GnIndentForPCode = strtol( ValBuffer, NULL, 10 ); + } + fclose( pFile ); +} struct TraceTextData { @@ -122,7 +256,7 @@ static rtl::OString lcl_toOStringSkipLeadingWhites( const String& aStr ) return aORetStr; } -String dumpMethodParameters( SbMethod* pMethod ) +String lcl_dumpMethodParameters( SbMethod* pMethod ) { String aStr; if( pMethod == NULL ) @@ -166,16 +300,36 @@ String dumpMethodParameters( SbMethod* pMethod ) return aStr; } + // Public functions + +static bool GbSavTraceOn = false; void dbg_InitTrace( void ) { + if( GpTraceIniFile != NULL ) + lcl_ReadIniFile( GpTraceIniFile ); + FILE* pFile = fopen( GpTraceFileName, "w" ); if( pFile != NULL ) fclose( pFile ); + GbSavTraceOn = GbTraceOn; + if( !GbTraceOn ) + lcl_lineOut( GpTraceFileName, "### Program started with trace off ###" ); +} + +void dbg_DeInitTrace( void ) +{ + GbTraceOn = GbSavTraceOn; } +static INT32 GnLastCallLvl = 0; + void dbg_traceStep( SbModule* pModule, UINT32 nPC, INT32 nCallLvl ) { + if( !GbTraceOn ) + return; + GnLastCallLvl = nCallLvl; + SbModule* pTraceMod = pModule; if( pTraceMod->ISA(SbClassModuleObject) ) { @@ -206,14 +360,11 @@ void dbg_traceStep( SbModule* pModule, UINT32 nPC, INT32 nCallLvl ) { const char* pModuleNameStr = OUStringToOString( rtl::OUString( aModuleName ), RTL_TEXTENCODING_ASCII_US ).getStr(); char Buffer[200]; - sprintf( Buffer, "TRACE ERROR: No info for PC = %d in module \"%s\"", nPC, pModuleNameStr ); + sprintf( Buffer, "TRACE ERROR: No info for PC = %d in module \"%s\"", (int)nPC, pModuleNameStr ); lcl_lineOut( GpTraceFileName, Buffer ); return; } - //nCallLvl--; - //if( nCallLvl < 0 ) - // nCallLvl = 0; int nIndent = nCallLvl * GnIndentPerCallLevel; const TraceTextData& rTraceTextData = itInner->second; @@ -234,6 +385,10 @@ void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, INT32 nCallLvl, { static const char* pSeparator = "' ================================================================================"; + if( !GbTraceOn ) + return; + GnLastCallLvl = nCallLvl; + SbModule* pTraceMod = pModule; SbClassModuleObject* pClassModuleObj = NULL; if( pTraceMod->ISA(SbClassModuleObject) ) @@ -281,7 +436,7 @@ void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, INT32 nCallLvl, aStr.AppendAscii( "]" ); } if( !bLeave ) - aStr += dumpMethodParameters( pMethod ); + aStr += lcl_dumpMethodParameters( pMethod ); lcl_lineOut( GpTraceFileName, OUStringToOString( rtl::OUString( aStr ), RTL_TEXTENCODING_ASCII_US ).getStr(), lcl_getSpaces( nIndent ) ); if( !bLeave ) @@ -293,6 +448,10 @@ void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, INT32 nCallLvl, void dbg_traceNotifyError( SbError nTraceErr, const String& aTraceErrMsg, bool bTraceErrHandled, INT32 nCallLvl ) { + if( !GbTraceOn ) + return; + GnLastCallLvl = nCallLvl; + rtl::OString aOTraceErrMsg = OUStringToOString( rtl::OUString( aTraceErrMsg ), RTL_TEXTENCODING_ASCII_US ); char Buffer[200]; @@ -329,6 +488,63 @@ void dbg_RegisterTraceTextForPC( SbModule* pModule, UINT32 nPC, (*pInnerMap)[nPC] = aData; } +void RTL_Impl_TraceCommand( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + String aCommand = rPar.Get(1)->GetString(); + + if( aCommand.EqualsIgnoreCaseAscii( "TraceOn" ) ) + GbTraceOn = true; + else + if( aCommand.EqualsIgnoreCaseAscii( "TraceOff" ) ) + GbTraceOn = false; + else + if( aCommand.EqualsIgnoreCaseAscii( "PCodeOn" ) ) + GbIncludePCodes = true; + else + if( aCommand.EqualsIgnoreCaseAscii( "PCodeOff" ) ) + GbIncludePCodes = false; + else + if( aCommand.EqualsIgnoreCaseAscii( "Print" ) ) + { + if ( rPar.Count() < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + SbxError eOld = SbxBase::GetError(); + if( eOld != SbxERR_OK ) + SbxBase::ResetError(); + + String aValStr = rPar.Get(2)->GetString(); + SbxError eErr = SbxBase::GetError(); + if( eErr != SbxERR_OK ) + { + aValStr = String( RTL_CONSTASCII_USTRINGPARAM( "<ERROR converting value to String>" ) ); + SbxBase::ResetError(); + } + + char Buffer[500]; + const char* pValStr = OUStringToOString( rtl::OUString( aValStr ), RTL_TEXTENCODING_ASCII_US ).getStr(); + + sprintf( Buffer, "### TRACE_PRINT: %s ###", pValStr ); + int nIndent = GnLastCallLvl * GnIndentPerCallLevel; + lcl_lineOut( GpTraceFileName, Buffer, lcl_getSpaces( nIndent ) ); + + if( eOld != SbxERR_OK ) + SbxBase::SetError( eOld ); + } +} + #endif diff --git a/basic/source/inc/sbtrace.hxx b/basic/source/inc/sbtrace.hxx index e8a482c2f6e9..50e344fb63d2 100755 --- a/basic/source/inc/sbtrace.hxx +++ b/basic/source/inc/sbtrace.hxx @@ -28,15 +28,17 @@ #ifndef _SBTRACE_HXX #define _SBTRACE_HXX -// #define DBG_TRACE_BASIC +//#define DBG_TRACE_BASIC #ifdef DBG_TRACE_BASIC void dbg_InitTrace( void ); +void dbg_DeInitTrace( void ); void dbg_traceStep( SbModule* pModule, UINT32 nPC, INT32 nCallLvl ); void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, INT32 nCallLvl, bool bLeave = false ); void dbg_traceNotifyError( SbError nTraceErr, const String& aTraceErrMsg, bool bTraceErrHandled, INT32 nCallLvl ); void dbg_RegisterTraceTextForPC( SbModule* pModule, UINT32 nPC, const String& aTraceStr_STMNT, const String& aTraceStr_PCode ); +void RTL_Impl_TraceCommand( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); #endif #endif diff --git a/basic/source/runtime/methods1.cxx b/basic/source/runtime/methods1.cxx index a59a7d25b54a..68f4dbe76c5f 100755 --- a/basic/source/runtime/methods1.cxx +++ b/basic/source/runtime/methods1.cxx @@ -1666,6 +1666,12 @@ RTLFUNC(GetDefaultContext) RTL_Impl_GetDefaultContext( pBasic, rPar, bWrite ); } +#ifdef DBG_TRACE_BASIC +RTLFUNC(TraceCommand) +{ + RTL_Impl_TraceCommand( pBasic, rPar, bWrite ); +} +#endif RTLFUNC(Join) { diff --git a/basic/source/runtime/rtlproto.hxx b/basic/source/runtime/rtlproto.hxx index a05db9d8974d..ba7af48c8472 100644 --- a/basic/source/runtime/rtlproto.hxx +++ b/basic/source/runtime/rtlproto.hxx @@ -26,6 +26,7 @@ ************************************************************************/ #include <basic/sbstar.hxx> +#include "sbtrace.hxx" #define RTLFUNC( name ) void SbRtl_##name( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) #define RTLNAME( name ) &SbRtl_##name @@ -346,5 +347,9 @@ extern RTLFUNC(CDec); extern RTLFUNC(Partition); // Fong +#ifdef DBG_TRACE_BASIC +extern RTLFUNC(TraceCommand); +#endif + extern double Now_Impl(); extern void Wait_Impl( bool bDurationBased, SbxArray& rPar ); diff --git a/basic/source/runtime/stdobj.cxx b/basic/source/runtime/stdobj.cxx index c7ca576c6576..39f92afdea4a 100644 --- a/basic/source/runtime/stdobj.cxx +++ b/basic/source/runtime/stdobj.cxx @@ -535,6 +535,10 @@ static Methods aMethods[] = { { "TimeValue", SbxDATE, 1 | _FUNCTION, RTLNAME(TimeValue),0 }, { "String", SbxSTRING, 0,NULL,0 }, { "TOGGLE", SbxINTEGER, _CPROP, RTLNAME(TOGGLE),0 }, +#ifdef DBG_TRACE_BASIC +{ "TraceCommand", SbxNULL, 1 | _FUNCTION, RTLNAME(TraceCommand),0 }, + { "Command", SbxSTRING, 0,NULL,0 }, +#endif { "Trim", SbxSTRING, 1 | _FUNCTION, RTLNAME(Trim),0 }, { "String", SbxSTRING, 0,NULL,0 }, { "True", SbxBOOL, _CPROP, RTLNAME(True),0 }, |