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

Generated by: LCOV version 1.11