summaryrefslogtreecommitdiff
path: root/formula
diff options
context:
space:
mode:
authorEike Rathke [er] <eike.rathke@oracle.com>2011-03-04 14:43:09 +0100
committerEike Rathke [er] <eike.rathke@oracle.com>2011-03-04 14:43:09 +0100
commit4f24ef15969c9c062f6ed60d0f2848608cee079e (patch)
tree9ffb4295d911a6aaffd6292744c78931255458af /formula
parentcd0d6a5a6775f197fdb7e78b54c8133074a7a236 (diff)
calc66: #i103331# make OFFSET with external references work again
+ Introduced FormulaSubroutineToken to hold a FormulaTokenArray. * INDIRECT in case of external reference returns FormulaSubroutineToken instead of directly pushing the token array to code and signalling its presence to ScInterpreter::Interpret(). * ScInterpreter::ScExternalRef() checks if an external reference is used with OFFSET and if so does not resolve it but pushes it so it can be handled within OFFSET. + OFFSET recognizes external reference and creates an external reference of the new area and returns that as subroutine to be resolved by ScExternalRef(). * Interpret() pushes the subroutine to code and rememberes the token and array for late destruction.
Diffstat (limited to 'formula')
-rw-r--r--formula/inc/formula/token.hxx19
-rw-r--r--formula/inc/formula/tokenarray.hxx4
-rw-r--r--formula/source/core/api/token.cxx67
3 files changed, 75 insertions, 15 deletions
diff --git a/formula/inc/formula/token.hxx b/formula/inc/formula/token.hxx
index 30618c67381a..8a94b1005bc8 100644
--- a/formula/inc/formula/token.hxx
+++ b/formula/inc/formula/token.hxx
@@ -70,6 +70,7 @@ enum StackVarEnum
svExternalSingleRef,
svExternalDoubleRef,
svExternalName,
+ svSubroutine, // A token with a subroutine token array.
svError, // error token
svMissing = 0x70, // 0 or ""
svSep, // separator, ocSep, ocOpen, ocClose
@@ -89,6 +90,7 @@ class FormulaToken;
typedef SimpleIntrusiveReference< class FormulaToken > FormulaTokenRef;
typedef SimpleIntrusiveReference< const class FormulaToken > FormulaConstTokenRef;
+class FormulaTokenArray;
class FORMULA_DLLPUBLIC FormulaToken : public IFormulaToken
{
@@ -364,6 +366,23 @@ public:
};
+class FORMULA_DLLPUBLIC FormulaSubroutineToken : public FormulaToken
+{
+public:
+ /** Takes ownership of pArray and deletes it upon destruction! */
+ FormulaSubroutineToken( const FormulaTokenArray* pArray ) :
+ FormulaToken( svSubroutine, ocCall ), mpArray( pArray) {}
+ FormulaSubroutineToken( const FormulaSubroutineToken& r );
+ virtual ~FormulaSubroutineToken();
+ virtual FormulaToken* Clone() const { return new FormulaSubroutineToken(*this); }
+ virtual sal_Bool operator==( const FormulaToken& rToken ) const;
+ const FormulaTokenArray* GetTokenArray() const;
+
+private:
+ const FormulaTokenArray* mpArray;
+};
+
+
class FORMULA_DLLPUBLIC FormulaUnknownToken : public FormulaToken
{
public:
diff --git a/formula/inc/formula/tokenarray.hxx b/formula/inc/formula/tokenarray.hxx
index 31d780c81a79..bcd4061f5ac6 100644
--- a/formula/inc/formula/tokenarray.hxx
+++ b/formula/inc/formula/tokenarray.hxx
@@ -256,6 +256,7 @@ public:
void Reset();
const FormulaToken* First();
const FormulaToken* Next();
+ const FormulaToken* PeekNextOperator();
bool IsEndOfPath() const; /// if a jump or subroutine path is done
bool HasStacked() const { return pCur->pNext != 0; }
short GetPC() const { return pCur->nPC; }
@@ -276,6 +277,9 @@ public:
void Jump( short nStart, short nNext, short nStop = SHRT_MAX );
void Push( const FormulaTokenArray* );
void Pop();
+
+private:
+ const FormulaToken* GetNonEndOfPathToken( short nIdx ) const;
};
// =============================================================================
} // formula
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 3942712da6a4..b644d1cd8fb3 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -1265,15 +1265,7 @@ const FormulaToken* FormulaTokenIterator::First()
const FormulaToken* FormulaTokenIterator::Next()
{
- const FormulaToken* t = NULL;
- ++pCur->nPC;
- if( pCur->nPC < pCur->pArr->nRPN && pCur->nPC < pCur->nStop )
- {
- t = pCur->pArr->pRPN[ pCur->nPC ];
- // such an OpCode ends an IF() or CHOOSE() path
- if( t->GetOpCode() == ocSep || t->GetOpCode() == ocClose )
- t = NULL;
- }
+ const FormulaToken* t = GetNonEndOfPathToken( ++pCur->nPC );
if( !t && pCur->pNext )
{
Pop();
@@ -1282,6 +1274,25 @@ const FormulaToken* FormulaTokenIterator::Next()
return t;
}
+const FormulaToken* FormulaTokenIterator::PeekNextOperator()
+{
+ const FormulaToken* t = NULL;
+ short nIdx = pCur->nPC;
+ while (!t && ((t = GetNonEndOfPathToken( ++nIdx)) != NULL))
+ {
+ if (t->GetOpCode() == ocPush)
+ t = NULL; // ignore operands
+ }
+ if (!t && pCur->pNext)
+ {
+ ImpTokenIterator* pHere = pCur;
+ pCur = pCur->pNext;
+ t = PeekNextOperator();
+ pCur = pHere;
+ }
+ return t;
+}
+
//! The nPC counts after a Push() are -1
void FormulaTokenIterator::Jump( short nStart, short nNext, short nStop )
@@ -1295,17 +1306,22 @@ void FormulaTokenIterator::Jump( short nStart, short nNext, short nStop )
}
}
-bool FormulaTokenIterator::IsEndOfPath() const
+const FormulaToken* FormulaTokenIterator::GetNonEndOfPathToken( short nIdx ) const
{
- sal_uInt16 nTest = pCur->nPC + 1;
- if( nTest < pCur->pArr->nRPN && nTest < pCur->nStop )
+ if (nIdx < pCur->pArr->nRPN && nIdx < pCur->nStop)
{
- const FormulaToken* t = pCur->pArr->pRPN[ nTest ];
+ const FormulaToken* t = pCur->pArr->pRPN[ nIdx ];
// such an OpCode ends an IF() or CHOOSE() path
- return t->GetOpCode() == ocSep || t->GetOpCode() == ocClose;
+ return (t->GetOpCode() == ocSep || t->GetOpCode() == ocClose) ? NULL : t;
}
- return true;
+ return NULL;
}
+
+bool FormulaTokenIterator::IsEndOfPath() const
+{
+ return GetNonEndOfPathToken( pCur->nPC + 1) != NULL;
+}
+
// -----------------------------------------------------------------------------
// ==========================================================================
// real implementations of virtual functions
@@ -1367,6 +1383,27 @@ sal_Bool FormulaMissingToken::operator==( const FormulaToken& r ) const
}
+FormulaSubroutineToken::FormulaSubroutineToken( const FormulaSubroutineToken& r ) :
+ FormulaToken( r ),
+ mpArray( r.mpArray->Clone())
+{
+}
+FormulaSubroutineToken::~FormulaSubroutineToken()
+{
+ delete mpArray;
+}
+const FormulaTokenArray* FormulaSubroutineToken::GetTokenArray() const
+{
+ return mpArray;
+}
+sal_Bool FormulaSubroutineToken::operator==( const FormulaToken& r ) const
+{
+ // Arrays don't equal..
+ return FormulaToken::operator==( r ) &&
+ (mpArray == static_cast<const FormulaSubroutineToken&>(r).mpArray);
+}
+
+
sal_Bool FormulaUnknownToken::operator==( const FormulaToken& r ) const
{
return FormulaToken::operator==( r );