1*e1f63238SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*e1f63238SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*e1f63238SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*e1f63238SAndrew Rist * distributed with this work for additional information 6*e1f63238SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*e1f63238SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*e1f63238SAndrew Rist * "License"); you may not use this file except in compliance 9*e1f63238SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*e1f63238SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*e1f63238SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*e1f63238SAndrew Rist * software distributed under the License is distributed on an 15*e1f63238SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*e1f63238SAndrew Rist * KIND, either express or implied. See the License for the 17*e1f63238SAndrew Rist * specific language governing permissions and limitations 18*e1f63238SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*e1f63238SAndrew Rist *************************************************************/ 21*e1f63238SAndrew Rist 22*e1f63238SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_basic.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <basic/sbx.hxx> 28cdf0e10cSrcweir #include "sbcomp.hxx" 29cdf0e10cSrcweir #include "image.hxx" 30cdf0e10cSrcweir #include "sbtrace.hxx" 31cdf0e10cSrcweir #include <basic/sbobjmod.hxx> 32cdf0e10cSrcweir #include <stdio.h> 33cdf0e10cSrcweir 34cdf0e10cSrcweir //========================================================================== 35cdf0e10cSrcweir // Tracing, for debugging only 36cdf0e10cSrcweir 37cdf0e10cSrcweir // To activate tracing enable in sbtrace.hxx 38cdf0e10cSrcweir #ifdef DBG_TRACE_BASIC 39cdf0e10cSrcweir 40cdf0e10cSrcweir #include <hash_map> 41cdf0e10cSrcweir 42cdf0e10cSrcweir // Trace ini file (set NULL to ignore) 43cdf0e10cSrcweir // can be overridden with the environment variable OOO_BASICTRACEINI 44cdf0e10cSrcweir static char GpTraceIniFile[] = "~/BasicTrace.ini"; 45cdf0e10cSrcweir //static char* GpTraceIniFile = NULL; 46cdf0e10cSrcweir 47cdf0e10cSrcweir 48cdf0e10cSrcweir // Trace Settings, used if no ini file / not found in ini file 49cdf0e10cSrcweir static char GpTraceFileNameDefault[] = "~/BasicTrace.txt"; 50cdf0e10cSrcweir static char* GpTraceFileName = GpTraceFileNameDefault; 51cdf0e10cSrcweir 52cdf0e10cSrcweir // GbTraceOn: 53cdf0e10cSrcweir // true = tracing is active, false = tracing is disabled, default = true 54cdf0e10cSrcweir // Set to false initially if you want to activate tracing on demand with 55cdf0e10cSrcweir // TraceCommand( "TraceOn" ), see below 56cdf0e10cSrcweir static bool GbTraceOn = true; 57cdf0e10cSrcweir 58cdf0e10cSrcweir // GbIncludePCodes: 59cdf0e10cSrcweir // true = PCodes are written to trace, default = false, correspondents 60cdf0e10cSrcweir // with TraceCommand( "PCodeOn" / "PCodeOff" ), see below 61cdf0e10cSrcweir static bool GbIncludePCodes = false; 62cdf0e10cSrcweir 63cdf0e10cSrcweir // GbInitOnlyAtOfficeStart: 64cdf0e10cSrcweir // true = Tracing is only intialized onces after Office start when 65cdf0e10cSrcweir // Basic runs the first time. Further calls to Basic, e.g. via events 66cdf0e10cSrcweir // use the same output file. The trace ini file is not read again. 67cdf0e10cSrcweir static bool GbInitOnlyAtOfficeStart = false; 68cdf0e10cSrcweir 69cdf0e10cSrcweir static int GnIndentPerCallLevel = 4; 70cdf0e10cSrcweir static int GnIndentForPCode = 2; 71cdf0e10cSrcweir 72cdf0e10cSrcweir /* 73cdf0e10cSrcweir With trace enabled the runtime function TraceCommand 74cdf0e10cSrcweir can be used to influence the trace functionality 75cdf0e10cSrcweir from within the running Basic macro. 76cdf0e10cSrcweir 77cdf0e10cSrcweir Format: TraceCommand( command as String [, param as Variant] ) 78cdf0e10cSrcweir 79cdf0e10cSrcweir Supported commands (command is NOT case sensitive): 80cdf0e10cSrcweir TraceCommand "TraceOn" sets GbTraceOn = true 81cdf0e10cSrcweir TraceCommand "TraceOff" sets GbTraceOn = false 82cdf0e10cSrcweir 83cdf0e10cSrcweir TraceCommand "PCodeOn" sets GbIncludePCodes = true 84cdf0e10cSrcweir TraceCommand "PCodeOff" sets GbIncludePCodes = false 85cdf0e10cSrcweir 86cdf0e10cSrcweir TraceCommand "Print", aVal writes aVal into the trace file as 87cdf0e10cSrcweir long as it can be converted to string 88cdf0e10cSrcweir */ 89cdf0e10cSrcweir 90cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 91cdf0e10cSrcweir 92cdf0e10cSrcweir #include <algorithm> 93cdf0e10cSrcweir #include <stack> 94cdf0e10cSrcweir #include "canvas/elapsedtime.hxx" 95cdf0e10cSrcweir 96cdf0e10cSrcweir //*** Profiling *** 97cdf0e10cSrcweir // GbTimerOn: 98cdf0e10cSrcweir // true = including time stamps 99cdf0e10cSrcweir static bool GbTimerOn = true; 100cdf0e10cSrcweir 101cdf0e10cSrcweir // GbTimeStampForEachStep: 102cdf0e10cSrcweir // true = prints time stamp after each command / pcode (very slow) 103cdf0e10cSrcweir static bool GbTimeStampForEachStep = false; 104cdf0e10cSrcweir 105cdf0e10cSrcweir // GbBlockAllAfterFirstFunctionUsage: 106cdf0e10cSrcweir // true = everything (commands, pcodes, functions) is only printed 107cdf0e10cSrcweir // for the first usage (improves performance when tracing / pro- 108cdf0e10cSrcweir // filing large macros) 109cdf0e10cSrcweir static bool GbBlockAllAfterFirstFunctionUsage = false; 110cdf0e10cSrcweir 111cdf0e10cSrcweir // GbBlockStepsAfterFirstFunctionUsage: 112cdf0e10cSrcweir // true = commands / pcodes are only printed for the first time 113cdf0e10cSrcweir // a function is executed. Afterwards only the entering/leaving 114cdf0e10cSrcweir // messages are logged (improves performance when tracing / pro- 115cdf0e10cSrcweir // filing large macros) 116cdf0e10cSrcweir static bool GbBlockStepsAfterFirstFunctionUsage = false; 117cdf0e10cSrcweir 118cdf0e10cSrcweir #endif 119cdf0e10cSrcweir 120cdf0e10cSrcweir 121cdf0e10cSrcweir static void lcl_skipWhites( char*& rpc ) 122cdf0e10cSrcweir { 123cdf0e10cSrcweir while( *rpc == ' ' || *rpc == '\t' ) 124cdf0e10cSrcweir ++rpc; 125cdf0e10cSrcweir } 126cdf0e10cSrcweir 127cdf0e10cSrcweir inline void lcl_findNextLine( char*& rpc, char* pe ) 128cdf0e10cSrcweir { 129cdf0e10cSrcweir // Find line end 130cdf0e10cSrcweir while( rpc < pe && *rpc != 13 && *rpc != 10 ) 131cdf0e10cSrcweir ++rpc; 132cdf0e10cSrcweir 133cdf0e10cSrcweir // Read all 134cdf0e10cSrcweir while( rpc < pe && (*rpc == 13 || *rpc == 10) ) 135cdf0e10cSrcweir ++rpc; 136cdf0e10cSrcweir } 137cdf0e10cSrcweir 138cdf0e10cSrcweir inline bool lcl_isAlpha( char c ) 139cdf0e10cSrcweir { 140cdf0e10cSrcweir bool bRet = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); 141cdf0e10cSrcweir return bRet; 142cdf0e10cSrcweir } 143cdf0e10cSrcweir 144cdf0e10cSrcweir static void lcl_ReadIniFile( const char* pIniFileName ) 145cdf0e10cSrcweir { 146cdf0e10cSrcweir const int BUF_SIZE = 1000; 147cdf0e10cSrcweir static sal_Char TraceFileNameBuffer[BUF_SIZE]; 148cdf0e10cSrcweir sal_Char Buffer[BUF_SIZE]; 149cdf0e10cSrcweir sal_Char VarNameBuffer[BUF_SIZE]; 150cdf0e10cSrcweir sal_Char ValBuffer[BUF_SIZE]; 151cdf0e10cSrcweir 152cdf0e10cSrcweir FILE* pFile = fopen( pIniFileName ,"rb" ); 153cdf0e10cSrcweir if( pFile == NULL ) 154cdf0e10cSrcweir return; 155cdf0e10cSrcweir 156cdf0e10cSrcweir size_t nRead = fread( Buffer, 1, BUF_SIZE, pFile ); 157cdf0e10cSrcweir 158cdf0e10cSrcweir // Scan 159cdf0e10cSrcweir char* pc = Buffer; 160cdf0e10cSrcweir char* pe = Buffer + nRead; 161cdf0e10cSrcweir while( pc < pe ) 162cdf0e10cSrcweir { 163cdf0e10cSrcweir lcl_skipWhites( pc ); if( pc == pe ) break; 164cdf0e10cSrcweir 165cdf0e10cSrcweir // Read variable 166cdf0e10cSrcweir char* pVarStart = pc; 167cdf0e10cSrcweir while( pc < pe && lcl_isAlpha( *pc ) ) 168cdf0e10cSrcweir ++pc; 169cdf0e10cSrcweir int nVarLen = pc - pVarStart; 170cdf0e10cSrcweir if( nVarLen == 0 ) 171cdf0e10cSrcweir { 172cdf0e10cSrcweir lcl_findNextLine( pc, pe ); 173cdf0e10cSrcweir continue; 174cdf0e10cSrcweir } 175cdf0e10cSrcweir strncpy( VarNameBuffer, pVarStart, nVarLen ); 176cdf0e10cSrcweir VarNameBuffer[nVarLen] = '\0'; 177cdf0e10cSrcweir 178cdf0e10cSrcweir // Check = 179cdf0e10cSrcweir lcl_skipWhites( pc ); if( pc == pe ) break; 180cdf0e10cSrcweir if( *pc != '=' ) 181cdf0e10cSrcweir continue; 182cdf0e10cSrcweir ++pc; 183cdf0e10cSrcweir lcl_skipWhites( pc ); if( pc == pe ) break; 184cdf0e10cSrcweir 185cdf0e10cSrcweir // Read value 186cdf0e10cSrcweir char* pValStart = pc; 187cdf0e10cSrcweir while( pc < pe && *pc != 13 && *pc != 10 ) 188cdf0e10cSrcweir ++pc; 189cdf0e10cSrcweir int nValLen = pc - pValStart; 190cdf0e10cSrcweir if( nValLen == 0 ) 191cdf0e10cSrcweir { 192cdf0e10cSrcweir lcl_findNextLine( pc, pe ); 193cdf0e10cSrcweir continue; 194cdf0e10cSrcweir } 195cdf0e10cSrcweir strncpy( ValBuffer, pValStart, nValLen ); 196cdf0e10cSrcweir ValBuffer[nValLen] = '\0'; 197cdf0e10cSrcweir 198cdf0e10cSrcweir // Match variables 199cdf0e10cSrcweir if( strcmp( VarNameBuffer, "GpTraceFileName") == 0 ) 200cdf0e10cSrcweir { 201cdf0e10cSrcweir strcpy( TraceFileNameBuffer, ValBuffer ); 202cdf0e10cSrcweir GpTraceFileName = TraceFileNameBuffer; 203cdf0e10cSrcweir } 204cdf0e10cSrcweir else 205cdf0e10cSrcweir if( strcmp( VarNameBuffer, "GbTraceOn") == 0 ) 206cdf0e10cSrcweir GbTraceOn = (strcmp( ValBuffer, "true" ) == 0); 207cdf0e10cSrcweir else 208cdf0e10cSrcweir if( strcmp( VarNameBuffer, "GbIncludePCodes") == 0 ) 209cdf0e10cSrcweir GbIncludePCodes = (strcmp( ValBuffer, "true" ) == 0); 210cdf0e10cSrcweir else 211cdf0e10cSrcweir if( strcmp( VarNameBuffer, "GbInitOnlyAtOfficeStart") == 0 ) 212cdf0e10cSrcweir GbInitOnlyAtOfficeStart = (strcmp( ValBuffer, "true" ) == 0); 213cdf0e10cSrcweir else 214cdf0e10cSrcweir if( strcmp( VarNameBuffer, "GnIndentPerCallLevel") == 0 ) 215cdf0e10cSrcweir GnIndentPerCallLevel = strtol( ValBuffer, NULL, 10 ); 216cdf0e10cSrcweir else 217cdf0e10cSrcweir if( strcmp( VarNameBuffer, "GnIndentForPCode") == 0 ) 218cdf0e10cSrcweir GnIndentForPCode = strtol( ValBuffer, NULL, 10 ); 219cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 220cdf0e10cSrcweir else 221cdf0e10cSrcweir if( strcmp( VarNameBuffer, "GbTimerOn") == 0 ) 222cdf0e10cSrcweir GbTimerOn = (strcmp( ValBuffer, "true" ) == 0); 223cdf0e10cSrcweir else 224cdf0e10cSrcweir if( strcmp( VarNameBuffer, "GbTimeStampForEachStep") == 0 ) 225cdf0e10cSrcweir GbTimeStampForEachStep = (strcmp( ValBuffer, "true" ) == 0); 226cdf0e10cSrcweir else 227cdf0e10cSrcweir if( strcmp( VarNameBuffer, "GbBlockAllAfterFirstFunctionUsage") == 0 ) 228cdf0e10cSrcweir GbBlockAllAfterFirstFunctionUsage = (strcmp( ValBuffer, "true" ) == 0); 229cdf0e10cSrcweir else 230cdf0e10cSrcweir if( strcmp( VarNameBuffer, "GbBlockStepsAfterFirstFunctionUsage") == 0 ) 231cdf0e10cSrcweir GbBlockStepsAfterFirstFunctionUsage = (strcmp( ValBuffer, "true" ) == 0); 232cdf0e10cSrcweir #endif 233cdf0e10cSrcweir } 234cdf0e10cSrcweir fclose( pFile ); 235cdf0e10cSrcweir } 236cdf0e10cSrcweir 237cdf0e10cSrcweir struct TraceTextData 238cdf0e10cSrcweir { 239cdf0e10cSrcweir rtl::OString m_aTraceStr_STMNT; 240cdf0e10cSrcweir rtl::OString m_aTraceStr_PCode; 241cdf0e10cSrcweir }; 242cdf0e10cSrcweir typedef std::hash_map< sal_Int32, TraceTextData > PCToTextDataMap; 243cdf0e10cSrcweir typedef std::hash_map< ::rtl::OUString, PCToTextDataMap*, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ModuleTraceMap; 244cdf0e10cSrcweir 245cdf0e10cSrcweir ModuleTraceMap GaModuleTraceMap; 246cdf0e10cSrcweir ModuleTraceMap& rModuleTraceMap = GaModuleTraceMap; 247cdf0e10cSrcweir 248cdf0e10cSrcweir static void lcl_PrepareTraceForModule( SbModule* pModule ) 249cdf0e10cSrcweir { 250cdf0e10cSrcweir String aModuleName = pModule->GetName(); 251cdf0e10cSrcweir ModuleTraceMap::iterator it = rModuleTraceMap.find( aModuleName ); 252cdf0e10cSrcweir if( it != rModuleTraceMap.end() ) 253cdf0e10cSrcweir { 254cdf0e10cSrcweir PCToTextDataMap* pInnerMap = it->second; 255cdf0e10cSrcweir delete pInnerMap; 256cdf0e10cSrcweir rModuleTraceMap.erase( it ); 257cdf0e10cSrcweir } 258cdf0e10cSrcweir 259cdf0e10cSrcweir String aDisassemblyStr; 260cdf0e10cSrcweir pModule->Disassemble( aDisassemblyStr ); 261cdf0e10cSrcweir } 262cdf0e10cSrcweir 263cdf0e10cSrcweir static FILE* GpGlobalFile = NULL; 264cdf0e10cSrcweir 265cdf0e10cSrcweir static void lcl_lineOut( const char* pStr, const char* pPreStr = NULL, const char* pPostStr = NULL ) 266cdf0e10cSrcweir { 267cdf0e10cSrcweir if( GpGlobalFile != NULL ) 268cdf0e10cSrcweir { 269cdf0e10cSrcweir fprintf( GpGlobalFile, "%s%s%s\n", pPreStr ? pPreStr : "", pStr, pPostStr ? pPostStr : "" ); 270cdf0e10cSrcweir fflush( GpGlobalFile ); 271cdf0e10cSrcweir } 272cdf0e10cSrcweir } 273cdf0e10cSrcweir 274cdf0e10cSrcweir const char* lcl_getSpaces( int nSpaceCount ) 275cdf0e10cSrcweir { 276cdf0e10cSrcweir static sal_Char Spaces[] = " " 277cdf0e10cSrcweir " " 278cdf0e10cSrcweir " "; 279cdf0e10cSrcweir static int nAvailableSpaceCount = strlen( Spaces ); 280cdf0e10cSrcweir static sal_Char* pSpacesEnd = Spaces + nAvailableSpaceCount; 281cdf0e10cSrcweir 282cdf0e10cSrcweir if( nSpaceCount > nAvailableSpaceCount ) 283cdf0e10cSrcweir nSpaceCount = nAvailableSpaceCount; 284cdf0e10cSrcweir 285cdf0e10cSrcweir return pSpacesEnd - nSpaceCount; 286cdf0e10cSrcweir } 287cdf0e10cSrcweir 288cdf0e10cSrcweir static rtl::OString lcl_toOStringSkipLeadingWhites( const String& aStr ) 289cdf0e10cSrcweir { 290cdf0e10cSrcweir static sal_Char Buffer[1000]; 291cdf0e10cSrcweir 292cdf0e10cSrcweir rtl::OString aOStr = OUStringToOString( rtl::OUString( aStr ), RTL_TEXTENCODING_ASCII_US ); 293cdf0e10cSrcweir const sal_Char* pStr = aOStr.getStr(); 294cdf0e10cSrcweir 295cdf0e10cSrcweir // Skip whitespace 296cdf0e10cSrcweir sal_Char c = *pStr; 297cdf0e10cSrcweir while( c == ' ' || c == '\t' ) 298cdf0e10cSrcweir { 299cdf0e10cSrcweir pStr++; 300cdf0e10cSrcweir c = *pStr; 301cdf0e10cSrcweir } 302cdf0e10cSrcweir 303cdf0e10cSrcweir int nLen = strlen( pStr ); 304cdf0e10cSrcweir strncpy( Buffer, pStr, nLen ); 305cdf0e10cSrcweir Buffer[nLen] = 0; 306cdf0e10cSrcweir 307cdf0e10cSrcweir rtl::OString aORetStr( Buffer ); 308cdf0e10cSrcweir return aORetStr; 309cdf0e10cSrcweir } 310cdf0e10cSrcweir 311cdf0e10cSrcweir String lcl_dumpMethodParameters( SbMethod* pMethod ) 312cdf0e10cSrcweir { 313cdf0e10cSrcweir String aStr; 314cdf0e10cSrcweir if( pMethod == NULL ) 315cdf0e10cSrcweir return aStr; 316cdf0e10cSrcweir 317cdf0e10cSrcweir SbxError eOld = SbxBase::GetError(); 318cdf0e10cSrcweir 319cdf0e10cSrcweir SbxArray* pParams = pMethod->GetParameters(); 320cdf0e10cSrcweir SbxInfo* pInfo = pMethod->GetInfo(); 321cdf0e10cSrcweir if ( pParams ) 322cdf0e10cSrcweir { 323cdf0e10cSrcweir aStr += '('; 324cdf0e10cSrcweir // 0 is sub itself 325cdf0e10cSrcweir for ( sal_uInt16 nParam = 1; nParam < pParams->Count(); nParam++ ) 326cdf0e10cSrcweir { 327cdf0e10cSrcweir SbxVariable* pVar = pParams->Get( nParam ); 328cdf0e10cSrcweir DBG_ASSERT( pVar, "Parameter?!" ); 329cdf0e10cSrcweir if ( pVar->GetName().Len() ) 330cdf0e10cSrcweir aStr += pVar->GetName(); 331cdf0e10cSrcweir else if ( pInfo ) 332cdf0e10cSrcweir { 333cdf0e10cSrcweir const SbxParamInfo* pParam = pInfo->GetParam( nParam ); 334cdf0e10cSrcweir if ( pParam ) 335cdf0e10cSrcweir aStr += pParam->aName; 336cdf0e10cSrcweir } 337cdf0e10cSrcweir aStr += '='; 338cdf0e10cSrcweir SbxDataType eType = pVar->GetType(); 339cdf0e10cSrcweir if( eType & SbxARRAY ) 340cdf0e10cSrcweir aStr += String( RTL_CONSTASCII_USTRINGPARAM( "..." ) ); 341cdf0e10cSrcweir else if( eType != SbxOBJECT ) 342cdf0e10cSrcweir aStr += pVar->GetString(); 343cdf0e10cSrcweir if ( nParam < ( pParams->Count() - 1 ) ) 344cdf0e10cSrcweir aStr += String( RTL_CONSTASCII_USTRINGPARAM( ", " ) ); 345cdf0e10cSrcweir } 346cdf0e10cSrcweir aStr += ')'; 347cdf0e10cSrcweir } 348cdf0e10cSrcweir 349cdf0e10cSrcweir SbxBase::ResetError(); 350cdf0e10cSrcweir if( eOld != SbxERR_OK ) 351cdf0e10cSrcweir SbxBase::SetError( eOld ); 352cdf0e10cSrcweir 353cdf0e10cSrcweir return aStr; 354cdf0e10cSrcweir } 355cdf0e10cSrcweir 356cdf0e10cSrcweir 357cdf0e10cSrcweir // Public functions 358cdf0e10cSrcweir static bool GbSavTraceOn = false; 359cdf0e10cSrcweir 360cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 361cdf0e10cSrcweir static canvas::tools::ElapsedTime* GpTimer = NULL; 362cdf0e10cSrcweir static double GdStartTime = 0.0; 363cdf0e10cSrcweir static double GdLastTime = 0.0; 364cdf0e10cSrcweir static bool GbBlockSteps = false; 365cdf0e10cSrcweir static bool GbBlockAll = false; 366cdf0e10cSrcweir 367cdf0e10cSrcweir struct FunctionItem 368cdf0e10cSrcweir { 369cdf0e10cSrcweir String m_aCompleteFunctionName; 370cdf0e10cSrcweir double m_dTotalTime; 371cdf0e10cSrcweir double m_dNetTime; 372cdf0e10cSrcweir int m_nCallCount; 373cdf0e10cSrcweir bool m_bBlockAll; 374cdf0e10cSrcweir bool m_bBlockSteps; 375cdf0e10cSrcweir 376cdf0e10cSrcweir FunctionItem( void ) 377cdf0e10cSrcweir : m_dTotalTime( 0.0 ) 378cdf0e10cSrcweir , m_dNetTime( 0.0 ) 379cdf0e10cSrcweir , m_nCallCount( 0 ) 380cdf0e10cSrcweir , m_bBlockAll( false ) 381cdf0e10cSrcweir , m_bBlockSteps( false ) 382cdf0e10cSrcweir {} 383cdf0e10cSrcweir }; 384cdf0e10cSrcweir typedef std::hash_map< ::rtl::OUString, FunctionItem*, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > FunctionItemMap; 385cdf0e10cSrcweir 386cdf0e10cSrcweir static std::stack< double > GaCallEnterTimeStack; 387cdf0e10cSrcweir static std::stack< FunctionItem* > GaFunctionItemStack; 388cdf0e10cSrcweir static FunctionItemMap GaFunctionItemMap; 389cdf0e10cSrcweir 390cdf0e10cSrcweir bool compareFunctionNetTime( FunctionItem* p1, FunctionItem* p2 ) 391cdf0e10cSrcweir { 392cdf0e10cSrcweir return (p1->m_dNetTime > p2->m_dNetTime); 393cdf0e10cSrcweir } 394cdf0e10cSrcweir 395cdf0e10cSrcweir void lcl_printTimeOutput( void ) 396cdf0e10cSrcweir { 397cdf0e10cSrcweir // Overall time output 398cdf0e10cSrcweir lcl_lineOut( "" ); 399cdf0e10cSrcweir lcl_lineOut( "***** Time Output *****" ); 400cdf0e10cSrcweir char TimeBuffer[500]; 401cdf0e10cSrcweir double dTotalTime = GpTimer->getElapsedTime() - GdStartTime; 402cdf0e10cSrcweir sprintf( TimeBuffer, "Total execution time = %f ms", dTotalTime*1000.0 ); 403cdf0e10cSrcweir lcl_lineOut( TimeBuffer ); 404cdf0e10cSrcweir lcl_lineOut( "" ); 405cdf0e10cSrcweir 406cdf0e10cSrcweir if( GbTimerOn ) 407cdf0e10cSrcweir { 408cdf0e10cSrcweir lcl_lineOut( "Functions:" ); 409cdf0e10cSrcweir 410cdf0e10cSrcweir std::vector<FunctionItem*> avFunctionItems; 411cdf0e10cSrcweir 412cdf0e10cSrcweir FunctionItemMap::iterator it; 413cdf0e10cSrcweir for( it = GaFunctionItemMap.begin() ; it != GaFunctionItemMap.end() ; ++it ) 414cdf0e10cSrcweir { 415cdf0e10cSrcweir FunctionItem* pFunctionItem = it->second; 416cdf0e10cSrcweir if( pFunctionItem != NULL ) 417cdf0e10cSrcweir avFunctionItems.push_back( pFunctionItem ); 418cdf0e10cSrcweir } 419cdf0e10cSrcweir 420cdf0e10cSrcweir std::sort( avFunctionItems.begin(), avFunctionItems.end(), compareFunctionNetTime ); 421cdf0e10cSrcweir 422cdf0e10cSrcweir std::vector<FunctionItem*>::iterator itv; 423cdf0e10cSrcweir for( itv = avFunctionItems.begin() ; itv != avFunctionItems.end() ; ++itv ) 424cdf0e10cSrcweir { 425cdf0e10cSrcweir FunctionItem* pFunctionItem = *itv; 426cdf0e10cSrcweir if( pFunctionItem != NULL ) 427cdf0e10cSrcweir { 428cdf0e10cSrcweir rtl::OUString aCompleteFunctionName = pFunctionItem->m_aCompleteFunctionName; 429cdf0e10cSrcweir const char* pName = OUStringToOString( aCompleteFunctionName, RTL_TEXTENCODING_ASCII_US ).getStr(); 430cdf0e10cSrcweir int nNameLen = aCompleteFunctionName.getLength(); 431cdf0e10cSrcweir 432cdf0e10cSrcweir double dFctTotalTime = pFunctionItem->m_dTotalTime; 433cdf0e10cSrcweir double dFctNetTime = pFunctionItem->m_dNetTime; 434cdf0e10cSrcweir double dFctTotalTimePercent = 100.0 * dFctTotalTime / dTotalTime; 435cdf0e10cSrcweir double dFctNetTimePercent = 100.0 * dFctNetTime / dTotalTime; 436cdf0e10cSrcweir int nSpaceCount = 30 - nNameLen; 437cdf0e10cSrcweir if( nSpaceCount < 0 ) 438cdf0e10cSrcweir nSpaceCount = 2; 439cdf0e10cSrcweir sprintf( TimeBuffer, "%s:%sCalled %d times\t%f ms (%f%%) / net %f (%f%%) ms", 440cdf0e10cSrcweir pName, lcl_getSpaces( nSpaceCount ), pFunctionItem->m_nCallCount, 441cdf0e10cSrcweir dFctTotalTime*1000.0, dFctTotalTimePercent, dFctNetTime*1000.0, dFctNetTimePercent ); 442cdf0e10cSrcweir lcl_lineOut( TimeBuffer ); 443cdf0e10cSrcweir } 444cdf0e10cSrcweir } 445cdf0e10cSrcweir } 446cdf0e10cSrcweir } 447cdf0e10cSrcweir #endif 448cdf0e10cSrcweir 449cdf0e10cSrcweir 450cdf0e10cSrcweir static bool GbInitTraceAlreadyCalled = false; 451cdf0e10cSrcweir 452cdf0e10cSrcweir void dbg_InitTrace( void ) 453cdf0e10cSrcweir { 454cdf0e10cSrcweir if( GbInitOnlyAtOfficeStart && GbInitTraceAlreadyCalled ) 455cdf0e10cSrcweir { 456cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 457cdf0e10cSrcweir if( GbTimerOn ) 458cdf0e10cSrcweir GpTimer->continueTimer(); 459cdf0e10cSrcweir #endif 460cdf0e10cSrcweir GpGlobalFile = fopen( GpTraceFileName, "a+" ); 461cdf0e10cSrcweir return; 462cdf0e10cSrcweir } 463cdf0e10cSrcweir GbInitTraceAlreadyCalled = true; 464cdf0e10cSrcweir 465cdf0e10cSrcweir if( const sal_Char* pcIniFileName = ::getenv( "OOO_BASICTRACEINI" ) ) 466cdf0e10cSrcweir lcl_ReadIniFile( pcIniFileName ); 467cdf0e10cSrcweir else if( GpTraceIniFile != NULL ) 468cdf0e10cSrcweir lcl_ReadIniFile( GpTraceIniFile ); 469cdf0e10cSrcweir 470cdf0e10cSrcweir GpGlobalFile = fopen( GpTraceFileName, "w" ); 471cdf0e10cSrcweir GbSavTraceOn = GbTraceOn; 472cdf0e10cSrcweir if( !GbTraceOn ) 473cdf0e10cSrcweir lcl_lineOut( "### Program started with trace off ###" ); 474cdf0e10cSrcweir 475cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 476cdf0e10cSrcweir GpTimer = new canvas::tools::ElapsedTime(); 477cdf0e10cSrcweir GdStartTime = GpTimer->getElapsedTime(); 478cdf0e10cSrcweir GdLastTime = GdStartTime; 479cdf0e10cSrcweir GbBlockSteps = false; 480cdf0e10cSrcweir GbBlockAll = false; 481cdf0e10cSrcweir #endif 482cdf0e10cSrcweir } 483cdf0e10cSrcweir 484cdf0e10cSrcweir void dbg_DeInitTrace( void ) 485cdf0e10cSrcweir { 486cdf0e10cSrcweir GbTraceOn = GbSavTraceOn; 487cdf0e10cSrcweir 488cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 489cdf0e10cSrcweir while( !GaCallEnterTimeStack.empty() ) 490cdf0e10cSrcweir GaCallEnterTimeStack.pop(); 491cdf0e10cSrcweir while( !GaFunctionItemStack.empty() ) 492cdf0e10cSrcweir GaFunctionItemStack.pop(); 493cdf0e10cSrcweir 494cdf0e10cSrcweir lcl_printTimeOutput(); 495cdf0e10cSrcweir 496cdf0e10cSrcweir for( FunctionItemMap::iterator it = GaFunctionItemMap.begin() ; it != GaFunctionItemMap.end() ; ++it ) 497cdf0e10cSrcweir delete it->second; 498cdf0e10cSrcweir GaFunctionItemMap.clear(); 499cdf0e10cSrcweir 500cdf0e10cSrcweir if( GpGlobalFile ) 501cdf0e10cSrcweir { 502cdf0e10cSrcweir fclose( GpGlobalFile ); 503cdf0e10cSrcweir GpGlobalFile = NULL; 504cdf0e10cSrcweir } 505cdf0e10cSrcweir 506cdf0e10cSrcweir if( GbInitOnlyAtOfficeStart ) 507cdf0e10cSrcweir { 508cdf0e10cSrcweir if( GbTimerOn ) 509cdf0e10cSrcweir GpTimer->pauseTimer(); 510cdf0e10cSrcweir } 511cdf0e10cSrcweir else 512cdf0e10cSrcweir { 513cdf0e10cSrcweir delete GpTimer; 514cdf0e10cSrcweir } 515cdf0e10cSrcweir #endif 516cdf0e10cSrcweir } 517cdf0e10cSrcweir 518cdf0e10cSrcweir static sal_Int32 GnLastCallLvl = 0; 519cdf0e10cSrcweir 520cdf0e10cSrcweir void dbg_tracePrint( const String& aStr, sal_Int32 nCallLvl, bool bCallLvlRelativeToCurrent ) 521cdf0e10cSrcweir { 522cdf0e10cSrcweir if( bCallLvlRelativeToCurrent ) 523cdf0e10cSrcweir nCallLvl += GnLastCallLvl; 524cdf0e10cSrcweir 525cdf0e10cSrcweir int nIndent = nCallLvl * GnIndentPerCallLevel; 526cdf0e10cSrcweir lcl_lineOut( OUStringToOString( rtl::OUString( aStr ), RTL_TEXTENCODING_ASCII_US ).getStr(), lcl_getSpaces( nIndent ) ); 527cdf0e10cSrcweir } 528cdf0e10cSrcweir 529cdf0e10cSrcweir void dbg_traceStep( SbModule* pModule, sal_uInt32 nPC, sal_Int32 nCallLvl ) 530cdf0e10cSrcweir { 531cdf0e10cSrcweir if( !GbTraceOn ) 532cdf0e10cSrcweir return; 533cdf0e10cSrcweir 534cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 535cdf0e10cSrcweir if( GbBlockSteps || GbBlockAll ) 536cdf0e10cSrcweir return; 537cdf0e10cSrcweir 538cdf0e10cSrcweir double dCurTime = 0.0; 539cdf0e10cSrcweir bool bPrintTimeStamp = false; 540cdf0e10cSrcweir if( GbTimerOn ) 541cdf0e10cSrcweir { 542cdf0e10cSrcweir GpTimer->pauseTimer(); 543cdf0e10cSrcweir dCurTime = GpTimer->getElapsedTime(); 544cdf0e10cSrcweir bPrintTimeStamp = GbTimeStampForEachStep; 545cdf0e10cSrcweir } 546cdf0e10cSrcweir #else 547cdf0e10cSrcweir bool bPrintTimeStamp = false; 548cdf0e10cSrcweir #endif 549cdf0e10cSrcweir 550cdf0e10cSrcweir GnLastCallLvl = nCallLvl; 551cdf0e10cSrcweir 552cdf0e10cSrcweir SbModule* pTraceMod = pModule; 553cdf0e10cSrcweir if( pTraceMod->ISA(SbClassModuleObject) ) 554cdf0e10cSrcweir { 555cdf0e10cSrcweir SbClassModuleObject* pClassModuleObj = (SbClassModuleObject*)(SbxBase*)pTraceMod; 556cdf0e10cSrcweir pTraceMod = pClassModuleObj->getClassModule(); 557cdf0e10cSrcweir } 558cdf0e10cSrcweir 559cdf0e10cSrcweir String aModuleName = pTraceMod->GetName(); 560cdf0e10cSrcweir ModuleTraceMap::iterator it = rModuleTraceMap.find( aModuleName ); 561cdf0e10cSrcweir if( it == rModuleTraceMap.end() ) 562cdf0e10cSrcweir { 563cdf0e10cSrcweir const char* pModuleNameStr = OUStringToOString( rtl::OUString( aModuleName ), RTL_TEXTENCODING_ASCII_US ).getStr(); 564cdf0e10cSrcweir char Buffer[200]; 565cdf0e10cSrcweir sprintf( Buffer, "TRACE ERROR: Unknown module \"%s\"", pModuleNameStr ); 566cdf0e10cSrcweir lcl_lineOut( Buffer ); 567cdf0e10cSrcweir return; 568cdf0e10cSrcweir } 569cdf0e10cSrcweir 570cdf0e10cSrcweir PCToTextDataMap* pInnerMap = it->second; 571cdf0e10cSrcweir if( pInnerMap == NULL ) 572cdf0e10cSrcweir { 573cdf0e10cSrcweir lcl_lineOut( "TRACE INTERNAL ERROR: No inner map" ); 574cdf0e10cSrcweir return; 575cdf0e10cSrcweir } 576cdf0e10cSrcweir 577cdf0e10cSrcweir PCToTextDataMap::iterator itInner = pInnerMap->find( nPC ); 578cdf0e10cSrcweir if( itInner == pInnerMap->end() ) 579cdf0e10cSrcweir { 580cdf0e10cSrcweir const char* pModuleNameStr = OUStringToOString( rtl::OUString( aModuleName ), RTL_TEXTENCODING_ASCII_US ).getStr(); 581cdf0e10cSrcweir char Buffer[200]; 582cdf0e10cSrcweir sprintf( Buffer, "TRACE ERROR: No info for PC = %d in module \"%s\"", (int)nPC, pModuleNameStr ); 583cdf0e10cSrcweir lcl_lineOut( Buffer ); 584cdf0e10cSrcweir return; 585cdf0e10cSrcweir } 586cdf0e10cSrcweir 587cdf0e10cSrcweir int nIndent = nCallLvl * GnIndentPerCallLevel; 588cdf0e10cSrcweir 589cdf0e10cSrcweir const TraceTextData& rTraceTextData = itInner->second; 590cdf0e10cSrcweir const rtl::OString& rStr_STMNT = rTraceTextData.m_aTraceStr_STMNT; 591cdf0e10cSrcweir bool bSTMT = false; 592cdf0e10cSrcweir if( rStr_STMNT.getLength() ) 593cdf0e10cSrcweir bSTMT = true; 594cdf0e10cSrcweir 595cdf0e10cSrcweir char TimeBuffer[200]; 596cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 597cdf0e10cSrcweir if( bPrintTimeStamp ) 598cdf0e10cSrcweir { 599cdf0e10cSrcweir double dDiffTime = dCurTime - GdLastTime; 600cdf0e10cSrcweir GdLastTime = dCurTime; 601cdf0e10cSrcweir sprintf( TimeBuffer, "\t\t// Time = %f ms / += %f ms", dCurTime*1000.0, dDiffTime*1000.0 ); 602cdf0e10cSrcweir } 603cdf0e10cSrcweir #endif 604cdf0e10cSrcweir 605cdf0e10cSrcweir if( bSTMT ) 606cdf0e10cSrcweir { 607cdf0e10cSrcweir lcl_lineOut( rStr_STMNT.getStr(), lcl_getSpaces( nIndent ), 608cdf0e10cSrcweir (bPrintTimeStamp && !GbIncludePCodes) ? TimeBuffer : NULL ); 609cdf0e10cSrcweir } 610cdf0e10cSrcweir 611cdf0e10cSrcweir if( !GbIncludePCodes ) 612cdf0e10cSrcweir { 613cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 614cdf0e10cSrcweir if( GbTimerOn ) 615cdf0e10cSrcweir GpTimer->continueTimer(); 616cdf0e10cSrcweir #endif 617cdf0e10cSrcweir return; 618cdf0e10cSrcweir } 619cdf0e10cSrcweir 620cdf0e10cSrcweir nIndent += GnIndentForPCode; 621cdf0e10cSrcweir const rtl::OString& rStr_PCode = rTraceTextData.m_aTraceStr_PCode; 622cdf0e10cSrcweir if( rStr_PCode.getLength() ) 623cdf0e10cSrcweir { 624cdf0e10cSrcweir lcl_lineOut( rStr_PCode.getStr(), lcl_getSpaces( nIndent ), 625cdf0e10cSrcweir bPrintTimeStamp ? TimeBuffer : NULL ); 626cdf0e10cSrcweir } 627cdf0e10cSrcweir 628cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 629cdf0e10cSrcweir if( GbTimerOn ) 630cdf0e10cSrcweir GpTimer->continueTimer(); 631cdf0e10cSrcweir #endif 632cdf0e10cSrcweir } 633cdf0e10cSrcweir 634cdf0e10cSrcweir 635cdf0e10cSrcweir void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, sal_Int32 nCallLvl, bool bLeave ) 636cdf0e10cSrcweir { 637cdf0e10cSrcweir static const char* pSeparator = "' ================================================================================"; 638cdf0e10cSrcweir 639cdf0e10cSrcweir if( !GbTraceOn ) 640cdf0e10cSrcweir return; 641cdf0e10cSrcweir 642cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 643cdf0e10cSrcweir double dCurTime = 0.0; 644cdf0e10cSrcweir double dExecutionTime = 0.0; 645cdf0e10cSrcweir if( GbTimerOn ) 646cdf0e10cSrcweir { 647cdf0e10cSrcweir dCurTime = GpTimer->getElapsedTime(); 648cdf0e10cSrcweir GpTimer->pauseTimer(); 649cdf0e10cSrcweir } 650cdf0e10cSrcweir #endif 651cdf0e10cSrcweir 652cdf0e10cSrcweir GnLastCallLvl = nCallLvl; 653cdf0e10cSrcweir 654cdf0e10cSrcweir SbModule* pTraceMod = pModule; 655cdf0e10cSrcweir SbClassModuleObject* pClassModuleObj = NULL; 656cdf0e10cSrcweir if( pTraceMod->ISA(SbClassModuleObject) ) 657cdf0e10cSrcweir { 658cdf0e10cSrcweir pClassModuleObj = (SbClassModuleObject*)(SbxBase*)pTraceMod; 659cdf0e10cSrcweir pTraceMod = pClassModuleObj->getClassModule(); 660cdf0e10cSrcweir } 661cdf0e10cSrcweir 662cdf0e10cSrcweir String aCompleteFunctionName = pTraceMod->GetName(); 663cdf0e10cSrcweir if( pMethod != NULL ) 664cdf0e10cSrcweir { 665cdf0e10cSrcweir aCompleteFunctionName.AppendAscii( "::" ); 666cdf0e10cSrcweir String aMethodName = pMethod->GetName(); 667cdf0e10cSrcweir aCompleteFunctionName += aMethodName; 668cdf0e10cSrcweir } 669cdf0e10cSrcweir else 670cdf0e10cSrcweir { 671cdf0e10cSrcweir aCompleteFunctionName.AppendAscii( "/RunInit" ); 672cdf0e10cSrcweir } 673cdf0e10cSrcweir 674cdf0e10cSrcweir bool bOwnBlockSteps = false; 675cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 676cdf0e10cSrcweir bool bOwnBlockAll = false; 677cdf0e10cSrcweir FunctionItem* pFunctionItem = NULL; 678cdf0e10cSrcweir if( GbTimerOn ) 679cdf0e10cSrcweir { 680cdf0e10cSrcweir FunctionItemMap::iterator itFunctionItem = GaFunctionItemMap.find( aCompleteFunctionName ); 681cdf0e10cSrcweir if( itFunctionItem != GaFunctionItemMap.end() ) 682cdf0e10cSrcweir pFunctionItem = itFunctionItem->second; 683cdf0e10cSrcweir 684cdf0e10cSrcweir if( pFunctionItem == NULL ) 685cdf0e10cSrcweir { 686cdf0e10cSrcweir DBG_ASSERT( !bLeave, "No FunctionItem in leave!" ); 687cdf0e10cSrcweir 688cdf0e10cSrcweir pFunctionItem = new FunctionItem(); 689cdf0e10cSrcweir pFunctionItem->m_aCompleteFunctionName = aCompleteFunctionName; 690cdf0e10cSrcweir GaFunctionItemMap[ aCompleteFunctionName ] = pFunctionItem; 691cdf0e10cSrcweir } 692cdf0e10cSrcweir else if( GbBlockAllAfterFirstFunctionUsage && !bLeave ) 693cdf0e10cSrcweir { 694cdf0e10cSrcweir pFunctionItem->m_bBlockAll = true; 695cdf0e10cSrcweir } 696cdf0e10cSrcweir else if( GbBlockStepsAfterFirstFunctionUsage && !bLeave ) 697cdf0e10cSrcweir { 698cdf0e10cSrcweir pFunctionItem->m_bBlockSteps = true; 699cdf0e10cSrcweir } 700cdf0e10cSrcweir 701cdf0e10cSrcweir if( bLeave ) 702cdf0e10cSrcweir { 703cdf0e10cSrcweir bOwnBlockAll = GbBlockAll; 704cdf0e10cSrcweir bOwnBlockSteps = GbBlockSteps; 705cdf0e10cSrcweir GbBlockAll = false; 706cdf0e10cSrcweir GbBlockSteps = false; 707cdf0e10cSrcweir 708cdf0e10cSrcweir dExecutionTime = dCurTime - GaCallEnterTimeStack.top(); 709cdf0e10cSrcweir GaCallEnterTimeStack.pop(); 710cdf0e10cSrcweir 711cdf0e10cSrcweir pFunctionItem->m_dTotalTime += dExecutionTime; 712cdf0e10cSrcweir pFunctionItem->m_dNetTime += dExecutionTime; 713cdf0e10cSrcweir pFunctionItem->m_nCallCount++; 714cdf0e10cSrcweir 715cdf0e10cSrcweir GaFunctionItemStack.pop(); 716cdf0e10cSrcweir if( !GaFunctionItemStack.empty() ) 717cdf0e10cSrcweir { 718cdf0e10cSrcweir FunctionItem* pParentItem = GaFunctionItemStack.top(); 719cdf0e10cSrcweir if( pParentItem != NULL ) 720cdf0e10cSrcweir { 721cdf0e10cSrcweir pParentItem->m_dNetTime -= dExecutionTime; 722cdf0e10cSrcweir 723cdf0e10cSrcweir GbBlockSteps = pParentItem->m_bBlockSteps; 724cdf0e10cSrcweir GbBlockAll = pParentItem->m_bBlockAll; 725cdf0e10cSrcweir } 726cdf0e10cSrcweir } 727cdf0e10cSrcweir } 728cdf0e10cSrcweir else 729cdf0e10cSrcweir { 730cdf0e10cSrcweir GbBlockSteps = bOwnBlockSteps = pFunctionItem->m_bBlockSteps; 731cdf0e10cSrcweir GbBlockAll = bOwnBlockAll = pFunctionItem->m_bBlockAll; 732cdf0e10cSrcweir 733cdf0e10cSrcweir GaCallEnterTimeStack.push( dCurTime ); 734cdf0e10cSrcweir GaFunctionItemStack.push( pFunctionItem ); 735cdf0e10cSrcweir } 736cdf0e10cSrcweir } 737cdf0e10cSrcweir 738cdf0e10cSrcweir if( bOwnBlockAll ) 739cdf0e10cSrcweir { 740cdf0e10cSrcweir if( GbTimerOn ) 741cdf0e10cSrcweir GpTimer->continueTimer(); 742cdf0e10cSrcweir return; 743cdf0e10cSrcweir } 744cdf0e10cSrcweir #endif 745cdf0e10cSrcweir 746cdf0e10cSrcweir if( nCallLvl > 0 ) 747cdf0e10cSrcweir nCallLvl--; 748cdf0e10cSrcweir int nIndent = nCallLvl * GnIndentPerCallLevel; 749cdf0e10cSrcweir if( !bLeave && !bOwnBlockSteps ) 750cdf0e10cSrcweir { 751cdf0e10cSrcweir lcl_lineOut( "" ); 752cdf0e10cSrcweir lcl_lineOut( pSeparator, lcl_getSpaces( nIndent ) ); 753cdf0e10cSrcweir } 754cdf0e10cSrcweir 755cdf0e10cSrcweir String aStr; 756cdf0e10cSrcweir if( bLeave ) 757cdf0e10cSrcweir { 758cdf0e10cSrcweir if( !bOwnBlockSteps ) 759cdf0e10cSrcweir { 760cdf0e10cSrcweir lcl_lineOut( "}", lcl_getSpaces( nIndent ) ); 761cdf0e10cSrcweir aStr.AppendAscii( "' Leaving " ); 762cdf0e10cSrcweir } 763cdf0e10cSrcweir } 764cdf0e10cSrcweir else 765cdf0e10cSrcweir { 766cdf0e10cSrcweir aStr.AppendAscii( "Entering " ); 767cdf0e10cSrcweir } 768cdf0e10cSrcweir if( !bLeave || !bOwnBlockSteps ) 769cdf0e10cSrcweir aStr += aCompleteFunctionName; 770cdf0e10cSrcweir 771cdf0e10cSrcweir if( !bOwnBlockSteps && pClassModuleObj != NULL ) 772cdf0e10cSrcweir { 773cdf0e10cSrcweir aStr.AppendAscii( "[this=" ); 774cdf0e10cSrcweir aStr += pClassModuleObj->GetName(); 775cdf0e10cSrcweir aStr.AppendAscii( "]" ); 776cdf0e10cSrcweir } 777cdf0e10cSrcweir if( !bLeave ) 778cdf0e10cSrcweir aStr += lcl_dumpMethodParameters( pMethod ); 779cdf0e10cSrcweir 780cdf0e10cSrcweir const char* pPostStr = NULL; 781cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 782cdf0e10cSrcweir char TimeBuffer[200]; 783cdf0e10cSrcweir if( GbTimerOn && bLeave ) 784cdf0e10cSrcweir { 785cdf0e10cSrcweir sprintf( TimeBuffer, " // Execution Time = %f ms", dExecutionTime*1000.0 ); 786cdf0e10cSrcweir pPostStr = TimeBuffer; 787cdf0e10cSrcweir } 788cdf0e10cSrcweir #endif 789cdf0e10cSrcweir lcl_lineOut( (!bLeave || !bOwnBlockSteps) ? OUStringToOString( rtl::OUString( aStr ), RTL_TEXTENCODING_ASCII_US ).getStr() : "}", 790cdf0e10cSrcweir lcl_getSpaces( nIndent ), pPostStr ); 791cdf0e10cSrcweir if( !bLeave ) 792cdf0e10cSrcweir lcl_lineOut( "{", lcl_getSpaces( nIndent ) ); 793cdf0e10cSrcweir 794cdf0e10cSrcweir if( bLeave && !bOwnBlockSteps ) 795cdf0e10cSrcweir lcl_lineOut( "" ); 796cdf0e10cSrcweir 797cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 798cdf0e10cSrcweir if( GbTimerOn ) 799cdf0e10cSrcweir GpTimer->continueTimer(); 800cdf0e10cSrcweir #endif 801cdf0e10cSrcweir } 802cdf0e10cSrcweir 803cdf0e10cSrcweir void dbg_traceNotifyError( SbError nTraceErr, const String& aTraceErrMsg, bool bTraceErrHandled, sal_Int32 nCallLvl ) 804cdf0e10cSrcweir { 805cdf0e10cSrcweir if( !GbTraceOn ) 806cdf0e10cSrcweir return; 807cdf0e10cSrcweir #ifdef DBG_TRACE_PROFILING 808cdf0e10cSrcweir if( GbBlockSteps || GbBlockAll ) 809cdf0e10cSrcweir return; 810cdf0e10cSrcweir #endif 811cdf0e10cSrcweir GnLastCallLvl = nCallLvl; 812cdf0e10cSrcweir 813cdf0e10cSrcweir rtl::OString aOTraceErrMsg = OUStringToOString( rtl::OUString( aTraceErrMsg ), RTL_TEXTENCODING_ASCII_US ); 814cdf0e10cSrcweir 815cdf0e10cSrcweir char Buffer[200]; 816cdf0e10cSrcweir const char* pHandledStr = bTraceErrHandled ? " / HANDLED" : ""; 817cdf0e10cSrcweir sprintf( Buffer, "*** ERROR%s, Id = %d, Msg = \"%s\" ***", pHandledStr, (int)nTraceErr, aOTraceErrMsg.getStr() ); 818cdf0e10cSrcweir int nIndent = nCallLvl * GnIndentPerCallLevel; 819cdf0e10cSrcweir lcl_lineOut( Buffer, lcl_getSpaces( nIndent ) ); 820cdf0e10cSrcweir } 821cdf0e10cSrcweir 822cdf0e10cSrcweir void dbg_RegisterTraceTextForPC( SbModule* pModule, sal_uInt32 nPC, 823cdf0e10cSrcweir const String& aTraceStr_STMNT, const String& aTraceStr_PCode ) 824cdf0e10cSrcweir { 825cdf0e10cSrcweir String aModuleName = pModule->GetName(); 826cdf0e10cSrcweir ModuleTraceMap::iterator it = rModuleTraceMap.find( aModuleName ); 827cdf0e10cSrcweir PCToTextDataMap* pInnerMap; 828cdf0e10cSrcweir if( it == rModuleTraceMap.end() ) 829cdf0e10cSrcweir { 830cdf0e10cSrcweir pInnerMap = new PCToTextDataMap(); 831cdf0e10cSrcweir rModuleTraceMap[ aModuleName ] = pInnerMap; 832cdf0e10cSrcweir } 833cdf0e10cSrcweir else 834cdf0e10cSrcweir { 835cdf0e10cSrcweir pInnerMap = it->second; 836cdf0e10cSrcweir } 837cdf0e10cSrcweir 838cdf0e10cSrcweir TraceTextData aData; 839cdf0e10cSrcweir 840cdf0e10cSrcweir rtl::OString aOTraceStr_STMNT = lcl_toOStringSkipLeadingWhites( aTraceStr_STMNT ); 841cdf0e10cSrcweir aData.m_aTraceStr_STMNT = aOTraceStr_STMNT; 842cdf0e10cSrcweir 843cdf0e10cSrcweir rtl::OString aOTraceStr_PCode = lcl_toOStringSkipLeadingWhites( aTraceStr_PCode ); 844cdf0e10cSrcweir aData.m_aTraceStr_PCode = aOTraceStr_PCode; 845cdf0e10cSrcweir 846cdf0e10cSrcweir (*pInnerMap)[nPC] = aData; 847cdf0e10cSrcweir } 848cdf0e10cSrcweir 849cdf0e10cSrcweir void RTL_Impl_TraceCommand( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) 850cdf0e10cSrcweir { 851cdf0e10cSrcweir (void)pBasic; 852cdf0e10cSrcweir (void)bWrite; 853cdf0e10cSrcweir 854cdf0e10cSrcweir if ( rPar.Count() < 2 ) 855cdf0e10cSrcweir { 856cdf0e10cSrcweir StarBASIC::Error( SbERR_BAD_ARGUMENT ); 857cdf0e10cSrcweir return; 858cdf0e10cSrcweir } 859cdf0e10cSrcweir 860cdf0e10cSrcweir String aCommand = rPar.Get(1)->GetString(); 861cdf0e10cSrcweir 862cdf0e10cSrcweir if( aCommand.EqualsIgnoreCaseAscii( "TraceOn" ) ) 863cdf0e10cSrcweir GbTraceOn = true; 864cdf0e10cSrcweir else 865cdf0e10cSrcweir if( aCommand.EqualsIgnoreCaseAscii( "TraceOff" ) ) 866cdf0e10cSrcweir GbTraceOn = false; 867cdf0e10cSrcweir else 868cdf0e10cSrcweir if( aCommand.EqualsIgnoreCaseAscii( "PCodeOn" ) ) 869cdf0e10cSrcweir GbIncludePCodes = true; 870cdf0e10cSrcweir else 871cdf0e10cSrcweir if( aCommand.EqualsIgnoreCaseAscii( "PCodeOff" ) ) 872cdf0e10cSrcweir GbIncludePCodes = false; 873cdf0e10cSrcweir else 874cdf0e10cSrcweir if( aCommand.EqualsIgnoreCaseAscii( "Print" ) ) 875cdf0e10cSrcweir { 876cdf0e10cSrcweir if ( rPar.Count() < 3 ) 877cdf0e10cSrcweir { 878cdf0e10cSrcweir StarBASIC::Error( SbERR_BAD_ARGUMENT ); 879cdf0e10cSrcweir return; 880cdf0e10cSrcweir } 881cdf0e10cSrcweir 882cdf0e10cSrcweir SbxError eOld = SbxBase::GetError(); 883cdf0e10cSrcweir if( eOld != SbxERR_OK ) 884cdf0e10cSrcweir SbxBase::ResetError(); 885cdf0e10cSrcweir 886cdf0e10cSrcweir String aValStr = rPar.Get(2)->GetString(); 887cdf0e10cSrcweir SbxError eErr = SbxBase::GetError(); 888cdf0e10cSrcweir if( eErr != SbxERR_OK ) 889cdf0e10cSrcweir { 890cdf0e10cSrcweir aValStr = String( RTL_CONSTASCII_USTRINGPARAM( "<ERROR converting value to String>" ) ); 891cdf0e10cSrcweir SbxBase::ResetError(); 892cdf0e10cSrcweir } 893cdf0e10cSrcweir 894cdf0e10cSrcweir char Buffer[500]; 895cdf0e10cSrcweir const char* pValStr = OUStringToOString( rtl::OUString( aValStr ), RTL_TEXTENCODING_ASCII_US ).getStr(); 896cdf0e10cSrcweir 897cdf0e10cSrcweir sprintf( Buffer, "### TRACE_PRINT: %s ###", pValStr ); 898cdf0e10cSrcweir int nIndent = GnLastCallLvl * GnIndentPerCallLevel; 899cdf0e10cSrcweir lcl_lineOut( Buffer, lcl_getSpaces( nIndent ) ); 900cdf0e10cSrcweir 901cdf0e10cSrcweir if( eOld != SbxERR_OK ) 902cdf0e10cSrcweir SbxBase::SetError( eOld ); 903cdf0e10cSrcweir } 904cdf0e10cSrcweir } 905cdf0e10cSrcweir 906cdf0e10cSrcweir #endif 907cdf0e10cSrcweir 908cdf0e10cSrcweir 909cdf0e10cSrcweir //========================================================================== 910cdf0e10cSrcweir // For debugging only 911cdf0e10cSrcweir //#define DBG_SAVE_DISASSEMBLY 912cdf0e10cSrcweir 913cdf0e10cSrcweir #ifdef DBG_SAVE_DISASSEMBLY 914cdf0e10cSrcweir static bool dbg_bDisassemble = true; 915cdf0e10cSrcweir #include <comphelper/processfactory.hxx> 916cdf0e10cSrcweir 917cdf0e10cSrcweir #include <com/sun/star/lang/XMultiServiceFactory.hpp> 918cdf0e10cSrcweir #include <com/sun/star/ucb/XSimpleFileAccess3.hpp> 919cdf0e10cSrcweir #include <com/sun/star/io/XTextOutputStream.hpp> 920cdf0e10cSrcweir #include <com/sun/star/io/XActiveDataSource.hpp> 921cdf0e10cSrcweir 922cdf0e10cSrcweir using namespace comphelper; 923cdf0e10cSrcweir using namespace rtl; 924cdf0e10cSrcweir using namespace com::sun::star::uno; 925cdf0e10cSrcweir using namespace com::sun::star::lang; 926cdf0e10cSrcweir using namespace com::sun::star::ucb; 927cdf0e10cSrcweir using namespace com::sun::star::io; 928cdf0e10cSrcweir 929cdf0e10cSrcweir void dbg_SaveDisassembly( SbModule* pModule ) 930cdf0e10cSrcweir { 931cdf0e10cSrcweir bool bDisassemble = dbg_bDisassemble; 932cdf0e10cSrcweir if( bDisassemble ) 933cdf0e10cSrcweir { 934cdf0e10cSrcweir Reference< XSimpleFileAccess3 > xSFI; 935cdf0e10cSrcweir Reference< XTextOutputStream > xTextOut; 936cdf0e10cSrcweir Reference< XOutputStream > xOut; 937cdf0e10cSrcweir Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); 938cdf0e10cSrcweir if( xSMgr.is() ) 939cdf0e10cSrcweir { 940cdf0e10cSrcweir Reference< XSimpleFileAccess3 > xSFI = Reference< XSimpleFileAccess3 >( xSMgr->createInstance 941cdf0e10cSrcweir ( OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); 942cdf0e10cSrcweir if( xSFI.is() ) 943cdf0e10cSrcweir { 944cdf0e10cSrcweir String aFile( RTL_CONSTASCII_USTRINGPARAM("file:///d:/zBasic.Asm/Asm_") ); 945cdf0e10cSrcweir StarBASIC* pBasic = (StarBASIC*)pModule->GetParent(); 946cdf0e10cSrcweir if( pBasic ) 947cdf0e10cSrcweir { 948cdf0e10cSrcweir aFile += pBasic->GetName(); 949cdf0e10cSrcweir aFile.AppendAscii( "_" ); 950cdf0e10cSrcweir } 951cdf0e10cSrcweir aFile += pModule->GetName(); 952cdf0e10cSrcweir aFile.AppendAscii( ".txt" ); 953cdf0e10cSrcweir 954cdf0e10cSrcweir // String aFile( RTL_CONSTASCII_USTRINGPARAM("file:///d:/BasicAsm.txt") ); 955cdf0e10cSrcweir if( xSFI->exists( aFile ) ) 956cdf0e10cSrcweir xSFI->kill( aFile ); 957cdf0e10cSrcweir xOut = xSFI->openFileWrite( aFile ); 958cdf0e10cSrcweir Reference< XInterface > x = xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.io.TextOutputStream" ) ); 959cdf0e10cSrcweir Reference< XActiveDataSource > xADS( x, UNO_QUERY ); 960cdf0e10cSrcweir xADS->setOutputStream( xOut ); 961cdf0e10cSrcweir xTextOut = Reference< XTextOutputStream >( x, UNO_QUERY ); 962cdf0e10cSrcweir } 963cdf0e10cSrcweir } 964cdf0e10cSrcweir 965cdf0e10cSrcweir if( xTextOut.is() ) 966cdf0e10cSrcweir { 967cdf0e10cSrcweir String aDisassemblyStr; 968cdf0e10cSrcweir pModule->Disassemble( aDisassemblyStr ); 969cdf0e10cSrcweir xTextOut->writeString( aDisassemblyStr ); 970cdf0e10cSrcweir } 971cdf0e10cSrcweir xOut->closeOutput(); 972cdf0e10cSrcweir } 973cdf0e10cSrcweir } 974cdf0e10cSrcweir #endif 975cdf0e10cSrcweir 976cdf0e10cSrcweir 977cdf0e10cSrcweir // Diese Routine ist hier definiert, damit der Compiler als eigenes Segment 978cdf0e10cSrcweir // geladen werden kann. 979cdf0e10cSrcweir 980cdf0e10cSrcweir sal_Bool SbModule::Compile() 981cdf0e10cSrcweir { 982cdf0e10cSrcweir if( pImage ) 983cdf0e10cSrcweir return sal_True; 984cdf0e10cSrcweir StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent()); 985cdf0e10cSrcweir if( !pBasic ) 986cdf0e10cSrcweir return sal_False; 987cdf0e10cSrcweir SbxBase::ResetError(); 988cdf0e10cSrcweir // Aktuelles Modul! 989cdf0e10cSrcweir SbModule* pOld = pCMOD; 990cdf0e10cSrcweir pCMOD = this; 991cdf0e10cSrcweir 992cdf0e10cSrcweir SbiParser* pParser = new SbiParser( (StarBASIC*) GetParent(), this ); 993cdf0e10cSrcweir while( pParser->Parse() ) {} 994cdf0e10cSrcweir if( !pParser->GetErrors() ) 995cdf0e10cSrcweir pParser->aGen.Save(); 996cdf0e10cSrcweir delete pParser; 997cdf0e10cSrcweir // fuer den Disassembler 998cdf0e10cSrcweir if( pImage ) 999cdf0e10cSrcweir pImage->aOUSource = aOUSource; 1000cdf0e10cSrcweir 1001cdf0e10cSrcweir pCMOD = pOld; 1002cdf0e10cSrcweir 1003cdf0e10cSrcweir // Beim Compilieren eines Moduls werden die Modul-globalen 1004cdf0e10cSrcweir // Variablen aller Module ungueltig 1005cdf0e10cSrcweir sal_Bool bRet = IsCompiled(); 1006cdf0e10cSrcweir if( bRet ) 1007cdf0e10cSrcweir { 1008cdf0e10cSrcweir if( !this->ISA(SbObjModule) ) 1009cdf0e10cSrcweir pBasic->ClearAllModuleVars(); 1010cdf0e10cSrcweir RemoveVars(); // remove 'this' Modules variables 1011cdf0e10cSrcweir // clear all method statics 1012cdf0e10cSrcweir for( sal_uInt16 i = 0; i < pMethods->Count(); i++ ) 1013cdf0e10cSrcweir { 1014cdf0e10cSrcweir SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) ); 1015cdf0e10cSrcweir if( p ) 1016cdf0e10cSrcweir p->ClearStatics(); 1017cdf0e10cSrcweir } 1018cdf0e10cSrcweir 1019cdf0e10cSrcweir // #i31510 Init other libs only if Basic isn't running 1020cdf0e10cSrcweir if( pINST == NULL ) 1021cdf0e10cSrcweir { 1022cdf0e10cSrcweir SbxObject* pParent_ = pBasic->GetParent(); 1023cdf0e10cSrcweir if( pParent_ ) 1024cdf0e10cSrcweir pBasic = PTR_CAST(StarBASIC,pParent_); 1025cdf0e10cSrcweir if( pBasic ) 1026cdf0e10cSrcweir pBasic->ClearAllModuleVars(); 1027cdf0e10cSrcweir } 1028cdf0e10cSrcweir } 1029cdf0e10cSrcweir 1030cdf0e10cSrcweir #ifdef DBG_SAVE_DISASSEMBLY 1031cdf0e10cSrcweir dbg_SaveDisassembly( this ); 1032cdf0e10cSrcweir #endif 1033cdf0e10cSrcweir 1034cdf0e10cSrcweir #ifdef DBG_TRACE_BASIC 1035cdf0e10cSrcweir lcl_PrepareTraceForModule( this ); 1036cdf0e10cSrcweir #endif 1037cdf0e10cSrcweir 1038cdf0e10cSrcweir return bRet; 1039cdf0e10cSrcweir } 1040cdf0e10cSrcweir 1041cdf0e10cSrcweir /************************************************************************** 1042cdf0e10cSrcweir * 1043cdf0e10cSrcweir * Syntax-Highlighting 1044cdf0e10cSrcweir * 1045cdf0e10cSrcweir **************************************************************************/ 1046cdf0e10cSrcweir 1047cdf0e10cSrcweir void StarBASIC::Highlight( const String& rSrc, SbTextPortions& rList ) 1048cdf0e10cSrcweir { 1049cdf0e10cSrcweir SbiTokenizer aTok( rSrc ); 1050cdf0e10cSrcweir aTok.Hilite( rList ); 1051cdf0e10cSrcweir } 1052cdf0e10cSrcweir 1053