LCOV - code coverage report
Current view: top level - basic/source/comp - sbcomp.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 32 33 97.0 %
Date: 2014-04-11 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10