diff options
Diffstat (limited to 'basic/source/comp/sbcomp.cxx')
-rwxr-xr-x | basic/source/comp/sbcomp.cxx | 247 |
1 files changed, 233 insertions, 14 deletions
diff --git a/basic/source/comp/sbcomp.cxx b/basic/source/comp/sbcomp.cxx index 5b7e5c70591d..c8fe782487e3 100755 --- a/basic/source/comp/sbcomp.cxx +++ b/basic/source/comp/sbcomp.cxx @@ -32,6 +32,7 @@ #include "sbcomp.hxx" #include "image.hxx" #include "sbtrace.hxx" +#include <basic/sbobjmod.hxx> //========================================================================== @@ -42,11 +43,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 +257,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 ) @@ -149,9 +284,10 @@ String dumpMethodParameters( SbMethod* pMethod ) aStr += pParam->aName; } aStr += '='; - if( pVar->GetType() & SbxARRAY ) + SbxDataType eType = pVar->GetType(); + if( eType & SbxARRAY ) aStr += String( RTL_CONSTASCII_USTRINGPARAM( "..." ) ); - else + else if( eType != SbxOBJECT ) aStr += pVar->GetString(); if ( nParam < ( pParams->Count() - 1 ) ) aStr += String( RTL_CONSTASCII_USTRINGPARAM( ", " ) ); @@ -166,16 +302,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 +362,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 +387,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 +438,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 +450,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 +490,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 @@ -431,7 +649,8 @@ BOOL SbModule::Compile() BOOL bRet = IsCompiled(); if( bRet ) { - pBasic->ClearAllModuleVars(); + if( !this->ISA(SbObjModule) ) + pBasic->ClearAllModuleVars(); RemoveVars(); // remove 'this' Modules variables // clear all method statics for( USHORT i = 0; i < pMethods->Count(); i++ ) |