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

Generated by: LCOV version 1.10