2010-10-12 15:53:47 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2012-07-17 12:30:48 +01:00
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following license notice:
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
|
|
* with this work for additional information regarding copyright
|
|
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
|
|
*/
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2006-09-17 09:03:16 +00:00
|
|
|
|
2007-06-27 13:20:58 +00:00
|
|
|
#include <basic/sbx.hxx>
|
2000-09-18 15:18:56 +00:00
|
|
|
#include "sbcomp.hxx"
|
|
|
|
#include "image.hxx"
|
2013-12-11 10:39:57 +02:00
|
|
|
#include "sbobjmod.hxx"
|
GSOC work week 2, getting infromation from variables and print on terminal
This is an early version. I use the BASIC parser to parse the source,
then the infromation is extracted from the symbol table built by parser.
Error reporting is suppressed, beacuse it is not needed fro code completition.
I placed my function inside SbModule, and created a struct called CodeCompletitionData, which holds the object's name, it's parent, and it's type name.
This function, SbMethod::GetCodeCompleteDataFromParse() is called from Basic IDE's Notify function, which updates a cache(actually, reassigns a viariable :) ).
Later, in the EditorWindow::KeyInput function there is a check wheteher dot key is pressed. After that, the actual variable (or word) is being looked up in the vector that holds code completition data. And finally, if it is found, it's methods are printed on the terminal.
Change-Id: Idaf19baa8f720b8b117a76dc3cc2f90dd04fd155
2013-06-21 14:10:31 +02:00
|
|
|
#include <svtools/miscopt.hxx>
|
2011-03-30 13:17:45 +02:00
|
|
|
#include <stdio.h>
|
2014-05-29 09:27:30 +09:00
|
|
|
#include <boost/scoped_ptr.hpp>
|
2015-01-25 13:58:08 +01:00
|
|
|
#include <rtl/character.hxx>
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2010-07-26 14:20:03 +02:00
|
|
|
// To activate tracing enable in sbtrace.hxx
|
|
|
|
#ifdef DBG_TRACE_BASIC
|
|
|
|
|
2010-08-23 11:16:00 +02:00
|
|
|
// Trace ini file (set NULL to ignore)
|
2011-03-25 10:40:25 +01:00
|
|
|
// can be overridden with the environment variable OOO_BASICTRACEINI
|
|
|
|
static char GpTraceIniFile[] = "~/BasicTrace.ini";
|
2010-08-23 11:16:00 +02:00
|
|
|
//static char* GpTraceIniFile = NULL;
|
|
|
|
|
|
|
|
// Trace Settings, used if no ini file / not found in ini file
|
2011-03-25 10:40:25 +01:00
|
|
|
static char GpTraceFileNameDefault[] = "~/BasicTrace.txt";
|
2010-08-23 11:16:00 +02:00
|
|
|
static char* GpTraceFileName = GpTraceFileNameDefault;
|
|
|
|
|
|
|
|
// GbTraceOn:
|
|
|
|
// true = tracing is active, false = tracing is disabled, default = true
|
|
|
|
// Set to false initially if you want to activate tracing on demand with
|
|
|
|
// TraceCommand( "TraceOn" ), see below
|
|
|
|
static bool GbTraceOn = true;
|
|
|
|
|
|
|
|
// GbIncludePCodes:
|
|
|
|
// true = PCodes are written to trace, default = false, correspondents
|
|
|
|
// with TraceCommand( "PCodeOn" / "PCodeOff" ), see below
|
|
|
|
static bool GbIncludePCodes = false;
|
|
|
|
|
2011-03-25 10:40:25 +01:00
|
|
|
// GbInitOnlyAtOfficeStart:
|
|
|
|
// true = Tracing is only intialized onces after Office start when
|
|
|
|
// Basic runs the first time. Further calls to Basic, e.g. via events
|
|
|
|
// use the same output file. The trace ini file is not read again.
|
|
|
|
static bool GbInitOnlyAtOfficeStart = false;
|
|
|
|
|
2010-08-23 11:16:00 +02:00
|
|
|
static int GnIndentPerCallLevel = 4;
|
|
|
|
static int GnIndentForPCode = 2;
|
|
|
|
|
|
|
|
/*
|
|
|
|
With trace enabled the runtime function TraceCommand
|
|
|
|
can be used to influence the trace functionality
|
|
|
|
from within the running Basic macro.
|
|
|
|
|
|
|
|
Format: TraceCommand( command as String [, param as Variant] )
|
|
|
|
|
|
|
|
Supported commands (command is NOT case sensitive):
|
|
|
|
TraceCommand "TraceOn" sets GbTraceOn = true
|
|
|
|
TraceCommand "TraceOff" sets GbTraceOn = false
|
|
|
|
|
|
|
|
TraceCommand "PCodeOn" sets GbIncludePCodes = true
|
|
|
|
TraceCommand "PCodeOff" sets GbIncludePCodes = false
|
|
|
|
|
|
|
|
TraceCommand "Print", aVal writes aVal into the trace file as
|
|
|
|
long as it can be converted to string
|
|
|
|
*/
|
|
|
|
|
2011-03-25 10:40:25 +01:00
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <stack>
|
2013-11-11 21:25:36 -06:00
|
|
|
#include <canvas/elapsedtime.hxx>
|
2011-03-25 10:40:25 +01:00
|
|
|
|
|
|
|
//*** Profiling ***
|
|
|
|
// GbTimerOn:
|
|
|
|
// true = including time stamps
|
|
|
|
static bool GbTimerOn = true;
|
|
|
|
|
|
|
|
// GbTimeStampForEachStep:
|
|
|
|
// true = prints time stamp after each command / pcode (very slow)
|
|
|
|
static bool GbTimeStampForEachStep = false;
|
|
|
|
|
|
|
|
// GbBlockAllAfterFirstFunctionUsage:
|
|
|
|
// true = everything (commands, pcodes, functions) is only printed
|
|
|
|
// for the first usage (improves performance when tracing / pro-
|
|
|
|
// filing large macros)
|
|
|
|
static bool GbBlockAllAfterFirstFunctionUsage = false;
|
|
|
|
|
|
|
|
// GbBlockStepsAfterFirstFunctionUsage:
|
|
|
|
// true = commands / pcodes are only printed for the first time
|
|
|
|
// a function is executed. Afterwards only the entering/leaving
|
|
|
|
// messages are logged (improves performance when tracing / pro-
|
|
|
|
// filing large macros)
|
|
|
|
static bool GbBlockStepsAfterFirstFunctionUsage = false;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2010-08-23 11:16:00 +02:00
|
|
|
static void lcl_skipWhites( char*& rpc )
|
|
|
|
{
|
|
|
|
while( *rpc == ' ' || *rpc == '\t' )
|
|
|
|
++rpc;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void lcl_findNextLine( char*& rpc, char* pe )
|
|
|
|
{
|
|
|
|
// Find line end
|
|
|
|
while( rpc < pe && *rpc != 13 && *rpc != 10 )
|
|
|
|
++rpc;
|
|
|
|
|
|
|
|
// Read all
|
|
|
|
while( rpc < pe && (*rpc == 13 || *rpc == 10) )
|
|
|
|
++rpc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void lcl_ReadIniFile( const char* pIniFileName )
|
|
|
|
{
|
|
|
|
const int BUF_SIZE = 1000;
|
|
|
|
static sal_Char TraceFileNameBuffer[BUF_SIZE];
|
|
|
|
sal_Char Buffer[BUF_SIZE];
|
|
|
|
sal_Char VarNameBuffer[BUF_SIZE];
|
|
|
|
sal_Char ValBuffer[BUF_SIZE];
|
|
|
|
|
|
|
|
FILE* pFile = fopen( pIniFileName ,"rb" );
|
|
|
|
if( pFile == NULL )
|
|
|
|
return;
|
|
|
|
|
|
|
|
size_t nRead = fread( Buffer, 1, BUF_SIZE, pFile );
|
|
|
|
|
|
|
|
// Scan
|
|
|
|
char* pc = Buffer;
|
|
|
|
char* pe = Buffer + nRead;
|
|
|
|
while( pc < pe )
|
|
|
|
{
|
|
|
|
lcl_skipWhites( pc ); if( pc == pe ) break;
|
|
|
|
|
|
|
|
// Read variable
|
|
|
|
char* pVarStart = pc;
|
2015-01-25 13:58:08 +01:00
|
|
|
while( pc < pe && rtl::isAsciiAlpha( *pc ) )
|
2010-08-23 11:16:00 +02:00
|
|
|
++pc;
|
|
|
|
int nVarLen = pc - pVarStart;
|
|
|
|
if( nVarLen == 0 )
|
|
|
|
{
|
|
|
|
lcl_findNextLine( pc, pe );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
strncpy( VarNameBuffer, pVarStart, nVarLen );
|
|
|
|
VarNameBuffer[nVarLen] = '\0';
|
|
|
|
|
|
|
|
// Check =
|
|
|
|
lcl_skipWhites( pc ); if( pc == pe ) break;
|
|
|
|
if( *pc != '=' )
|
|
|
|
continue;
|
|
|
|
++pc;
|
|
|
|
lcl_skipWhites( pc ); if( pc == pe ) break;
|
|
|
|
|
|
|
|
// Read value
|
|
|
|
char* pValStart = pc;
|
|
|
|
while( pc < pe && *pc != 13 && *pc != 10 )
|
|
|
|
++pc;
|
|
|
|
int nValLen = pc - pValStart;
|
|
|
|
if( nValLen == 0 )
|
|
|
|
{
|
|
|
|
lcl_findNextLine( pc, pe );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
strncpy( ValBuffer, pValStart, nValLen );
|
|
|
|
ValBuffer[nValLen] = '\0';
|
|
|
|
|
|
|
|
// Match variables
|
|
|
|
if( strcmp( VarNameBuffer, "GpTraceFileName") == 0 )
|
|
|
|
{
|
|
|
|
strcpy( TraceFileNameBuffer, ValBuffer );
|
|
|
|
GpTraceFileName = TraceFileNameBuffer;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if( strcmp( VarNameBuffer, "GbTraceOn") == 0 )
|
|
|
|
GbTraceOn = (strcmp( ValBuffer, "true" ) == 0);
|
|
|
|
else
|
|
|
|
if( strcmp( VarNameBuffer, "GbIncludePCodes") == 0 )
|
|
|
|
GbIncludePCodes = (strcmp( ValBuffer, "true" ) == 0);
|
|
|
|
else
|
2011-03-25 10:40:25 +01:00
|
|
|
if( strcmp( VarNameBuffer, "GbInitOnlyAtOfficeStart") == 0 )
|
|
|
|
GbInitOnlyAtOfficeStart = (strcmp( ValBuffer, "true" ) == 0);
|
|
|
|
else
|
2010-08-23 11:16:00 +02:00
|
|
|
if( strcmp( VarNameBuffer, "GnIndentPerCallLevel") == 0 )
|
|
|
|
GnIndentPerCallLevel = strtol( ValBuffer, NULL, 10 );
|
|
|
|
else
|
|
|
|
if( strcmp( VarNameBuffer, "GnIndentForPCode") == 0 )
|
|
|
|
GnIndentForPCode = strtol( ValBuffer, NULL, 10 );
|
2011-03-25 10:40:25 +01:00
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
else
|
|
|
|
if( strcmp( VarNameBuffer, "GbTimerOn") == 0 )
|
|
|
|
GbTimerOn = (strcmp( ValBuffer, "true" ) == 0);
|
|
|
|
else
|
|
|
|
if( strcmp( VarNameBuffer, "GbTimeStampForEachStep") == 0 )
|
|
|
|
GbTimeStampForEachStep = (strcmp( ValBuffer, "true" ) == 0);
|
|
|
|
else
|
|
|
|
if( strcmp( VarNameBuffer, "GbBlockAllAfterFirstFunctionUsage") == 0 )
|
|
|
|
GbBlockAllAfterFirstFunctionUsage = (strcmp( ValBuffer, "true" ) == 0);
|
|
|
|
else
|
|
|
|
if( strcmp( VarNameBuffer, "GbBlockStepsAfterFirstFunctionUsage") == 0 )
|
|
|
|
GbBlockStepsAfterFirstFunctionUsage = (strcmp( ValBuffer, "true" ) == 0);
|
|
|
|
#endif
|
2010-08-23 11:16:00 +02:00
|
|
|
}
|
|
|
|
fclose( pFile );
|
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
|
|
struct TraceTextData
|
|
|
|
{
|
2013-04-07 12:06:47 +02:00
|
|
|
OString m_aTraceStr_STMNT;
|
|
|
|
OString m_aTraceStr_PCode;
|
2010-07-26 14:20:03 +02:00
|
|
|
};
|
|
|
|
typedef std::hash_map< sal_Int32, TraceTextData > PCToTextDataMap;
|
2012-12-30 13:07:28 -02:00
|
|
|
typedef std::hash_map< OUString, PCToTextDataMap*, OUStringHash, ::std::equal_to< OUString > > ModuleTraceMap;
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
|
|
ModuleTraceMap GaModuleTraceMap;
|
|
|
|
ModuleTraceMap& rModuleTraceMap = GaModuleTraceMap;
|
|
|
|
|
2011-03-25 10:40:25 +01:00
|
|
|
static FILE* GpGlobalFile = NULL;
|
|
|
|
|
|
|
|
static void lcl_lineOut( const char* pStr, const char* pPreStr = NULL, const char* pPostStr = NULL )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
if( GpGlobalFile != NULL )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
fprintf( GpGlobalFile, "%s%s%s\n", pPreStr ? pPreStr : "", pStr, pPostStr ? pPostStr : "" );
|
|
|
|
fflush( GpGlobalFile );
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* lcl_getSpaces( int nSpaceCount )
|
|
|
|
{
|
2013-07-22 20:57:11 +09:00
|
|
|
static const sal_Char Spaces[] = " "
|
2010-07-26 14:20:03 +02:00
|
|
|
" "
|
|
|
|
" ";
|
2013-07-22 20:57:11 +09:00
|
|
|
static const int nAvailableSpaceCount = strlen( Spaces );
|
|
|
|
static const sal_Char* pSpacesEnd = Spaces + nAvailableSpaceCount;
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
|
|
if( nSpaceCount > nAvailableSpaceCount )
|
|
|
|
nSpaceCount = nAvailableSpaceCount;
|
|
|
|
|
|
|
|
return pSpacesEnd - nSpaceCount;
|
|
|
|
}
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
static OString lcl_toOStringSkipLeadingWhites( const OUString& aStr )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
2013-04-07 12:06:47 +02:00
|
|
|
OString aOStr = OUStringToOString( OUString( aStr ), RTL_TEXTENCODING_ASCII_US );
|
2010-07-26 14:20:03 +02:00
|
|
|
const sal_Char* pStr = aOStr.getStr();
|
|
|
|
|
|
|
|
// Skip whitespace
|
|
|
|
sal_Char c = *pStr;
|
|
|
|
while( c == ' ' || c == '\t' )
|
|
|
|
{
|
|
|
|
pStr++;
|
|
|
|
c = *pStr;
|
|
|
|
}
|
|
|
|
|
2015-02-06 20:01:31 +01:00
|
|
|
OString aORetStr( pStr, strlen(pStr) );
|
2010-07-26 14:20:03 +02:00
|
|
|
return aORetStr;
|
|
|
|
}
|
|
|
|
|
2013-10-10 11:51:22 +02:00
|
|
|
OUString lcl_dumpMethodParameters( SbMethod* pMethod )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
2012-11-06 23:34:23 -06:00
|
|
|
OUString aStr;
|
2010-07-26 14:20:03 +02:00
|
|
|
if( pMethod == NULL )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-07-26 14:20:03 +02:00
|
|
|
return aStr;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
SbxError eOld = SbxBase::GetError();
|
|
|
|
|
|
|
|
SbxArray* pParams = pMethod->GetParameters();
|
|
|
|
SbxInfo* pInfo = pMethod->GetInfo();
|
|
|
|
if ( pParams )
|
|
|
|
{
|
|
|
|
aStr += '(';
|
|
|
|
// 0 is sub itself
|
2011-01-10 14:40:57 +01:00
|
|
|
for ( sal_uInt16 nParam = 1; nParam < pParams->Count(); nParam++ )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
|
|
|
SbxVariable* pVar = pParams->Get( nParam );
|
|
|
|
DBG_ASSERT( pVar, "Parameter?!" );
|
2012-11-06 23:34:23 -06:00
|
|
|
if ( !pVar->GetName().isEmpty() )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-07-26 14:20:03 +02:00
|
|
|
aStr += pVar->GetName();
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
else if ( pInfo )
|
|
|
|
{
|
|
|
|
const SbxParamInfo* pParam = pInfo->GetParam( nParam );
|
|
|
|
if ( pParam )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-07-26 14:20:03 +02:00
|
|
|
aStr += pParam->aName;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
|
|
|
aStr += '=';
|
2010-09-06 14:57:23 +02:00
|
|
|
SbxDataType eType = pVar->GetType();
|
|
|
|
if( eType & SbxARRAY )
|
2012-11-06 23:34:23 -06:00
|
|
|
{
|
|
|
|
aStr += "...";
|
|
|
|
}
|
2010-09-06 14:57:23 +02:00
|
|
|
else if( eType != SbxOBJECT )
|
2012-11-06 23:34:23 -06:00
|
|
|
{
|
2010-07-26 14:20:03 +02:00
|
|
|
aStr += pVar->GetString();
|
2012-11-06 23:34:23 -06:00
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
if ( nParam < ( pParams->Count() - 1 ) )
|
2012-11-06 23:34:23 -06:00
|
|
|
{
|
|
|
|
aStr += ", ";
|
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
|
|
|
aStr += ')';
|
|
|
|
}
|
|
|
|
|
|
|
|
SbxBase::ResetError();
|
|
|
|
if( eOld != SbxERR_OK )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-07-26 14:20:03 +02:00
|
|
|
SbxBase::SetError( eOld );
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
return aStr;
|
|
|
|
}
|
|
|
|
|
2010-08-23 11:16:00 +02:00
|
|
|
|
2010-07-26 14:20:03 +02:00
|
|
|
// Public functions
|
2010-08-23 11:16:00 +02:00
|
|
|
static bool GbSavTraceOn = false;
|
2011-03-25 10:40:25 +01:00
|
|
|
|
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
static canvas::tools::ElapsedTime* GpTimer = NULL;
|
|
|
|
static double GdStartTime = 0.0;
|
|
|
|
static double GdLastTime = 0.0;
|
|
|
|
static bool GbBlockSteps = false;
|
|
|
|
static bool GbBlockAll = false;
|
|
|
|
|
|
|
|
struct FunctionItem
|
|
|
|
{
|
2012-11-06 23:34:23 -06:00
|
|
|
OUString m_aCompleteFunctionName;
|
2011-03-25 10:40:25 +01:00
|
|
|
double m_dTotalTime;
|
|
|
|
double m_dNetTime;
|
|
|
|
int m_nCallCount;
|
|
|
|
bool m_bBlockAll;
|
|
|
|
bool m_bBlockSteps;
|
|
|
|
|
2015-04-14 12:44:47 +02:00
|
|
|
FunctionItem()
|
2011-03-25 10:40:25 +01:00
|
|
|
: m_dTotalTime( 0.0 )
|
|
|
|
, m_dNetTime( 0.0 )
|
|
|
|
, m_nCallCount( 0 )
|
|
|
|
, m_bBlockAll( false )
|
|
|
|
, m_bBlockSteps( false )
|
|
|
|
{}
|
|
|
|
};
|
2012-12-30 13:07:28 -02:00
|
|
|
typedef std::hash_map< OUString, FunctionItem*, OUStringHash, ::std::equal_to< OUString > > FunctionItemMap;
|
2011-03-25 10:40:25 +01:00
|
|
|
|
|
|
|
static std::stack< double > GaCallEnterTimeStack;
|
|
|
|
static std::stack< FunctionItem* > GaFunctionItemStack;
|
|
|
|
static FunctionItemMap GaFunctionItemMap;
|
|
|
|
|
|
|
|
bool compareFunctionNetTime( FunctionItem* p1, FunctionItem* p2 )
|
|
|
|
{
|
|
|
|
return (p1->m_dNetTime > p2->m_dNetTime);
|
|
|
|
}
|
|
|
|
|
2015-04-14 12:44:47 +02:00
|
|
|
void lcl_printTimeOutput()
|
2011-03-25 10:40:25 +01:00
|
|
|
{
|
|
|
|
// Overall time output
|
|
|
|
lcl_lineOut( "" );
|
2014-10-08 14:34:58 +02:00
|
|
|
lcl_lineOut( "***** Time Output *****" );
|
2011-03-25 10:40:25 +01:00
|
|
|
char TimeBuffer[500];
|
|
|
|
double dTotalTime = GpTimer->getElapsedTime() - GdStartTime;
|
|
|
|
sprintf( TimeBuffer, "Total execution time = %f ms", dTotalTime*1000.0 );
|
|
|
|
lcl_lineOut( TimeBuffer );
|
|
|
|
lcl_lineOut( "" );
|
|
|
|
|
|
|
|
if( GbTimerOn )
|
|
|
|
{
|
|
|
|
lcl_lineOut( "Functions:" );
|
|
|
|
|
|
|
|
std::vector<FunctionItem*> avFunctionItems;
|
|
|
|
|
|
|
|
FunctionItemMap::iterator it;
|
|
|
|
for( it = GaFunctionItemMap.begin() ; it != GaFunctionItemMap.end() ; ++it )
|
|
|
|
{
|
|
|
|
FunctionItem* pFunctionItem = it->second;
|
|
|
|
if( pFunctionItem != NULL )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
avFunctionItems.push_back( pFunctionItem );
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::sort( avFunctionItems.begin(), avFunctionItems.end(), compareFunctionNetTime );
|
|
|
|
|
|
|
|
std::vector<FunctionItem*>::iterator itv;
|
|
|
|
for( itv = avFunctionItems.begin() ; itv != avFunctionItems.end() ; ++itv )
|
|
|
|
{
|
|
|
|
FunctionItem* pFunctionItem = *itv;
|
|
|
|
if( pFunctionItem != NULL )
|
|
|
|
{
|
2012-11-06 23:34:23 -06:00
|
|
|
OUString aCompleteFunctionName = pFunctionItem->m_aCompleteFunctionName;
|
2014-09-20 12:14:41 +08:00
|
|
|
OString aName = OUStringToOString( aCompleteFunctionName, RTL_TEXTENCODING_ASCII_US );
|
2011-03-25 10:40:25 +01:00
|
|
|
int nNameLen = aCompleteFunctionName.getLength();
|
|
|
|
|
|
|
|
double dFctTotalTime = pFunctionItem->m_dTotalTime;
|
|
|
|
double dFctNetTime = pFunctionItem->m_dNetTime;
|
|
|
|
double dFctTotalTimePercent = 100.0 * dFctTotalTime / dTotalTime;
|
|
|
|
double dFctNetTimePercent = 100.0 * dFctNetTime / dTotalTime;
|
|
|
|
int nSpaceCount = 30 - nNameLen;
|
|
|
|
if( nSpaceCount < 0 )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
nSpaceCount = 2;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
sprintf( TimeBuffer, "%s:%sCalled %d times\t%f ms (%f%%) / net %f (%f%%) ms",
|
2014-09-20 12:14:41 +08:00
|
|
|
aName.getStr(), lcl_getSpaces( nSpaceCount ), pFunctionItem->m_nCallCount,
|
2012-11-03 09:07:25 -05:00
|
|
|
dFctTotalTime*1000.0, dFctTotalTimePercent, dFctNetTime*1000.0, dFctNetTimePercent );
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_lineOut( TimeBuffer );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static bool GbInitTraceAlreadyCalled = false;
|
|
|
|
|
2015-04-14 12:44:47 +02:00
|
|
|
void dbg_InitTrace()
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
if( GbInitOnlyAtOfficeStart && GbInitTraceAlreadyCalled )
|
|
|
|
{
|
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
if( GbTimerOn )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
GpTimer->continueTimer();
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
#endif
|
|
|
|
GpGlobalFile = fopen( GpTraceFileName, "a+" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
GbInitTraceAlreadyCalled = true;
|
|
|
|
|
|
|
|
if( const sal_Char* pcIniFileName = ::getenv( "OOO_BASICTRACEINI" ) )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_ReadIniFile( pcIniFileName );
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
else if( GpTraceIniFile != NULL )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
lcl_ReadIniFile( GpTraceIniFile );
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
GpGlobalFile = fopen( GpTraceFileName, "w" );
|
2010-08-23 11:16:00 +02:00
|
|
|
GbSavTraceOn = GbTraceOn;
|
|
|
|
if( !GbTraceOn )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_lineOut( "### Program started with trace off ###" );
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
GpTimer = new canvas::tools::ElapsedTime();
|
|
|
|
GdStartTime = GpTimer->getElapsedTime();
|
|
|
|
GdLastTime = GdStartTime;
|
|
|
|
GbBlockSteps = false;
|
|
|
|
GbBlockAll = false;
|
|
|
|
#endif
|
2010-08-23 11:16:00 +02:00
|
|
|
}
|
|
|
|
|
2015-04-14 12:44:47 +02:00
|
|
|
void dbg_DeInitTrace()
|
2010-08-23 11:16:00 +02:00
|
|
|
{
|
|
|
|
GbTraceOn = GbSavTraceOn;
|
2011-03-25 10:40:25 +01:00
|
|
|
|
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
while( !GaCallEnterTimeStack.empty() )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
GaCallEnterTimeStack.pop();
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
while( !GaFunctionItemStack.empty() )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
GaFunctionItemStack.pop();
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_printTimeOutput();
|
|
|
|
|
|
|
|
for( FunctionItemMap::iterator it = GaFunctionItemMap.begin() ; it != GaFunctionItemMap.end() ; ++it )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
delete it->second;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
GaFunctionItemMap.clear();
|
|
|
|
|
|
|
|
if( GpGlobalFile )
|
|
|
|
{
|
|
|
|
fclose( GpGlobalFile );
|
|
|
|
GpGlobalFile = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( GbInitOnlyAtOfficeStart )
|
|
|
|
{
|
|
|
|
if( GbTimerOn )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
GpTimer->pauseTimer();
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete GpTimer;
|
|
|
|
}
|
|
|
|
#endif
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
|
|
|
|
2011-01-10 14:40:57 +01:00
|
|
|
static sal_Int32 GnLastCallLvl = 0;
|
2010-08-23 11:16:00 +02:00
|
|
|
|
2012-11-06 23:34:23 -06:00
|
|
|
void dbg_tracePrint( const OUString& aStr, sal_Int32 nCallLvl, bool bCallLvlRelativeToCurrent )
|
2011-03-25 10:40:25 +01:00
|
|
|
{
|
|
|
|
if( bCallLvlRelativeToCurrent )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
nCallLvl += GnLastCallLvl;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
int nIndent = nCallLvl * GnIndentPerCallLevel;
|
2012-12-30 13:07:28 -02:00
|
|
|
lcl_lineOut( OUStringToOString( OUString( aStr ), RTL_TEXTENCODING_ASCII_US ).getStr(), lcl_getSpaces( nIndent ) );
|
2011-03-25 10:40:25 +01:00
|
|
|
}
|
|
|
|
|
2011-01-10 14:40:57 +01:00
|
|
|
void dbg_traceStep( SbModule* pModule, sal_uInt32 nPC, sal_Int32 nCallLvl )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
if( !GbTraceOn )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
return;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
if( GbBlockSteps || GbBlockAll )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
return;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
double dCurTime = 0.0;
|
|
|
|
bool bPrintTimeStamp = false;
|
|
|
|
if( GbTimerOn )
|
|
|
|
{
|
|
|
|
GpTimer->pauseTimer();
|
|
|
|
dCurTime = GpTimer->getElapsedTime();
|
|
|
|
bPrintTimeStamp = GbTimeStampForEachStep;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
bool bPrintTimeStamp = false;
|
|
|
|
#endif
|
|
|
|
|
2010-08-23 11:16:00 +02:00
|
|
|
GnLastCallLvl = nCallLvl;
|
|
|
|
|
2010-07-26 14:20:03 +02:00
|
|
|
SbModule* pTraceMod = pModule;
|
|
|
|
if( pTraceMod->ISA(SbClassModuleObject) )
|
|
|
|
{
|
|
|
|
SbClassModuleObject* pClassModuleObj = (SbClassModuleObject*)(SbxBase*)pTraceMod;
|
|
|
|
pTraceMod = pClassModuleObj->getClassModule();
|
|
|
|
}
|
|
|
|
|
2012-11-06 23:34:23 -06:00
|
|
|
OUString aModuleName = pTraceMod->GetName();
|
2010-07-26 14:20:03 +02:00
|
|
|
ModuleTraceMap::iterator it = rModuleTraceMap.find( aModuleName );
|
|
|
|
if( it == rModuleTraceMap.end() )
|
|
|
|
{
|
2014-09-20 12:14:41 +08:00
|
|
|
OString aModuleNameStr = OUStringToOString( OUString( aModuleName ), RTL_TEXTENCODING_ASCII_US );
|
2010-07-26 14:20:03 +02:00
|
|
|
char Buffer[200];
|
2014-09-20 12:14:41 +08:00
|
|
|
sprintf( Buffer, "TRACE ERROR: Unknown module \"%s\"", aModuleNameStr.getStr() );
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_lineOut( Buffer );
|
2010-07-26 14:20:03 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PCToTextDataMap* pInnerMap = it->second;
|
|
|
|
if( pInnerMap == NULL )
|
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_lineOut( "TRACE INTERNAL ERROR: No inner map" );
|
2010-07-26 14:20:03 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PCToTextDataMap::iterator itInner = pInnerMap->find( nPC );
|
|
|
|
if( itInner == pInnerMap->end() )
|
|
|
|
{
|
2014-09-20 12:14:41 +08:00
|
|
|
OString aModuleNameStr = OUStringToOString( OUString( aModuleName ), RTL_TEXTENCODING_ASCII_US );
|
2010-07-26 14:20:03 +02:00
|
|
|
char Buffer[200];
|
2014-09-20 12:14:41 +08:00
|
|
|
sprintf( Buffer, "TRACE ERROR: No info for PC = %d in module \"%s\"", (int)nPC, aModuleNameStr.getStr() );
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_lineOut( Buffer );
|
2010-07-26 14:20:03 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nIndent = nCallLvl * GnIndentPerCallLevel;
|
|
|
|
|
|
|
|
const TraceTextData& rTraceTextData = itInner->second;
|
2013-04-07 12:06:47 +02:00
|
|
|
const OString& rStr_STMNT = rTraceTextData.m_aTraceStr_STMNT;
|
2011-03-25 10:40:25 +01:00
|
|
|
bool bSTMT = false;
|
2014-02-04 08:48:47 +00:00
|
|
|
if( !rStr_STMNT.isEmpty() )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
bSTMT = true;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
char TimeBuffer[200];
|
2013-02-12 11:37:53 +01:00
|
|
|
memset (TimeBuffer, 0, size(TimeBuffer));
|
2011-03-25 10:40:25 +01:00
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
if( bPrintTimeStamp )
|
|
|
|
{
|
|
|
|
double dDiffTime = dCurTime - GdLastTime;
|
|
|
|
GdLastTime = dCurTime;
|
2014-10-08 14:23:41 +02:00
|
|
|
sprintf( TimeBuffer, "\t\t// Time = %f ms / += %f ms", dCurTime*1000.0, dDiffTime*1000.0 );
|
2011-03-25 10:40:25 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if( bSTMT )
|
|
|
|
{
|
|
|
|
lcl_lineOut( rStr_STMNT.getStr(), lcl_getSpaces( nIndent ),
|
2012-11-03 09:07:25 -05:00
|
|
|
(bPrintTimeStamp && !GbIncludePCodes) ? TimeBuffer : NULL );
|
2011-03-25 10:40:25 +01:00
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
|
|
if( !GbIncludePCodes )
|
2011-03-25 10:40:25 +01:00
|
|
|
{
|
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
if( GbTimerOn )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
GpTimer->continueTimer();
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
#endif
|
2010-07-26 14:20:03 +02:00
|
|
|
return;
|
2011-03-25 10:40:25 +01:00
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
|
|
nIndent += GnIndentForPCode;
|
2013-04-07 12:06:47 +02:00
|
|
|
const OString& rStr_PCode = rTraceTextData.m_aTraceStr_PCode;
|
2014-02-04 08:48:47 +00:00
|
|
|
if( !rStr_PCode.isEmpty() )
|
2011-03-25 10:40:25 +01:00
|
|
|
{
|
|
|
|
lcl_lineOut( rStr_PCode.getStr(), lcl_getSpaces( nIndent ),
|
2012-11-03 09:07:25 -05:00
|
|
|
bPrintTimeStamp ? TimeBuffer : NULL );
|
2011-03-25 10:40:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
if( GbTimerOn )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
GpTimer->continueTimer();
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
#endif
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
|
|
|
|
2011-03-25 10:40:25 +01:00
|
|
|
|
2011-01-10 14:40:57 +01:00
|
|
|
void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, sal_Int32 nCallLvl, bool bLeave )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
|
|
|
|
2010-08-23 11:16:00 +02:00
|
|
|
if( !GbTraceOn )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
return;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
double dCurTime = 0.0;
|
|
|
|
double dExecutionTime = 0.0;
|
|
|
|
if( GbTimerOn )
|
|
|
|
{
|
|
|
|
dCurTime = GpTimer->getElapsedTime();
|
|
|
|
GpTimer->pauseTimer();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-08-23 11:16:00 +02:00
|
|
|
GnLastCallLvl = nCallLvl;
|
|
|
|
|
2010-07-26 14:20:03 +02:00
|
|
|
SbModule* pTraceMod = pModule;
|
|
|
|
SbClassModuleObject* pClassModuleObj = NULL;
|
|
|
|
if( pTraceMod->ISA(SbClassModuleObject) )
|
|
|
|
{
|
|
|
|
pClassModuleObj = (SbClassModuleObject*)(SbxBase*)pTraceMod;
|
|
|
|
pTraceMod = pClassModuleObj->getClassModule();
|
|
|
|
}
|
|
|
|
|
2012-11-06 23:34:23 -06:00
|
|
|
OUString aCompleteFunctionName = pTraceMod->GetName();
|
2011-03-25 10:40:25 +01:00
|
|
|
if( pMethod != NULL )
|
|
|
|
{
|
2012-11-06 23:34:23 -06:00
|
|
|
aCompleteFunctionName += "::";
|
|
|
|
OUString aMethodName = pMethod->GetName();
|
2011-03-25 10:40:25 +01:00
|
|
|
aCompleteFunctionName += aMethodName;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-11-06 23:34:23 -06:00
|
|
|
aCompleteFunctionName += "/RunInit";
|
2011-03-25 10:40:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool bOwnBlockSteps = false;
|
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
bool bOwnBlockAll = false;
|
|
|
|
FunctionItem* pFunctionItem = NULL;
|
|
|
|
if( GbTimerOn )
|
|
|
|
{
|
|
|
|
FunctionItemMap::iterator itFunctionItem = GaFunctionItemMap.find( aCompleteFunctionName );
|
|
|
|
if( itFunctionItem != GaFunctionItemMap.end() )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
pFunctionItem = itFunctionItem->second;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
if( pFunctionItem == NULL )
|
|
|
|
{
|
|
|
|
DBG_ASSERT( !bLeave, "No FunctionItem in leave!" );
|
|
|
|
|
|
|
|
pFunctionItem = new FunctionItem();
|
|
|
|
pFunctionItem->m_aCompleteFunctionName = aCompleteFunctionName;
|
|
|
|
GaFunctionItemMap[ aCompleteFunctionName ] = pFunctionItem;
|
|
|
|
}
|
|
|
|
else if( GbBlockAllAfterFirstFunctionUsage && !bLeave )
|
|
|
|
{
|
|
|
|
pFunctionItem->m_bBlockAll = true;
|
|
|
|
}
|
|
|
|
else if( GbBlockStepsAfterFirstFunctionUsage && !bLeave )
|
|
|
|
{
|
|
|
|
pFunctionItem->m_bBlockSteps = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( bLeave )
|
|
|
|
{
|
|
|
|
bOwnBlockAll = GbBlockAll;
|
|
|
|
bOwnBlockSteps = GbBlockSteps;
|
|
|
|
GbBlockAll = false;
|
|
|
|
GbBlockSteps = false;
|
|
|
|
|
|
|
|
dExecutionTime = dCurTime - GaCallEnterTimeStack.top();
|
|
|
|
GaCallEnterTimeStack.pop();
|
|
|
|
|
|
|
|
pFunctionItem->m_dTotalTime += dExecutionTime;
|
|
|
|
pFunctionItem->m_dNetTime += dExecutionTime;
|
|
|
|
pFunctionItem->m_nCallCount++;
|
|
|
|
|
|
|
|
GaFunctionItemStack.pop();
|
|
|
|
if( !GaFunctionItemStack.empty() )
|
|
|
|
{
|
|
|
|
FunctionItem* pParentItem = GaFunctionItemStack.top();
|
|
|
|
if( pParentItem != NULL )
|
|
|
|
{
|
|
|
|
pParentItem->m_dNetTime -= dExecutionTime;
|
|
|
|
|
|
|
|
GbBlockSteps = pParentItem->m_bBlockSteps;
|
|
|
|
GbBlockAll = pParentItem->m_bBlockAll;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GbBlockSteps = bOwnBlockSteps = pFunctionItem->m_bBlockSteps;
|
|
|
|
GbBlockAll = bOwnBlockAll = pFunctionItem->m_bBlockAll;
|
|
|
|
|
|
|
|
GaCallEnterTimeStack.push( dCurTime );
|
|
|
|
GaFunctionItemStack.push( pFunctionItem );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( bOwnBlockAll )
|
|
|
|
{
|
|
|
|
if( GbTimerOn )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
GpTimer->continueTimer();
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-07-26 14:20:03 +02:00
|
|
|
if( nCallLvl > 0 )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-07-26 14:20:03 +02:00
|
|
|
nCallLvl--;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
int nIndent = nCallLvl * GnIndentPerCallLevel;
|
2011-03-25 10:40:25 +01:00
|
|
|
if( !bLeave && !bOwnBlockSteps )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
2012-12-28 17:59:40 +01:00
|
|
|
static const char* pSeparator = "' ================================================================================";
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_lineOut( "" );
|
|
|
|
lcl_lineOut( pSeparator, lcl_getSpaces( nIndent ) );
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
|
|
|
|
2012-11-06 23:34:23 -06:00
|
|
|
OUString aStr;
|
2010-07-26 14:20:03 +02:00
|
|
|
if( bLeave )
|
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
if( !bOwnBlockSteps )
|
|
|
|
{
|
|
|
|
lcl_lineOut( "}", lcl_getSpaces( nIndent ) );
|
2012-11-06 23:34:23 -06:00
|
|
|
aStr = "' Leaving ";
|
2011-03-25 10:40:25 +01:00
|
|
|
}
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-11-06 23:34:23 -06:00
|
|
|
aStr = "Entering " ;
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
if( !bLeave || !bOwnBlockSteps )
|
2012-11-06 23:34:23 -06:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
aStr += aCompleteFunctionName;
|
2012-11-06 23:34:23 -06:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
if( !bOwnBlockSteps && pClassModuleObj != NULL )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
2012-11-06 23:34:23 -06:00
|
|
|
aStr += "[this=";
|
2010-07-26 14:20:03 +02:00
|
|
|
aStr += pClassModuleObj->GetName();
|
2012-11-06 23:34:23 -06:00
|
|
|
aStr += "]" ;
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
|
|
|
if( !bLeave )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
aStr += lcl_dumpMethodParameters( pMethod );
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
const char* pPostStr = NULL;
|
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
char TimeBuffer[200];
|
|
|
|
if( GbTimerOn && bLeave )
|
|
|
|
{
|
2014-10-08 14:23:41 +02:00
|
|
|
sprintf( TimeBuffer, " // Execution Time = %f ms", dExecutionTime*1000.0 );
|
2011-03-25 10:40:25 +01:00
|
|
|
pPostStr = TimeBuffer;
|
|
|
|
}
|
|
|
|
#endif
|
2012-12-30 13:07:28 -02:00
|
|
|
lcl_lineOut( (!bLeave || !bOwnBlockSteps) ? OUStringToOString( OUString( aStr ), RTL_TEXTENCODING_ASCII_US ).getStr() : "}",
|
2012-11-03 09:07:25 -05:00
|
|
|
lcl_getSpaces( nIndent ), pPostStr );
|
2010-07-26 14:20:03 +02:00
|
|
|
if( !bLeave )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_lineOut( "{", lcl_getSpaces( nIndent ) );
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
if( bLeave && !bOwnBlockSteps )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_lineOut( "" );
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
if( GbTimerOn )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
GpTimer->continueTimer();
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
#endif
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
|
|
|
|
2012-11-06 23:34:23 -06:00
|
|
|
void dbg_traceNotifyError( SbError nTraceErr, const OUString& aTraceErrMsg,
|
|
|
|
bool bTraceErrHandled, sal_Int32 nCallLvl )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
if( !GbTraceOn )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
return;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
#ifdef DBG_TRACE_PROFILING
|
|
|
|
if( GbBlockSteps || GbBlockAll )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2011-03-25 10:40:25 +01:00
|
|
|
return;
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2011-03-25 10:40:25 +01:00
|
|
|
#endif
|
2010-08-23 11:16:00 +02:00
|
|
|
GnLastCallLvl = nCallLvl;
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
OString aOTraceErrMsg = OUStringToOString( OUString( aTraceErrMsg ), RTL_TEXTENCODING_ASCII_US );
|
2010-07-26 14:20:03 +02:00
|
|
|
|
|
|
|
char Buffer[200];
|
|
|
|
const char* pHandledStr = bTraceErrHandled ? " / HANDLED" : "";
|
|
|
|
sprintf( Buffer, "*** ERROR%s, Id = %d, Msg = \"%s\" ***", pHandledStr, (int)nTraceErr, aOTraceErrMsg.getStr() );
|
|
|
|
int nIndent = nCallLvl * GnIndentPerCallLevel;
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_lineOut( Buffer, lcl_getSpaces( nIndent ) );
|
2010-07-26 14:20:03 +02:00
|
|
|
}
|
|
|
|
|
2011-01-10 14:40:57 +01:00
|
|
|
void dbg_RegisterTraceTextForPC( SbModule* pModule, sal_uInt32 nPC,
|
2012-11-06 23:34:23 -06:00
|
|
|
const OUString& aTraceStr_STMNT, const OUString& aTraceStr_PCode )
|
2010-07-26 14:20:03 +02:00
|
|
|
{
|
2012-11-06 23:34:23 -06:00
|
|
|
OUString aModuleName = pModule->GetName();
|
2010-07-26 14:20:03 +02:00
|
|
|
ModuleTraceMap::iterator it = rModuleTraceMap.find( aModuleName );
|
|
|
|
PCToTextDataMap* pInnerMap;
|
|
|
|
if( it == rModuleTraceMap.end() )
|
|
|
|
{
|
|
|
|
pInnerMap = new PCToTextDataMap();
|
|
|
|
rModuleTraceMap[ aModuleName ] = pInnerMap;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pInnerMap = it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
TraceTextData aData;
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
OString aOTraceStr_STMNT = lcl_toOStringSkipLeadingWhites( aTraceStr_STMNT );
|
2010-07-26 14:20:03 +02:00
|
|
|
aData.m_aTraceStr_STMNT = aOTraceStr_STMNT;
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
OString aOTraceStr_PCode = lcl_toOStringSkipLeadingWhites( aTraceStr_PCode );
|
2010-07-26 14:20:03 +02:00
|
|
|
aData.m_aTraceStr_PCode = aOTraceStr_PCode;
|
|
|
|
|
|
|
|
(*pInnerMap)[nPC] = aData;
|
|
|
|
}
|
|
|
|
|
2011-01-10 14:40:57 +01:00
|
|
|
void RTL_Impl_TraceCommand( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
|
2010-08-23 11:16:00 +02:00
|
|
|
{
|
|
|
|
(void)pBasic;
|
|
|
|
(void)bWrite;
|
|
|
|
|
|
|
|
if ( rPar.Count() < 2 )
|
|
|
|
{
|
|
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-11-06 23:34:23 -06:00
|
|
|
OUString aCommand = rPar.Get(1)->GetString();
|
2010-08-23 11:16:00 +02:00
|
|
|
|
2012-11-06 23:34:23 -06:00
|
|
|
if( aCommand.equalsIngoreAsciiCase( "TraceOn" ) )
|
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
GbTraceOn = true;
|
2012-11-06 23:34:23 -06:00
|
|
|
}
|
|
|
|
else if( aCommand.equalsIngoreAsciiCase( "TraceOff" ) )
|
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
GbTraceOn = false;
|
2012-11-06 23:34:23 -06:00
|
|
|
}
|
|
|
|
else if( aCommand.equalsIngoreAsciiCase( "PCodeOn" ) )
|
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
GbIncludePCodes = true;
|
2012-11-06 23:34:23 -06:00
|
|
|
}
|
|
|
|
else if( aCommand.equalsIngoreAsciiCase( "PCodeOff" ) )
|
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
GbIncludePCodes = false;
|
2012-11-06 23:34:23 -06:00
|
|
|
}
|
|
|
|
else if( aCommand.equalsIngoreAsciiCase( "Print" ) )
|
2010-08-23 11:16:00 +02:00
|
|
|
{
|
|
|
|
if ( rPar.Count() < 3 )
|
|
|
|
{
|
|
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SbxError eOld = SbxBase::GetError();
|
|
|
|
if( eOld != SbxERR_OK )
|
|
|
|
SbxBase::ResetError();
|
|
|
|
|
2012-11-06 23:34:23 -06:00
|
|
|
OUString aValStr = rPar.Get(2)->GetString();
|
2010-08-23 11:16:00 +02:00
|
|
|
SbxError eErr = SbxBase::GetError();
|
|
|
|
if( eErr != SbxERR_OK )
|
|
|
|
{
|
2012-11-06 23:34:23 -06:00
|
|
|
aValStr = "<ERROR converting value to String>";
|
2010-08-23 11:16:00 +02:00
|
|
|
SbxBase::ResetError();
|
|
|
|
}
|
|
|
|
|
|
|
|
char Buffer[500];
|
|
|
|
|
2014-09-20 12:14:41 +08:00
|
|
|
sprintf( Buffer, "### TRACE_PRINT: %s ###", OUStringToOString( OUString( aValStr ), RTL_TEXTENCODING_ASCII_US ).getStr() );
|
2010-08-23 11:16:00 +02:00
|
|
|
int nIndent = GnLastCallLvl * GnIndentPerCallLevel;
|
2011-03-25 10:40:25 +01:00
|
|
|
lcl_lineOut( Buffer, lcl_getSpaces( nIndent ) );
|
2010-08-23 11:16:00 +02:00
|
|
|
|
|
|
|
if( eOld != SbxERR_OK )
|
2012-11-03 09:07:25 -05:00
|
|
|
{
|
2010-08-23 11:16:00 +02:00
|
|
|
SbxBase::SetError( eOld );
|
2012-11-03 09:07:25 -05:00
|
|
|
}
|
2010-08-23 11:16:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-26 14:20:03 +02:00
|
|
|
#endif
|
|
|
|
|
2011-08-27 21:37:14 +02:00
|
|
|
// This routine is defined here, so that the
|
|
|
|
// compiler can be loaded as a discrete segment.
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2014-03-26 11:18:51 +02:00
|
|
|
bool SbModule::Compile()
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( pImage )
|
2014-03-26 11:18:51 +02:00
|
|
|
return true;
|
2000-09-18 15:18:56 +00:00
|
|
|
StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent());
|
|
|
|
if( !pBasic )
|
2014-03-26 11:18:51 +02:00
|
|
|
return false;
|
2000-09-18 15:18:56 +00:00
|
|
|
SbxBase::ResetError();
|
2011-08-27 21:37:14 +02:00
|
|
|
|
2012-01-15 16:15:08 +01:00
|
|
|
SbModule* pOld = GetSbData()->pCompMod;
|
|
|
|
GetSbData()->pCompMod = this;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2014-10-01 16:01:34 +02:00
|
|
|
boost::scoped_ptr<SbiParser> pParser(new SbiParser( static_cast<StarBASIC*>(GetParent()), this ));
|
2000-09-18 15:18:56 +00:00
|
|
|
while( pParser->Parse() ) {}
|
|
|
|
if( !pParser->GetErrors() )
|
|
|
|
pParser->aGen.Save();
|
2014-05-29 09:27:30 +09:00
|
|
|
pParser.reset();
|
2011-08-27 21:37:14 +02:00
|
|
|
// for the disassembler
|
2000-09-18 15:18:56 +00:00
|
|
|
if( pImage )
|
2003-04-23 15:56:59 +00:00
|
|
|
pImage->aOUSource = aOUSource;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2012-01-15 16:15:08 +01:00
|
|
|
GetSbData()->pCompMod = pOld;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2011-08-27 21:37:14 +02:00
|
|
|
// compiling a module, the module-global
|
|
|
|
// variables of all modules become invalid
|
2014-03-26 11:18:51 +02:00
|
|
|
bool bRet = IsCompiled();
|
2000-09-18 15:18:56 +00:00
|
|
|
if( bRet )
|
|
|
|
{
|
2010-09-15 08:45:40 +02:00
|
|
|
if( !this->ISA(SbObjModule) )
|
|
|
|
pBasic->ClearAllModuleVars();
|
2010-07-05 13:58:36 +02:00
|
|
|
RemoveVars(); // remove 'this' Modules variables
|
2008-07-02 08:58:48 +00:00
|
|
|
// clear all method statics
|
2011-01-10 14:40:57 +01:00
|
|
|
for( sal_uInt16 i = 0; i < pMethods->Count(); i++ )
|
2008-07-02 08:58:48 +00:00
|
|
|
{
|
|
|
|
SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) );
|
|
|
|
if( p )
|
|
|
|
p->ClearStatics();
|
|
|
|
}
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2005-01-13 17:47:36 +00:00
|
|
|
// #i31510 Init other libs only if Basic isn't running
|
2012-01-15 16:15:08 +01:00
|
|
|
if( GetSbData()->pInst == NULL )
|
2005-01-13 17:47:36 +00:00
|
|
|
{
|
2006-06-19 16:42:54 +00:00
|
|
|
SbxObject* pParent_ = pBasic->GetParent();
|
|
|
|
if( pParent_ )
|
|
|
|
pBasic = PTR_CAST(StarBASIC,pParent_);
|
2005-01-13 17:47:36 +00:00
|
|
|
if( pBasic )
|
|
|
|
pBasic->ClearAllModuleVars();
|
|
|
|
}
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
2003-03-18 15:28:40 +00:00
|
|
|
|
2000-09-18 15:18:56 +00:00
|
|
|
return bRet;
|
|
|
|
}
|
2010-10-12 15:53:47 +02:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|