summaryrefslogtreecommitdiff
path: root/sc/source/core/tool/interpr4.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/tool/interpr4.cxx')
-rwxr-xr-xsc/source/core/tool/interpr4.cxx48
1 files changed, 43 insertions, 5 deletions
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index e3cd6239191e..439e0375a8b9 100755
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -3181,6 +3181,14 @@ void ScInterpreter::ScColRowNameAuto()
void ScInterpreter::ScExternalRef()
{
+ const FormulaToken* pNextOp = aCode.PeekNextOperator();
+ if (pNextOp && pNextOp->GetOpCode() == ocOffset)
+ {
+ // Handled by OFFSET function.
+ PushTempToken( *pCur);
+ return;
+ }
+
ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
const String* pFile = pRefMgr->getExternalFileName(pCur->GetIndex());
if (!pFile)
@@ -3324,6 +3332,21 @@ void ScInterpreter::GlobalExit() // static
}
+// A ::std::vector<FormulaTokenRef> is not possible, a push_back() attempts to
+// use a FormulaToken(const FormulaTokenRef&) ctor. Reinvent wheel..
+struct FormulaTokenRefPtr
+{
+ FormulaToken* mp;
+ FormulaTokenRefPtr() : mp(0) {}
+ FormulaTokenRefPtr( FormulaToken* p ) : mp(p) { if (mp) mp->IncRef(); }
+ FormulaTokenRefPtr( const FormulaTokenRefPtr & r ) : mp(r.mp) { if (mp) mp->IncRef(); }
+ ~FormulaTokenRefPtr() { if (mp) mp->DecRef(); }
+ FormulaTokenRefPtr& operator=( const FormulaTokenRefPtr & r )
+ { if (r.mp) r.mp->IncRef(); if (mp) mp->DecRef(); mp = r.mp; return *this; }
+};
+typedef ::std::vector< FormulaTokenRefPtr > FormulaTokenDtor;
+
+
StackVar ScInterpreter::Interpret()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Interpret" );
@@ -3342,6 +3365,7 @@ StackVar ScInterpreter::Interpret()
pJumpMatrix = NULL;
glSubTotal = sal_False;
ScTokenMatrixMap::const_iterator aTokenMatrixMapIter;
+ ::boost::scoped_ptr< FormulaTokenDtor > pTokenDtor;
// Once upon a time we used to have FP exceptions on, and there was a
// Windows printer driver that kept switching off exceptions, so we had to
@@ -3724,13 +3748,27 @@ StackVar ScInterpreter::Interpret()
default : PushError( errUnknownOpCode); break;
}
- // If the function signalled that it pushed a subroutine on the
- // instruction code stack instead of a result, continue with
+ // If the function pushed a subroutine as result, continue with
// execution of the subroutine.
- if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall)
+ if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall && pStack[sp-1]->GetType() == svSubroutine)
{
- Pop();
- continue; // while( ( pCur = aCode.Next() ) != NULL ...
+ FormulaTokenRef xTok = PopToken();
+ const FormulaSubroutineToken* pSub = dynamic_cast<FormulaSubroutineToken*>(xTok.get());
+ if (pSub)
+ {
+ // Remember token for late destruction.
+ if (!pTokenDtor)
+ pTokenDtor.reset( new FormulaTokenDtor);
+ pTokenDtor->push_back( FormulaTokenDtor::value_type( xTok));
+ // Continue with execution of subroutine.
+ aCode.Push( pSub->GetTokenArray());
+ continue; // while( ( pCur = aCode.Next() ) != NULL ...
+ }
+ else
+ {
+ DBG_ERRORFILE( "ScInterpreter::Interpret: ocCall svSubroutine, but no FormulaSubroutineToken?!?");
+ PushError( errNoCode);
+ }
}
// Remember result matrix in case it could be reused.