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

Generated by: LCOV version 1.10