From f270d113e354aa608a2efa641691167a504c6539 Mon Sep 17 00:00:00 2001
Message-Id: <f270d113e354aa608a2efa641691167a504c6539.1328721514.git.erack@redhat.com>
From: Eike Rathke <erack@erack.de>
Date: Wed, 8 Feb 2012 10:28:46 -0500
Subject: [PATCH] fdo#40378 compile defined names that had unresolveds during
load
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------erAck-patch-parts"
This is a multi-part message in MIME format.
--------------erAck-patch-parts
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
Dependencies of defined names must not depend on the order in which they
are inserted during file load. In a second step compile defined names
that had unresolved names during load, and only those.
Signed-off-by: Kohei Yoshida <kohei.yoshida@suse.com>
---
sc/inc/compiler.hxx | 11 +++-
sc/inc/rangenam.hxx | 25 +++++--
sc/source/core/data/document.cxx | 3 +
sc/source/core/data/table2.cxx | 3 +
sc/source/core/tool/compiler.cxx | 11 ++--
sc/source/core/tool/rangenam.cxx | 131 ++++++++++++++++++++++++++------------
sc/source/ui/view/viewfunc.cxx | 2 +-
7 files changed, 129 insertions(+), 57 deletions(-)
--------------erAck-patch-parts
Content-Type: text/x-patch; name="0001-fdo-40378-compile-defined-names-that-had-unresolveds.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0001-fdo-40378-compile-defined-names-that-had-unresolveds.patch"
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 5fcc6dc..6947460 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -227,6 +227,13 @@ public:
ENCODE_NEVER,
};
+ enum ExtendedErrorDetection
+ {
+ EXTENDED_ERROR_DETECTION_NONE = 0, // no error on unknown symbols, default (interpreter handles it)
+ EXTENDED_ERROR_DETECTION_NAME_BREAK, // name error on unknown symbols and break, pCode incomplete
+ EXTENDED_ERROR_DETECTION_NAME_NO_BREAK // name error on unknown symbols, don't break, continue
+ };
+
struct Convention
{
const formula::FormulaGrammar::AddressConvention meConv;
@@ -327,8 +334,8 @@ private:
sal_Int32 mnRangeOpPosInSymbol; // if and where a range operator is in symbol
const Convention *pConv;
EncodeUrlMode meEncodeUrlMode;
+ ExtendedErrorDetection meExtendedErrorDetection;
bool mbCloseBrackets; // whether to close open brackets automatically, default TRUE
- bool mbExtendedErrorDetection;
bool mbRewind; // whether symbol is to be rewound to some step during lexical analysis
sal_Bool NextNewToken(bool bInArray = false);
@@ -413,7 +420,7 @@ public:
void CreateStringFromXMLTokenArray( String& rFormula, String& rFormulaNmsp );
- void SetExtendedErrorDetection( bool bVal ) { mbExtendedErrorDetection = bVal; }
+ void SetExtendedErrorDetection( ExtendedErrorDetection eVal ) { meExtendedErrorDetection = eVal; }
sal_Bool IsCorrected() { return bCorrected; }
const String& GetCorrectedFormula() { return aCorrectedFormula; }
diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx
index 7417094..56c0544 100644
--- a/sc/inc/rangenam.hxx
+++ b/sc/inc/rangenam.hxx
@@ -75,18 +75,22 @@ private:
String aName;
String aUpperName; // #i62977# for faster searching (aName is never modified after ctor)
ScTokenArray* pCode;
- ScAddress aPos;
- RangeType eType;
- ScDocument* pDoc;
- sal_uInt16 nIndex;
- sal_Bool bModified; // is set/cleared by UpdateReference
-
- // max row and column to use for wrapping of references. If -1 use the
+ ScAddress aPos;
+ RangeType eType;
+ ScDocument* pDoc;
+ formula::FormulaGrammar::Grammar eTempGrammar; // needed for unresolved XML compiles
+ sal_uInt16 nIndex;
+ sal_Bool bModified; // is set/cleared by UpdateReference
+
+ // max row and column to use for wrapping of references. If -1 use the
// application's default.
SCROW mnMaxRow;
SCCOL mnMaxCol;
ScRangeData( sal_uInt16 nIndex );
+
+ void CompileRangeData( const String& rSymbol, bool bSetError );
+
public:
typedef ::std::map<sal_uInt16, sal_uInt16> IndexMap;
@@ -161,6 +165,8 @@ public:
SCROW GetMaxRow() const;
SC_DLLPUBLIC void SetMaxCol(SCCOL nCol);
SCCOL GetMaxCol() const;
+
+ void CompileUnresolvedXML();
};
inline sal_Bool ScRangeData::HasType( RangeType nType ) const
@@ -211,6 +217,11 @@ public:
void UpdateTranspose(const ScRange& rSource, const ScAddress& rDest);
void UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY);
+ /** Compile those names that couldn't be resolved during loading and
+ inserting because they may have referred a name that was inserted later.
+ */
+ void CompileUnresolvedXML();
+
SC_DLLPUBLIC const_iterator begin() const;
SC_DLLPUBLIC const_iterator end() const;
SC_DLLPUBLIC iterator begin();
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index e85ba1f..6f3fec0 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -3154,6 +3154,9 @@ void ScDocument::CompileXML()
DBG_ASSERT( !pAutoNameCache, "AutoNameCache already set" );
pAutoNameCache = new ScAutoNameCache( this );
+ if (pRangeName)
+ pRangeName->CompileUnresolvedXML();
+
for (SCTAB i=0; i<=MAXTAB; i++)
if (pTab[i]) pTab[i]->CompileXML( aProgress );
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 7d7d554..b9c58ce 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1297,6 +1297,9 @@ void ScTable::CompileAll()
void ScTable::CompileXML( ScProgress& rProgress )
{
+ if (mpRangeName)
+ mpRangeName->CompileUnresolvedXML();
+
for (SCCOL i=0; i <= MAXCOL; i++)
{
aCol[i].CompileXML( rProgress );
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 9f39358..a4938f1 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -1741,8 +1741,8 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArra
mnRangeOpPosInSymbol(-1),
pConv( pConvOOO_A1 ),
meEncodeUrlMode( ENCODE_BY_GRAMMAR ),
+ meExtendedErrorDetection( EXTENDED_ERROR_DETECTION_NONE ),
mbCloseBrackets( true ),
- mbExtendedErrorDetection( false ),
mbRewind( false )
{
nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0;
@@ -1757,8 +1757,8 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos)
mnRangeOpPosInSymbol(-1),
pConv( pConvOOO_A1 ),
meEncodeUrlMode( ENCODE_BY_GRAMMAR ),
+ meExtendedErrorDetection( EXTENDED_ERROR_DETECTION_NONE ),
mbCloseBrackets( true ),
- mbExtendedErrorDetection( false ),
mbRewind( false )
{
nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0;
@@ -3623,11 +3623,12 @@ sal_Bool ScCompiler::NextNewToken( bool bInArray )
} while (mbRewind);
- if ( mbExtendedErrorDetection )
+ if ( meExtendedErrorDetection != EXTENDED_ERROR_DETECTION_NONE )
{
- // set an error and end compilation
+ // set an error
SetError( errNoName );
- return false;
+ if (meExtendedErrorDetection == EXTENDED_ERROR_DETECTION_NAME_BREAK)
+ return false; // end compilation
}
// Provide single token information and continue. Do not set an error, that
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
index b648d1a..2b9ca3b 100644
--- a/sc/source/core/tool/rangenam.cxx
+++ b/sc/source/core/tool/rangenam.cxx
@@ -72,36 +72,19 @@ ScRangeData::ScRangeData( ScDocument* pDok,
aName ( rName ),
aUpperName ( ScGlobal::pCharClass->upper( rName ) ),
pCode ( NULL ),
- aPos ( rAddress ),
- eType ( nType ),
- pDoc ( pDok ),
- nIndex ( 0 ),
- bModified ( false ),
+ aPos ( rAddress ),
+ eType ( nType ),
+ pDoc ( pDok ),
+ eTempGrammar( eGrammar ),
+ nIndex ( 0 ),
+ bModified ( false ),
mnMaxRow (-1),
mnMaxCol (-1)
{
if (rSymbol.Len() > 0)
- {
- ScCompiler aComp( pDoc, aPos );
- aComp.SetGrammar(eGrammar);
- pCode = aComp.CompileString( rSymbol );
- if( !pCode->GetCodeError() )
- {
- pCode->Reset();
- FormulaToken* p = pCode->GetNextReference();
- if( p )// genau eine Referenz als erstes
- {
- if( p->GetType() == svSingleRef )
- eType = eType | RT_ABSPOS;
- else
- eType = eType | RT_ABSAREA;
- }
- // ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
- // Dies ist fuer die manuelle Eingabe
- aComp.CompileTokenArray();
- pCode->DelRPN();
- }
- }
+ CompileRangeData( rSymbol, pDoc->IsImportingXML());
+ // Let the compiler set an error on unknown names for a subsequent
+ // CompileUnresolvedXML().
else
{
// #i63513#/#i65690# don't leave pCode as NULL.
@@ -120,11 +103,12 @@ ScRangeData::ScRangeData( ScDocument* pDok,
aName ( rName ),
aUpperName ( ScGlobal::pCharClass->upper( rName ) ),
pCode ( new ScTokenArray( rArr ) ),
- aPos ( rAddress ),
- eType ( nType ),
- pDoc ( pDok ),
- nIndex ( 0 ),
- bModified ( false ),
+ aPos ( rAddress ),
+ eType ( nType ),
+ pDoc ( pDok ),
+ eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ),
+ nIndex ( 0 ),
+ bModified ( false ),
mnMaxRow (-1),
mnMaxCol (-1)
{
@@ -148,11 +132,12 @@ ScRangeData::ScRangeData( ScDocument* pDok,
aName ( rName ),
aUpperName ( ScGlobal::pCharClass->upper( rName ) ),
pCode ( new ScTokenArray() ),
- aPos ( rTarget ),
- eType ( RT_NAME ),
- pDoc ( pDok ),
- nIndex ( 0 ),
- bModified ( false ),
+ aPos ( rTarget ),
+ eType ( RT_NAME ),
+ pDoc ( pDok ),
+ eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ),
+ nIndex ( 0 ),
+ bModified ( false ),
mnMaxRow (-1),
mnMaxCol (-1)
{
@@ -171,11 +156,12 @@ ScRangeData::ScRangeData(const ScRangeData& rScRangeData) :
aName (rScRangeData.aName),
aUpperName (rScRangeData.aUpperName),
pCode (rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()), // echte Kopie erzeugen (nicht copy-ctor)
- aPos (rScRangeData.aPos),
- eType (rScRangeData.eType),
- pDoc (rScRangeData.pDoc),
- nIndex (rScRangeData.nIndex),
- bModified (rScRangeData.bModified),
+ aPos (rScRangeData.aPos),
+ eType (rScRangeData.eType),
+ pDoc (rScRangeData.pDoc),
+ eTempGrammar(rScRangeData.eTempGrammar),
+ nIndex (rScRangeData.nIndex),
+ bModified (rScRangeData.bModified),
mnMaxRow (rScRangeData.mnMaxRow),
mnMaxCol (rScRangeData.mnMaxCol)
{}
@@ -185,9 +171,63 @@ ScRangeData::~ScRangeData()
delete pCode;
}
+void ScRangeData::CompileRangeData( const String& rSymbol, bool bSetError )
+{
+ if (eTempGrammar == FormulaGrammar::GRAM_UNSPECIFIED)
+ {
+ OSL_FAIL( "ScRangeData::CompileRangeData: unspecified grammar");
+ // Anything is almost as bad as this, but we might have the best choice
+ // if not loading documents.
+ eTempGrammar = FormulaGrammar::GRAM_NATIVE;
+ }
+
+ ScCompiler aComp( pDoc, aPos );
+ aComp.SetGrammar( eTempGrammar);
+ if (bSetError)
+ aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_NO_BREAK);
+ ScTokenArray* pNewCode = aComp.CompileString( rSymbol );
+ ::std::auto_ptr<ScTokenArray> pOldCode( pCode); // old pCode will be deleted
+ pCode = pNewCode;
+ if( !pCode->GetCodeError() )
+ {
+ pCode->Reset();
+ FormulaToken* p = pCode->GetNextReference();
+ if( p )
+ {
+ // first token is a reference
+ /* FIXME: wouldn't that need a check if it's exactly one reference? */
+ if( p->GetType() == svSingleRef )
+ eType = eType | RT_ABSPOS;
+ else
+ eType = eType | RT_ABSAREA;
+ }
+ // For manual input set an error for an incomplete formula.
+ if (!pDoc->IsImportingXML())
+ {
+ aComp.CompileTokenArray();
+ pCode->DelRPN();
+ }
+ }
+}
+
+void ScRangeData::CompileUnresolvedXML()
+{
+ if (pCode->GetCodeError() == errNoName)
+ {
+ // Reconstruct the symbol/formula and then recompile.
+ String aSymbol;
+ ScCompiler aComp( pDoc, aPos, *pCode);
+ aComp.SetGrammar( eTempGrammar);
+ aComp.CreateStringFromTokenArray( aSymbol);
+ // Don't let the compiler set an error for unknown names on final
+ // compile, errors are handled by the interpreter thereafter.
+ CompileRangeData( aSymbol, false);
+ }
+}
+
void ScRangeData::GuessPosition()
{
- // setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel
+ // setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel
// ohne Fehler verabsolutiert werden koennen
DBG_ASSERT(aPos == ScAddress(), "die Position geht jetzt verloren");
@@ -802,6 +842,13 @@ void ScRangeName::UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY)
itr->UpdateGrow(rArea, nGrowX, nGrowY);
}
+void ScRangeName::CompileUnresolvedXML()
+{
+ DataType::iterator itr = maData.begin(), itrEnd = maData.end();
+ for (; itr != itrEnd; ++itr)
+ itr->CompileUnresolvedXML();
+}
+
ScRangeName::const_iterator ScRangeName::begin() const
{
return maData.begin();
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index f0f05b1..2cb3fe0 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -482,7 +482,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rS
aComp.SetAutoCorrection( sal_True );
if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' )
{
- aComp.SetExtendedErrorDetection( true );
+ aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_BREAK );
}
String aFormula( rString );
ScTokenArray* pArr;
--------------erAck-patch-parts--