summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--formula/source/core/api/FormulaCompiler.cxx13
-rw-r--r--formula/source/core/api/token.cxx343
-rw-r--r--include/formula/tokenarray.hxx47
3 files changed, 299 insertions, 104 deletions
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 5b2e8ea35e26..5cb40fc6bb21 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1742,9 +1742,16 @@ void FormulaCompiler::CreateStringFromTokenArray( OUStringBuffer& rBuffer )
if (bODFF || FormulaGrammar::isPODF( meGrammar) )
{
// Scan token array for missing args and re-write if present.
- MissingConvention aConv( bODFF);
- if (pArr->NeedsPofRewrite( aConv))
- pArr = pArr->RewriteMissingToPof( aConv);
+ MissingConventionODF aConv( bODFF);
+ if (pArr->NeedsPodfRewrite( aConv))
+ pArr = pArr->RewriteMissing( aConv );
+ }
+ else if ( FormulaGrammar::isOOXML( meGrammar ) )
+ {
+ // Scan token array for missing args and rewrite if present.
+ MissingConventionOOXML aConv;
+ if (pArr->NeedsOoxmlRewrite( aConv))
+ pArr = pArr->RewriteMissing( aConv );
}
// At least one character per token, plus some are references, some are
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 92486dca19d4..a414a4b12cb9 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -995,11 +995,9 @@ bool FormulaTokenArray::HasMatrixDoubleRefOps()
return false;
}
+// --- Formula rewrite of a token array
-
-// --- POF (plain old formula) rewrite of a token array ---------------------
-
-inline bool MissingConvention::isRewriteNeeded( OpCode eOp ) const
+inline bool MissingConventionODF::isRewriteNeeded( OpCode eOp ) const
{
switch (eOp)
{
@@ -1011,7 +1009,62 @@ inline bool MissingConvention::isRewriteNeeded( OpCode eOp ) const
return true;
case ocMissing:
case ocLog:
- return !isODFF(); // rewrite only for PODF
+ return isPODF(); // rewrite only for PODF
+ default:
+ return false;
+ }
+}
+
+/*
+ * fdo 81596
+Test status ( . : in progress , v : tested , - not applicable )
+finished:
+- ocCosecant: // for OOXML not rewritten anymore
+- ocSecant: // for OOXML not rewritten anymore
+- ocCot: // for OOXML not rewritten anymore
+- ocCosecantHyp: // for OOXML not rewritten anymore
+- ocSecantHyp: // for OOXML not rewritten anymore
+- ocCotHyp: // for OOXML not rewritten anymore
+- ocArcCot: // for OOXML not rewritten anymore
+- ocArcCotHyp: // ACOTH(x), not needed for Excel2013 and later
+- ocChose: // CHOOSE() - no rewrite needed, it seems
+v ocEuroConvert:
+v ocIf:
+v ocRound:
+v ocRoundUp:
+v ocRoundDown:
+v ocGammaDist:
+v ocPoissonDist:
+v ocNormDist:
+v ocLogNormDist:
+
+To be implemented yet:
+ ocExternal: ?
+ ocMacro: ?
+ ocIndex: INDEX() ?
+ ocFDist: // later, fdo40835
+*/
+inline bool MissingConventionOOXML::isRewriteNeeded( OpCode eOp ) const
+{
+ switch (eOp)
+ {
+ case ocIf:
+
+ case ocExternal:
+ case ocEuroConvert:
+ case ocMacro:
+
+ case ocRound:
+ case ocRoundUp:
+ case ocRoundDown:
+
+ case ocIndex:
+
+ case ocGammaDist:
+ case ocPoissonDist:
+ case ocNormDist:
+ case ocLogNormDist:
+ return true;
default:
return false;
}
@@ -1035,51 +1088,129 @@ void FormulaMissingContext::AddMoreArgs( FormulaTokenArray *pNewArr, const Missi
if ( !mpFunc )
return;
- switch (mpFunc->GetOpCode())
+ switch (rConv.getConvention())
{
- case ocGammaDist:
- if (mnCurArg == 2)
- {
- pNewArr->AddOpCode( ocSep );
- pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
- }
- break;
- case ocPoissonDist:
- if (mnCurArg == 1)
- {
- pNewArr->AddOpCode( ocSep );
- pNewArr->AddDouble( 1.0 ); // 3rd, Cumulative=true()
- }
- break;
- case ocNormDist:
- if ( mnCurArg == 2 )
- {
- pNewArr->AddOpCode( ocSep );
- pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
- }
- break;
- case ocLogNormDist:
- if ( mnCurArg == 0 )
- {
- pNewArr->AddOpCode( ocSep );
- pNewArr->AddDouble( 0.0 ); // 2nd, mean = 0.0
- }
- if ( mnCurArg <= 1 )
+ case MissingConvention::FORMULA_MISSING_CONVENTION_ODFF:
+ case MissingConvention::FORMULA_MISSING_CONVENTION_PODF:
{
- pNewArr->AddOpCode( ocSep );
- pNewArr->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
+ switch (mpFunc->GetOpCode())
+ {
+ case ocGammaDist:
+ if (mnCurArg == 2)
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
+ }
+ break;
+ case ocPoissonDist:
+ if (mnCurArg == 1)
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 1.0 ); // 3rd, Cumulative=true()
+ }
+ break;
+ case ocNormDist:
+ if ( mnCurArg == 2 )
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
+ }
+ break;
+ case ocLogNormDist:
+ if ( mnCurArg == 0 )
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 0.0 ); // 2nd, mean = 0.0
+ }
+ if ( mnCurArg <= 1 )
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
+ }
+ break;
+ case ocLog:
+ if ( rConv.isPODF() && mnCurArg == 0 )
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 10.0 ); // 2nd, basis 10
+ }
+ break;
+ default:
+ break;
+ }
}
break;
- case ocLog:
- if ( !rConv.isODFF() && mnCurArg == 0 )
+ case MissingConvention::FORMULA_MISSING_CONVENTION_OOXML:
{
- pNewArr->AddOpCode( ocSep );
- pNewArr->AddDouble( 10.0 ); // 2nd, basis 10
+ switch (mpFunc->GetOpCode())
+ {
+ case ocIf:
+ if( mnCurArg == 0 )
+ {
+ // Excel needs at least two parameters in IF function
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddOpCode( ocTrue ); // 2nd, true() as function
+ pNewArr->AddOpCode( ocOpen ); // so the result is of logical type
+ pNewArr->AddOpCode( ocClose ); // and survives roundtrip
+ }
+ break;
+
+ case ocEuroConvert:
+ if ( mnCurArg == 2 )
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 0.0 ); // 4th, FullPrecision = false()
+ }
+ break;
+
+ case ocPoissonDist:
+ if (mnCurArg == 1)
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 1.0 ); // 3rd, Cumulative=true()
+ }
+ break;
+
+ case ocGammaDist:
+ case ocNormDist:
+ if (mnCurArg == 2)
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
+ }
+ break;
+
+ case ocLogNormDist:
+ if ( mnCurArg == 0 )
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 0.0 ); // 2nd, mean = 0.0
+ }
+ if ( mnCurArg <= 1 )
+ {
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
+ }
+ break;
+
+ case ocRound:
+ case ocRoundUp:
+ case ocRoundDown:
+ if( mnCurArg == 0 )
+ {
+ // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
+ pNewArr->AddOpCode( ocSep );
+ pNewArr->AddDouble( 0.0 ); // 2nd, 0.0
+ }
+ break;
+
+ default:
+ break;
+ }
}
break;
- default:
- break;
}
+
}
inline bool FormulaMissingContext::AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const
@@ -1124,61 +1255,87 @@ bool FormulaMissingContext::AddMissing( FormulaTokenArray *pNewArr, const Missin
bool bRet = false;
const OpCode eOp = mpFunc->GetOpCode();
- // Add for both, PODF and ODFF
- switch (eOp)
+ switch (rConv.getConvention())
{
- case ocAddress:
- return AddDefaultArg( pNewArr, 2, 1.0 ); // abs
- default:
+ case MissingConvention::FORMULA_MISSING_CONVENTION_ODFF:
+ {
+ // Add for ODFF
+ switch (eOp)
+ {
+ case ocAddress:
+ return AddDefaultArg( pNewArr, 2, 1.0 ); // abs
+ default:
+ break;
+ }
+ }
+ break;
+ case MissingConvention::FORMULA_MISSING_CONVENTION_PODF:
+ {
+ // Add for PODF
+ switch (eOp)
+ {
+ case ocAddress:
+ return AddDefaultArg( pNewArr, 2, 1.0 ); // abs
+ case ocFixed:
+ return AddDefaultArg( pNewArr, 1, 2.0 );
+ case ocBetaDist:
+ case ocBetaInv:
+ case ocRMZ: // PMT
+ return AddDefaultArg( pNewArr, 3, 0.0 );
+ case ocZinsZ: // IPMT
+ case ocKapz: // PPMT
+ return AddDefaultArg( pNewArr, 4, 0.0 );
+ case ocBW: // PV
+ case ocZW: // FV
+ bRet |= AddDefaultArg( pNewArr, 2, 0.0 ); // pmt
+ bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // [fp]v
+ break;
+ case ocZins: // RATE
+ bRet |= AddDefaultArg( pNewArr, 1, 0.0 ); // pmt
+ bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // fv
+ bRet |= AddDefaultArg( pNewArr, 4, 0.0 ); // type
+ break;
+ case ocExternal:
+ return AddMissingExternal( pNewArr );
+
+ // --- more complex cases ---
+
+ case ocOffset:
+ // FIXME: rather tough.
+ // if arg 3 (height) omitted, export arg1 (rows)
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case MissingConvention::FORMULA_MISSING_CONVENTION_OOXML:
+ {
+ switch (eOp)
+ {
+ case ocExternal:
+ return AddMissingExternal( pNewArr );
+ default:
+ break;
+ }
+ }
break;
}
- if (rConv.isODFF())
- {
- // Add for ODFF
- }
- else
- {
- // Add for PODF
- switch (eOp)
- {
- case ocFixed:
- return AddDefaultArg( pNewArr, 1, 2.0 );
- case ocBetaDist:
- case ocBetaInv:
- case ocRMZ: // PMT
- return AddDefaultArg( pNewArr, 3, 0.0 );
- case ocZinsZ: // IPMT
- case ocKapz: // PPMT
- return AddDefaultArg( pNewArr, 4, 0.0 );
- case ocBW: // PV
- case ocZW: // FV
- bRet |= AddDefaultArg( pNewArr, 2, 0.0 ); // pmt
- bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // [fp]v
- break;
- case ocZins: // RATE
- bRet |= AddDefaultArg( pNewArr, 1, 0.0 ); // pmt
- bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // fv
- bRet |= AddDefaultArg( pNewArr, 4, 0.0 ); // type
- break;
- case ocExternal:
- return AddMissingExternal( pNewArr );
-
- // --- more complex cases ---
+ return bRet;
+}
- case ocOffset:
- // FIXME: rather tough.
- // if arg 3 (height) omitted, export arg1 (rows)
- break;
- default:
- break;
- }
+bool FormulaTokenArray::NeedsPodfRewrite( const MissingConventionODF & rConv )
+{
+ for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
+ {
+ if ( rConv.isRewriteNeeded( pCur->GetOpCode()))
+ return true;
}
-
- return bRet;
+ return false;
}
-bool FormulaTokenArray::NeedsPofRewrite( const MissingConvention & rConv )
+bool FormulaTokenArray::NeedsOoxmlRewrite( const MissingConventionOOXML & rConv )
{
for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
{
@@ -1189,7 +1346,7 @@ bool FormulaTokenArray::NeedsPofRewrite( const MissingConvention & rConv )
}
-FormulaTokenArray * FormulaTokenArray::RewriteMissingToPof( const MissingConvention & rConv )
+FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention & rConv )
{
const size_t nAlloc = 256;
FormulaMissingContext aCtx[ nAlloc ];
@@ -1232,12 +1389,12 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissingToPof( const MissingConvent
++nFn; // all following operations on _that_ function
pCtx[ nFn ].mpFunc = PeekPrevNoSpaces();
pCtx[ nFn ].mnCurArg = 0;
- if (pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress && !rConv.isODFF())
+ if (rConv.isPODF() && pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress)
pOcas[ nOcas++ ] = nFn; // entering ADDRESS() if PODF
break;
case ocClose:
pCtx[ nFn ].AddMoreArgs( pNewArr, rConv );
- DBG_ASSERT( nFn > 0, "FormulaTokenArray::RewriteMissingToPof: underflow");
+ DBG_ASSERT( nFn > 0, "FormulaTokenArray::RewriteMissing: underflow");
if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn)
--nOcas; // leaving ADDRESS()
if (nFn > 0)
@@ -1252,7 +1409,7 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissingToPof( const MissingConvent
}
break;
case ocMissing:
- if (bAdd)
+ if ( bAdd )
bAdd = !pCtx[ nFn ].AddMissing( pNewArr, rConv );
break;
default:
diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx
index c6433aa43b07..ceb84253f246 100644
--- a/include/formula/tokenarray.hxx
+++ b/include/formula/tokenarray.hxx
@@ -55,12 +55,39 @@ class FormulaMissingContext;
class FORMULA_DLLPUBLIC MissingConvention
{
- bool mbODFF; /// TRUE: ODFF, FALSE: PODF
public:
- explicit MissingConvention( bool bODFF ) : mbODFF(bODFF) {}
+ enum Convention
+ {
+ FORMULA_MISSING_CONVENTION_PODF,
+ FORMULA_MISSING_CONVENTION_ODFF,
+ FORMULA_MISSING_CONVENTION_OOXML
+ };
+ explicit MissingConvention( Convention eConvention ) : meConvention(eConvention) {}
+ inline bool isPODF() const { return meConvention == FORMULA_MISSING_CONVENTION_PODF; }
+ inline Convention getConvention() const { return meConvention; }
+private:
+ Convention meConvention;
+};
+
+class FORMULA_DLLPUBLIC MissingConventionODF : public MissingConvention
+{
+public:
+ explicit MissingConventionODF( bool bODFF ) :
+ MissingConvention( bODFF ?
+ MissingConvention::FORMULA_MISSING_CONVENTION_ODFF :
+ MissingConvention::FORMULA_MISSING_CONVENTION_PODF)
+ {
+ }
+ // Implementation and usage only in token.cxx
+ inline bool isRewriteNeeded( OpCode eOp ) const;
+};
+
+class FORMULA_DLLPUBLIC MissingConventionOOXML : public MissingConvention
+{
+public:
+ explicit MissingConventionOOXML() : MissingConvention( MissingConvention::FORMULA_MISSING_CONVENTION_OOXML) {}
// Implementation and usage only in token.cxx
inline bool isRewriteNeeded( OpCode eOp ) const;
- inline bool isODFF() const { return mbODFF; }
};
class FORMULA_DLLPUBLIC FormulaTokenArray
@@ -238,15 +265,19 @@ public:
FormulaTokenArray& operator=( const FormulaTokenArray& );
/** Determines if this formula needs any changes to convert it to something
- previous versions of OOo could consume (Plain Old Formula). */
- bool NeedsPofRewrite(const MissingConvention & rConv);
+ previous versions of OOo could consume (Plain Old Formula, pre-ODFF, or
+ also ODFF) */
+ bool NeedsPodfRewrite( const MissingConventionODF & rConv );
+
+ /** Determines if this formula needs any changes to convert it to OOXML. */
+ bool NeedsOoxmlRewrite( const MissingConventionOOXML & rConv );
- /** Rewrites to Plain Old Formula, substituting missing parameters. The
+ /** Rewrites to Plain Old Formula or OOXML, substituting missing parameters. The
FormulaTokenArray* returned is new'ed. */
- FormulaTokenArray* RewriteMissingToPof(const MissingConvention & rConv);
+ FormulaTokenArray* RewriteMissing( const MissingConvention & rConv );
/** Determines if this formula may be followed by a reference. */
- bool MayReferenceFollow();
+ bool MayReferenceFollow();
};
inline OpCode FormulaTokenArray::GetOuterFuncOpCode()