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