LibreOffice Module sc (master)  1
xeformula.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <map>
21 #include <addincol.hxx>
22 #include <compiler.hxx>
23 #include <document.hxx>
24 #include <externalrefmgr.hxx>
25 #include <rangelst.hxx>
26 #include <tokenarray.hxx>
27 #include <scmatrix.hxx>
28 #include <xeformula.hxx>
29 #include <xehelper.hxx>
30 #include <xelink.hxx>
31 #include <xename.hxx>
32 #include <xestring.hxx>
33 #include <xllink.hxx>
34 #include <xltools.hxx>
35 #include <o3tl/safeint.hxx>
36 #include <sal/log.hxx>
38 
39 using namespace ::formula;
40 
41 // External reference log =====================================================
42 
44  mpUrl( nullptr ),
45  mpFirstTab( nullptr ),
46  mpLastTab( nullptr ),
47  mnFirstXclTab( EXC_TAB_DELETED ),
48  mnLastXclTab( EXC_TAB_DELETED )
49 {
50 }
51 
52 // Formula compiler ===========================================================
53 
54 namespace {
55 
58 struct XclExpScToken
59 {
60  const FormulaToken* mpScToken;
61  sal_uInt8 mnSpaces;
62 
63  explicit XclExpScToken() : mpScToken( nullptr ), mnSpaces( 0 ) {}
64  bool Is() const { return mpScToken != nullptr; }
65  StackVar GetType() const { return mpScToken ? mpScToken->GetType() : svUnknown; }
66  OpCode GetOpCode() const { return mpScToken ? mpScToken->GetOpCode() : ocNone; }
67 };
68 
71 {
72  EXC_CLASSCONV_ORG,
73  EXC_CLASSCONV_VAL,
74  EXC_CLASSCONV_ARR
75 };
76 
78 struct XclExpTokenConvInfo
79 {
80  sal_uInt16 mnTokPos;
81  XclFuncParamConv meConv;
82  bool mbValType;
83 };
84 
87 struct XclExpOperandList : public std::vector< XclExpTokenConvInfo >
88 {
89  explicit XclExpOperandList() { reserve( 2 ); }
90  void AppendOperand( sal_uInt16 nTokPos, XclFuncParamConv eConv, bool bValType );
91 };
92 
93 void XclExpOperandList::AppendOperand( sal_uInt16 nTokPos, XclFuncParamConv eConv, bool bValType )
94 {
95  resize( size() + 1 );
96  XclExpTokenConvInfo& rConvInfo = back();
97  rConvInfo.mnTokPos = nTokPos;
98  rConvInfo.meConv = eConv;
99  rConvInfo.mbValType = bValType;
100 }
101 
102 typedef std::shared_ptr< XclExpOperandList > XclExpOperandListRef;
103 
105 struct XclExpExtFuncData
106 {
107  OUString maFuncName;
108  bool mbVBasic;
109  bool mbHidden;
110 
111  explicit XclExpExtFuncData() : mbVBasic( false ), mbHidden( false ) {}
112  void Set( const OUString& rFuncName, bool bVBasic, bool bHidden );
113 };
114 
115 void XclExpExtFuncData::Set( const OUString& rFuncName, bool bVBasic, bool bHidden )
116 {
117  maFuncName = rFuncName;
118  mbVBasic = bVBasic;
119  mbHidden = bHidden;
120 }
121 
123 class XclExpFuncData
124 {
125 public:
126  explicit XclExpFuncData(
127  const XclExpScToken& rTokData,
128  const XclFunctionInfo& rFuncInfo,
129  const XclExpExtFuncData& rExtFuncData );
130 
131  const FormulaToken& GetScToken() const { return *mrTokData.mpScToken; }
132  OpCode GetOpCode() const { return mrFuncInfo.meOpCode; }
133  sal_uInt16 GetXclFuncIdx() const { return mrFuncInfo.mnXclFunc; }
134  bool IsVolatile() const { return mrFuncInfo.IsVolatile(); }
135  bool IsFixedParamCount() const { return mrFuncInfo.IsFixedParamCount(); }
136  bool IsAddInEquivalent() const { return mrFuncInfo.IsAddInEquivalent(); }
137  bool IsMacroFunc() const { return mrFuncInfo.IsMacroFunc(); }
138  sal_uInt8 GetSpaces() const { return mrTokData.mnSpaces; }
139  const XclExpExtFuncData& GetExtFuncData() const { return maExtFuncData; }
140  sal_uInt8 GetReturnClass() const { return mrFuncInfo.mnRetClass; }
141 
142  const XclFuncParamInfo& GetParamInfo() const;
143  bool IsCalcOnlyParam() const;
144  bool IsExcelOnlyParam() const;
145  void IncParamInfoIdx();
146 
147  sal_uInt8 GetMinParamCount() const { return mrFuncInfo.mnMinParamCount; }
148  sal_uInt8 GetMaxParamCount() const { return mrFuncInfo.mnMaxParamCount; }
149  sal_uInt8 GetParamCount() const { return static_cast< sal_uInt8 >( mxOperands->size() ); }
150  void FinishParam( sal_uInt16 nTokPos );
151  const XclExpOperandListRef& GetOperandList() const { return mxOperands; }
152 
153  ScfUInt16Vec& GetAttrPosVec() { return maAttrPosVec; }
154  void AppendAttrPos( sal_uInt16 nPos ) { maAttrPosVec.push_back( nPos ); }
155 
156 private:
157  ScfUInt16Vec maAttrPosVec;
158  const XclExpScToken& mrTokData;
159  const XclFunctionInfo& mrFuncInfo;
160  XclExpExtFuncData maExtFuncData;
161  XclExpOperandListRef mxOperands;
162  const XclFuncParamInfo* mpParamInfo;
163 };
164 
165 XclExpFuncData::XclExpFuncData( const XclExpScToken& rTokData,
166  const XclFunctionInfo& rFuncInfo, const XclExpExtFuncData& rExtFuncData ) :
167  mrTokData( rTokData ),
168  mrFuncInfo( rFuncInfo ),
169  maExtFuncData( rExtFuncData ),
170  mxOperands( std::make_shared<XclExpOperandList>() ),
171  mpParamInfo( rFuncInfo.mpParamInfos )
172 {
173  OSL_ENSURE( mrTokData.mpScToken, "XclExpFuncData::XclExpFuncData - missing core token" );
174  // set name of an add-in function
175  if( (maExtFuncData.maFuncName.isEmpty()) && dynamic_cast< const FormulaExternalToken* >( mrTokData.mpScToken ) )
176  maExtFuncData.Set( GetScToken().GetExternal(), true, false );
177 }
178 
179 const XclFuncParamInfo& XclExpFuncData::GetParamInfo() const
180 {
181  static const XclFuncParamInfo saInvalidInfo = { EXC_PARAM_NONE, EXC_PARAMCONV_ORG, false };
182  return mpParamInfo ? *mpParamInfo : saInvalidInfo;
183 }
184 
185 bool XclExpFuncData::IsCalcOnlyParam() const
186 {
187  return mpParamInfo && (mpParamInfo->meValid == EXC_PARAM_CALCONLY);
188 }
189 
190 bool XclExpFuncData::IsExcelOnlyParam() const
191 {
192  return mpParamInfo && (mpParamInfo->meValid == EXC_PARAM_EXCELONLY);
193 }
194 
195 void XclExpFuncData::IncParamInfoIdx()
196 {
197  if( !mpParamInfo )
198  return;
199 
200  // move pointer to next entry, if something explicit follows
201  if( (o3tl::make_unsigned( mpParamInfo - mrFuncInfo.mpParamInfos + 1 ) < EXC_FUNCINFO_PARAMINFO_COUNT) && (mpParamInfo[ 1 ].meValid != EXC_PARAM_NONE) )
202  ++mpParamInfo;
203  // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
204  else if( IsExcelOnlyParam() || IsCalcOnlyParam() )
205  mpParamInfo = nullptr;
206  // points to last info, but parameter pairs expected, move to previous info
207  else if( mrFuncInfo.IsParamPairs() )
208  --mpParamInfo;
209  // otherwise: repeat last parameter class
210 }
211 
212 void XclExpFuncData::FinishParam( sal_uInt16 nTokPos )
213 {
214  // write token class conversion info for this parameter
215  const XclFuncParamInfo& rParamInfo = GetParamInfo();
216  mxOperands->AppendOperand( nTokPos, rParamInfo.meConv, rParamInfo.mbValType );
217  // move to next parameter info structure
218  IncParamInfoIdx();
219 }
220 
221 // compiler configuration -----------------------------------------------------
222 
225 {
226  EXC_CLASSTYPE_CELL,
227  EXC_CLASSTYPE_ARRAY,
228  EXC_CLASSTYPE_NAME
229 };
230 
232 struct XclExpCompConfig
233 {
235  XclExpFmlaClassType meClassType;
236  bool mbLocalLinkMgr;
237  bool mbFromCell;
238  bool mb3DRefOnly;
239  bool mbAllowArrays;
240 };
241 
243 const XclExpCompConfig spConfigTable[] =
244 {
245  // formula type token class type lclLM inCell 3dOnly allowArray
246  { EXC_FMLATYPE_CELL, EXC_CLASSTYPE_CELL, true, true, false, true },
247  { EXC_FMLATYPE_SHARED, EXC_CLASSTYPE_CELL, true, true, false, true },
248  { EXC_FMLATYPE_MATRIX, EXC_CLASSTYPE_ARRAY, true, true, false, true },
249  { EXC_FMLATYPE_CONDFMT, EXC_CLASSTYPE_ARRAY, true, false, false, false },
250  { EXC_FMLATYPE_DATAVAL, EXC_CLASSTYPE_ARRAY, true, false, false, false },
251  { EXC_FMLATYPE_NAME, EXC_CLASSTYPE_NAME, false, false, true, true },
252  { EXC_FMLATYPE_CHART, EXC_CLASSTYPE_NAME, true, false, true, true },
253  { EXC_FMLATYPE_CONTROL, EXC_CLASSTYPE_NAME, true, false, false, false },
254  { EXC_FMLATYPE_WQUERY, EXC_CLASSTYPE_NAME, true, false, true, false },
255  { EXC_FMLATYPE_LISTVAL, EXC_CLASSTYPE_NAME, true, false, false, false }
256 };
257 
259 struct XclExpCompData
260 {
261  typedef std::shared_ptr< ScTokenArray > ScTokenArrayRef;
262 
263  const XclExpCompConfig& mrCfg;
264  ScTokenArrayRef mxOwnScTokArr;
265  XclTokenArrayIterator maTokArrIt;
266  XclExpLinkManager* mpLinkMgr;
267  XclExpRefLog* mpRefLog;
268  const ScAddress* mpScBasePos;
269 
270  ScfUInt8Vec maTokVec;
271  ScfUInt8Vec maExtDataVec;
272  std::vector< XclExpOperandListRef >
273  maOpListVec;
274  ScfUInt16Vec maOpPosStack;
275  bool mbStopAtSep;
276  bool mbVolatile;
277  bool mbOk;
278 
279  explicit XclExpCompData( const XclExpCompConfig* pCfg );
280 };
281 
282 XclExpCompData::XclExpCompData( const XclExpCompConfig* pCfg ) :
283  mrCfg( pCfg ? *pCfg : spConfigTable[ 0 ] ),
284  mpLinkMgr( nullptr ),
285  mpRefLog( nullptr ),
286  mpScBasePos( nullptr ),
287  mbStopAtSep( false ),
288  mbVolatile( false ),
289  mbOk( pCfg != nullptr )
290 {
291  OSL_ENSURE( pCfg, "XclExpFmlaCompImpl::Init - unknown formula type" );
292 }
293 
294 } // namespace
295 
298 {
299 public:
300  explicit XclExpFmlaCompImpl( const XclExpRoot& rRoot );
301 
304  XclFormulaType eType, const ScTokenArray& rScTokArr,
305  const ScAddress* pScBasePos = nullptr, XclExpRefLog* pRefLog = nullptr );
309  XclTokenArrayRef CreateSpecialRefFormula( sal_uInt8 nTokenId, const XclAddress& rXclPos );
311  XclTokenArrayRef CreateNameXFormula( sal_uInt16 nExtSheet, sal_uInt16 nExtName );
312 
314  bool Is3DRefOnly( XclFormulaType eType ) const;
315 
316  bool IsRef2D( const ScSingleRefData& rRefData, bool bCheck3DFlag ) const;
317  bool IsRef2D( const ScComplexRefData& rRefData, bool bCheck3DFlag ) const;
318 
319 private:
320  const XclExpCompConfig* GetConfigForType( XclFormulaType eType ) const;
321  sal_uInt16 GetSize() const { return static_cast< sal_uInt16 >( mxData->maTokVec.size() ); }
322 
323  void Init( XclFormulaType eType );
324  void Init( XclFormulaType eType, const ScTokenArray& rScTokArr,
325  const ScAddress* pScBasePos, XclExpRefLog* pRefLog );
326 
327  void RecalcTokenClasses();
328  void RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo, XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass );
329 
330  void FinalizeFormula();
332 
333  // compiler ---------------------------------------------------------------
334  // XclExpScToken: pass-by-value and return-by-value is intended
335 
336  const FormulaToken* GetNextRawToken();
337  const FormulaToken* PeekNextRawToken() const;
338 
339  bool GetNextToken( XclExpScToken& rTokData );
340  XclExpScToken GetNextToken();
341 
342  XclExpScToken Expression( XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep );
343  XclExpScToken SkipExpression( XclExpScToken aTokData, bool bStopAtSep );
344 
345  XclExpScToken OrTerm( XclExpScToken aTokData, bool bInParentheses );
346  XclExpScToken AndTerm( XclExpScToken aTokData, bool bInParentheses );
347  XclExpScToken CompareTerm( XclExpScToken aTokData, bool bInParentheses );
348  XclExpScToken ConcatTerm( XclExpScToken aTokData, bool bInParentheses );
349  XclExpScToken AddSubTerm( XclExpScToken aTokData, bool bInParentheses );
350  XclExpScToken MulDivTerm( XclExpScToken aTokData, bool bInParentheses );
351  XclExpScToken PowTerm( XclExpScToken aTokData, bool bInParentheses );
352  XclExpScToken UnaryPostTerm( XclExpScToken aTokData, bool bInParentheses );
353  XclExpScToken UnaryPreTerm( XclExpScToken aTokData, bool bInParentheses );
354  XclExpScToken ListTerm( XclExpScToken aTokData, bool bInParentheses );
355  XclExpScToken IntersectTerm( XclExpScToken aTokData, bool& rbHasRefOp );
356  XclExpScToken RangeTerm( XclExpScToken aTokData, bool& rbHasRefOp );
357  XclExpScToken Factor( XclExpScToken aTokData );
358 
359  // formula structure ------------------------------------------------------
360 
361  void ProcessDouble( const XclExpScToken& rTokData );
362  void ProcessString( const XclExpScToken& rTokData );
363  void ProcessMissing( const XclExpScToken& rTokData );
364  void ProcessBad( const XclExpScToken& rTokData );
365  void ProcessParentheses( const XclExpScToken& rTokData );
366  void ProcessBoolean( const XclExpScToken& rTokData );
367  void ProcessDdeLink( const XclExpScToken& rTokData );
368  void ProcessExternal( const XclExpScToken& rTokData );
369  void ProcessMatrix( const XclExpScToken& rTokData );
370 
371  void ProcessFunction( const XclExpScToken& rTokData );
372  void PrepareFunction( const XclExpFuncData& rFuncData );
373  void FinishFunction( XclExpFuncData& rFuncData, sal_uInt8 nCloseSpaces );
374  void FinishIfFunction( XclExpFuncData& rFuncData );
375  void FinishChooseFunction( XclExpFuncData& rFuncData );
376 
377  XclExpScToken ProcessParam( XclExpScToken aTokData, XclExpFuncData& rFuncData );
378  void PrepareParam( XclExpFuncData& rFuncData );
379  void FinishParam( XclExpFuncData& rFuncData );
380  void AppendDefaultParam( XclExpFuncData& rFuncData );
381  void AppendTrailingParam( XclExpFuncData& rFuncData );
382 
383  // reference handling -----------------------------------------------------
384 
385  SCTAB GetScTab( const ScSingleRefData& rRefData ) const;
386 
387  void ConvertRefData( ScSingleRefData& rRefData, XclAddress& rXclPos,
388  bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow ) const;
389  void ConvertRefData( ScComplexRefData& rRefData, XclRange& rXclRange,
390  bool bNatLangRef ) const;
391 
393  void ProcessCellRef( const XclExpScToken& rTokData );
394  void ProcessRangeRef( const XclExpScToken& rTokData );
395  void ProcessExternalCellRef( const XclExpScToken& rTokData );
396  void ProcessExternalRangeRef( const XclExpScToken& rTokData );
397  void ProcessDefinedName( const XclExpScToken& rTokData );
398  void ProcessExternalName( const XclExpScToken& rTokData );
399 
400  // token vector -----------------------------------------------------------
401 
402  void PushOperandPos( sal_uInt16 nTokPos );
403  void PushOperatorPos( sal_uInt16 nTokPos, const XclExpOperandListRef& rxOperands );
404  sal_uInt16 PopOperandPos();
405 
406  void Append( sal_uInt8 nData );
407  void Append( sal_uInt8 nData, size_t nCount );
408  void Append( sal_uInt16 nData );
409  void Append( sal_uInt32 nData );
410  void Append( double fData );
411  void Append( const OUString& rString );
412 
413  void AppendAddress( const XclAddress& rXclPos );
414  void AppendRange( const XclRange& rXclRange );
415 
416  void AppendSpaceToken( sal_uInt8 nType, sal_uInt8 nCount );
417 
418  void AppendOperandTokenId( sal_uInt8 nTokenId, sal_uInt8 nSpaces = 0 );
419  void AppendIntToken( sal_uInt16 nValue, sal_uInt8 nSpaces = 0 );
420  void AppendNumToken( double fValue, sal_uInt8 nSpaces = 0 );
421  void AppendBoolToken( bool bValue, sal_uInt8 nSpaces = 0 );
422  void AppendErrorToken( sal_uInt8 nErrCode, sal_uInt8 nSpaces = 0 );
423  void AppendMissingToken( sal_uInt8 nSpaces = 0 );
424  void AppendNameToken( sal_uInt16 nNameIdx, sal_uInt8 nSpaces = 0 );
425  void AppendMissingNameToken( const OUString& rName, sal_uInt8 nSpaces = 0 );
426  void AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces = 0 );
427  void AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData );
428  void AppendAddInCallToken( const XclExpExtFuncData& rExtFuncData );
429  void AppendEuroToolCallToken( const XclExpExtFuncData& rExtFuncData );
430 
431  void AppendOperatorTokenId( sal_uInt8 nTokenId, const XclExpOperandListRef& rxOperands, sal_uInt8 nSpaces = 0 );
432  void AppendUnaryOperatorToken( sal_uInt8 nTokenId, sal_uInt8 nSpaces = 0 );
433  void AppendBinaryOperatorToken( sal_uInt8 nTokenId, bool bValType, sal_uInt8 nSpaces = 0 );
434  void AppendLogicalOperatorToken( sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount );
435  void AppendFuncToken( const XclExpFuncData& rFuncData );
436 
437  void AppendParenToken( sal_uInt8 nOpenSpaces = 0, sal_uInt8 nCloseSpaces = 0 );
438  void AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType );
439 
440  void InsertZeros( sal_uInt16 nInsertPos, sal_uInt16 nInsertSize );
441  void Overwrite( sal_uInt16 nWriteToPos, sal_uInt16 nOffset );
442 
443  void UpdateAttrGoto( sal_uInt16 nAttrPos );
444 
445  bool IsSpaceToken( sal_uInt16 nPos ) const;
446  void RemoveTrailingParen();
447 
448  void AppendExt( sal_uInt8 nData );
449  void AppendExt( sal_uInt8 nData, size_t nCount );
450  void AppendExt( sal_uInt16 nData );
451  void AppendExt( double fData );
452  void AppendExt( const OUString& rString );
453 
454 private:
455  typedef std::map< XclFormulaType, XclExpCompConfig > XclExpCompConfigMap;
456  typedef std::shared_ptr< XclExpCompData > XclExpCompDataRef;
457 
458  XclExpCompConfigMap maCfgMap;
460  XclExpCompDataRef mxData;
461  std::vector< XclExpCompDataRef >
463  const XclBiff meBiff;
468  const sal_uInt16 mnMaxColMask;
469  const sal_uInt32 mnMaxRowMask;
470 };
471 
473  XclExpRoot( rRoot ),
474  maFuncProv( rRoot ),
475  meBiff( rRoot.GetBiff() ),
476  mnMaxAbsCol( rRoot.GetXclMaxPos().Col() ),
477  mnMaxAbsRow( rRoot.GetXclMaxPos().Row() ),
478  mnMaxScCol( rRoot.GetScMaxPos().Col() ),
479  mnMaxScRow( rRoot.GetScMaxPos().Row() ),
480  mnMaxColMask( static_cast< sal_uInt16 >( rRoot.GetXclMaxPos().Col() ) ),
481  mnMaxRowMask( static_cast< sal_uInt32 >( rRoot.GetXclMaxPos().Row() ) )
482 {
483  // build the configuration map
484  for(auto const &rEntry : spConfigTable)
485  maCfgMap[ rEntry.meType ] = rEntry;
486 }
487 
489  const ScTokenArray& rScTokArr, const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
490 {
491  // initialize the compiler
492  Init( eType, rScTokArr, pScBasePos, pRefLog );
493 
494  // start compilation, if initialization didn't fail
495  if( mxData->mbOk )
496  {
497  XclExpScToken aTokData( GetNextToken() );
498  FormulaError nScError = rScTokArr.GetCodeError();
499  if( (nScError != FormulaError::NONE) && (!aTokData.Is() || (aTokData.GetOpCode() == ocStop)) )
500  {
501  // #i50253# convert simple ocStop token to error code formula (e.g. =#VALUE!)
502  AppendErrorToken( XclTools::GetXclErrorCode( nScError ), aTokData.mnSpaces );
503  }
504  else if( aTokData.Is() )
505  {
506  aTokData = Expression( aTokData, false, false );
507  }
508  else
509  {
510  OSL_FAIL( "XclExpFmlaCompImpl::CreateFormula - empty token array" );
511  mxData->mbOk = false;
512  }
513 
514  if( mxData->mbOk )
515  {
516  // #i44907# auto-generated SUBTOTAL formula cells have trailing ocStop token
517  mxData->mbOk = !aTokData.Is() || (aTokData.GetOpCode() == ocStop);
518  OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::CreateFormula - unknown garbage behind formula" );
519  }
520  }
521 
522  // finalize (add tAttrVolatile token, calculate all token classes)
524  FinalizeFormula();
525 
526  // leave recursive call, create and return the final token array
527  return CreateTokenArray();
528 }
529 
531 {
533  AppendErrorToken( nErrCode );
534  return CreateTokenArray();
535 }
536 
538 {
540  AppendOperandTokenId( nTokenId );
541  Append( static_cast<sal_uInt16>(rXclPos.mnRow) );
542  Append( rXclPos.mnCol ); // do not use AppendAddress(), we always need 16-bit column here
543  return CreateTokenArray();
544 }
545 
546 XclTokenArrayRef XclExpFmlaCompImpl::CreateNameXFormula( sal_uInt16 nExtSheet, sal_uInt16 nExtName )
547 {
549  AppendNameXToken( nExtSheet, nExtName );
550  return CreateTokenArray();
551 }
552 
554 {
555  const XclExpCompConfig* pCfg = GetConfigForType( eType );
556  return pCfg && pCfg->mb3DRefOnly;
557 }
558 
559 // private --------------------------------------------------------------------
560 
561 const XclExpCompConfig* XclExpFmlaCompImpl::GetConfigForType( XclFormulaType eType ) const
562 {
563  XclExpCompConfigMap::const_iterator aIt = maCfgMap.find( eType );
564  OSL_ENSURE( aIt != maCfgMap.end(), "XclExpFmlaCompImpl::GetConfigForType - unknown formula type" );
565  return (aIt == maCfgMap.end()) ? nullptr : &aIt->second;
566 }
567 
569 {
570  // compiler invoked recursively? - store old working data
571  if( mxData )
572  maDataStack.push_back( mxData );
573  // new compiler working data structure
574  mxData = std::make_shared<XclExpCompData>( GetConfigForType( eType ) );
575 }
576 
578  const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
579 {
580  // common initialization
581  Init( eType );
582 
583  // special initialization
584  if( mxData->mbOk ) switch( mxData->mrCfg.meType )
585  {
586  case EXC_FMLATYPE_CELL:
587  case EXC_FMLATYPE_MATRIX:
588  case EXC_FMLATYPE_CHART:
589  mxData->mbOk = pScBasePos != nullptr;
590  OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::Init - missing cell address" );
591  mxData->mpScBasePos = pScBasePos;
592  break;
593  case EXC_FMLATYPE_SHARED:
594  mxData->mbOk = pScBasePos != nullptr;
595  assert(mxData->mbOk && "XclExpFmlaCompImpl::Init - missing cell address");
596  if (mxData->mbOk)
597  {
598  // clone the passed token array, convert references relative to current cell position
599  mxData->mxOwnScTokArr = rScTokArr.Clone();
600  ScCompiler::MoveRelWrap( *mxData->mxOwnScTokArr, &GetDoc(), *pScBasePos, GetDoc().MaxCol(), GetDoc().MaxRow() );
601  // don't remember pScBasePos in mxData->mpScBasePos, shared formulas use real relative refs
602  }
603  break;
604  default:;
605  }
606 
607  if( mxData->mbOk )
608  {
609  // link manager to be used
610  mxData->mpLinkMgr = mxData->mrCfg.mbLocalLinkMgr ? &GetLocalLinkManager() : &GetGlobalLinkManager();
611 
612  // token array iterator (use cloned token array if present)
613  mxData->maTokArrIt.Init( mxData->mxOwnScTokArr ? *mxData->mxOwnScTokArr : rScTokArr, false );
614  mxData->mpRefLog = pRefLog;
615  }
616 }
617 
619 {
620  if( !mxData->mbOk )
621  return;
622 
623  mxData->mbOk = mxData->maOpPosStack.size() == 1;
624  OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::RecalcTokenClasses - position of root token expected on stack" );
625  if( mxData->mbOk )
626  {
627  /* Cell and array formulas start with VAL conversion and VALTYPE
628  parameter type, defined names start with ARR conversion and
629  REFTYPE parameter type for the root token. */
630  bool bNameFmla = mxData->mrCfg.meClassType == EXC_CLASSTYPE_NAME;
631  XclFuncParamConv eParamConv = bNameFmla ? EXC_PARAMCONV_ARR : EXC_PARAMCONV_VAL;
632  XclExpClassConv eClassConv = bNameFmla ? EXC_CLASSCONV_ARR : EXC_CLASSCONV_VAL;
633  XclExpTokenConvInfo aConvInfo = { PopOperandPos(), eParamConv, !bNameFmla };
634  RecalcTokenClass( aConvInfo, eParamConv, eClassConv, bNameFmla );
635  }
636 
637  // clear operand vectors (calls to the expensive InsertZeros() may follow)
638  mxData->maOpListVec.clear();
639  mxData->maOpPosStack.clear();
640 }
641 
642 void XclExpFmlaCompImpl::RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo,
643  XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass )
644 {
645  OSL_ENSURE( rConvInfo.mnTokPos < GetSize(), "XclExpFmlaCompImpl::RecalcTokenClass - invalid token position" );
646  sal_uInt8& rnTokenId = mxData->maTokVec[ rConvInfo.mnTokPos ];
647  sal_uInt8 nTokClass = GetTokenClass( rnTokenId );
648 
649  // REF tokens in VALTYPE parameters behave like VAL tokens
650  if( rConvInfo.mbValType && (nTokClass == EXC_TOKCLASS_REF) )
651  {
652  nTokClass = EXC_TOKCLASS_VAL;
653  ChangeTokenClass( rnTokenId, nTokClass );
654  }
655 
656  // replace RPO conversion of operator with parent conversion
657  XclFuncParamConv eConv = (rConvInfo.meConv == EXC_PARAMCONV_RPO) ? ePrevConv : rConvInfo.meConv;
658 
659  // find the effective token class conversion to be performed for this token
660  XclExpClassConv eClassConv = EXC_CLASSCONV_ORG;
661  switch( eConv )
662  {
663  case EXC_PARAMCONV_ORG:
664  // conversion is forced independent of parent conversion
665  eClassConv = EXC_CLASSCONV_ORG;
666  break;
667  case EXC_PARAMCONV_VAL:
668  // conversion is forced independent of parent conversion
669  eClassConv = EXC_CLASSCONV_VAL;
670  break;
671  case EXC_PARAMCONV_ARR:
672  // conversion is forced independent of parent conversion
673  eClassConv = EXC_CLASSCONV_ARR;
674  break;
675  case EXC_PARAMCONV_RPT:
676  switch( ePrevConv )
677  {
678  case EXC_PARAMCONV_ORG:
679  case EXC_PARAMCONV_VAL:
680  case EXC_PARAMCONV_ARR:
681  /* If parent token has REF class (REF token in REFTYPE
682  function parameter), then RPT does not repeat the
683  previous explicit ORG or ARR conversion, but always
684  falls back to VAL conversion. */
685  eClassConv = bWasRefClass ? EXC_CLASSCONV_VAL : ePrevClassConv;
686  break;
687  case EXC_PARAMCONV_RPT:
688  // nested RPT repeats the previous effective conversion
689  eClassConv = ePrevClassConv;
690  break;
691  case EXC_PARAMCONV_RPX:
692  /* If parent token has REF class (REF token in REFTYPE
693  function parameter), then RPX repeats the previous
694  effective conversion (which will be either ORG or ARR,
695  but never VAL), otherwise falls back to ORG conversion. */
696  eClassConv = bWasRefClass ? ePrevClassConv : EXC_CLASSCONV_ORG;
697  break;
698  case EXC_PARAMCONV_RPO: // does not occur
699  break;
700  }
701  break;
702  case EXC_PARAMCONV_RPX:
703  /* If current token still has REF class, set previous effective
704  conversion as current conversion. This will not have an effect
705  on the REF token but is needed for RPT parameters of this
706  function that want to repeat this conversion type. If current
707  token is VAL or ARR class, the previous ARR conversion will be
708  repeated on the token, but VAL conversion will not. */
709  eClassConv = ((nTokClass == EXC_TOKCLASS_REF) || (ePrevClassConv == EXC_CLASSCONV_ARR)) ?
710  ePrevClassConv : EXC_CLASSCONV_ORG;
711  break;
712  case EXC_PARAMCONV_RPO: // does not occur (see above)
713  break;
714  }
715 
716  // do the token class conversion
717  switch( eClassConv )
718  {
719  case EXC_CLASSCONV_ORG:
720  /* Cell formulas: leave the current token class. Cell formulas
721  are the only type of formulas where all tokens can keep
722  their original token class.
723  Array and defined name formulas: convert VAL to ARR. */
724  if( (mxData->mrCfg.meClassType != EXC_CLASSTYPE_CELL) && (nTokClass == EXC_TOKCLASS_VAL) )
725  {
726  nTokClass = EXC_TOKCLASS_ARR;
727  ChangeTokenClass( rnTokenId, nTokClass );
728  }
729  break;
730  case EXC_CLASSCONV_VAL:
731  // convert ARR to VAL
732  if( nTokClass == EXC_TOKCLASS_ARR )
733  {
734  nTokClass = EXC_TOKCLASS_VAL;
735  ChangeTokenClass( rnTokenId, nTokClass );
736  }
737  break;
738  case EXC_CLASSCONV_ARR:
739  // convert VAL to ARR
740  if( nTokClass == EXC_TOKCLASS_VAL )
741  {
742  nTokClass = EXC_TOKCLASS_ARR;
743  ChangeTokenClass( rnTokenId, nTokClass );
744  }
745  break;
746  }
747 
748  // do conversion for nested operands, if token is an operator or function
749  if( rConvInfo.mnTokPos < mxData->maOpListVec.size() )
750  if( const XclExpOperandList* pOperands = mxData->maOpListVec[ rConvInfo.mnTokPos ].get() )
751  for( const auto& rOperand : *pOperands )
752  RecalcTokenClass( rOperand, eConv, eClassConv, nTokClass == EXC_TOKCLASS_REF );
753 }
754 
756 {
757  if( mxData->mbOk )
758  {
759  // Volatile? Add a tAttrVolatile token at the beginning of the token array.
760  if( mxData->mbVolatile )
761  {
762  // tAttrSpace token can be extended with volatile flag
763  if( !IsSpaceToken( 0 ) )
764  {
765  InsertZeros( 0, 4 );
766  mxData->maTokVec[ 0 ] = EXC_TOKID_ATTR;
767  }
768  mxData->maTokVec[ 1 ] |= EXC_TOK_ATTR_VOLATILE;
769  }
770 
771  // Token array too long? -> error
772  mxData->mbOk = mxData->maTokVec.size() <= EXC_TOKARR_MAXLEN;
773  }
774 
775  if( !mxData->mbOk )
776  {
777  // Any unrecoverable error? -> Create a =#NA formula.
778  mxData->maTokVec.clear();
779  mxData->maExtDataVec.clear();
780  mxData->mbVolatile = false;
782  }
783 }
784 
786 {
787  // create the Excel token array from working data before resetting mxData
788  OSL_ENSURE( mxData->mrCfg.mbAllowArrays || mxData->maExtDataVec.empty(), "XclExpFmlaCompImpl::CreateTokenArray - unexpected extended data" );
789  if( !mxData->mrCfg.mbAllowArrays )
790  mxData->maExtDataVec.clear();
791  XclTokenArrayRef xTokArr = std::make_shared<XclTokenArray>( mxData->maTokVec, mxData->maExtDataVec, mxData->mbVolatile );
792  mxData.reset();
793 
794  // compiler invoked recursively? - restore old working data
795  if( !maDataStack.empty() )
796  {
797  mxData = maDataStack.back();
798  maDataStack.pop_back();
799  }
800 
801  return xTokArr;
802 }
803 
804 // compiler -------------------------------------------------------------------
805 
807 {
808  const FormulaToken* pScToken = mxData->maTokArrIt.Get();
809  ++mxData->maTokArrIt;
810  return pScToken;
811 }
812 
813 const FormulaToken* XclExpFmlaCompImpl::PeekNextRawToken() const
814 {
815  /* Returns pointer to next raw token in the token array. The token array
816  iterator already points to the next token (A call to GetNextToken()
817  always increases the iterator), so this function just returns the token
818  the iterator points to. To skip space tokens, a copy of the iterator is
819  created and set to the passed skip-spaces mode. If spaces have to be
820  skipped, and the iterator currently points to a space token, the
821  constructor will move it to the next non-space token. */
822  XclTokenArrayIterator aTempIt( mxData->maTokArrIt, true/*bSkipSpaces*/ );
823  return aTempIt.Get();
824 }
825 
826 bool XclExpFmlaCompImpl::GetNextToken( XclExpScToken& rTokData )
827 {
828  rTokData.mpScToken = GetNextRawToken();
829  rTokData.mnSpaces = (rTokData.GetOpCode() == ocSpaces) ? rTokData.mpScToken->GetByte() : 0;
830  while( rTokData.GetOpCode() == ocSpaces )
831  rTokData.mpScToken = GetNextRawToken();
832  return rTokData.Is();
833 }
834 
836 {
837  XclExpScToken aTokData;
838  GetNextToken( aTokData );
839  return aTokData;
840 }
841 
842 namespace {
843 
845 sal_uInt8 lclGetCompareTokenId( OpCode eOpCode )
846 {
847  switch( eOpCode )
848  {
849  case ocLess: return EXC_TOKID_LT;
850  case ocLessEqual: return EXC_TOKID_LE;
851  case ocEqual: return EXC_TOKID_EQ;
852  case ocGreaterEqual: return EXC_TOKID_GE;
853  case ocGreater: return EXC_TOKID_GT;
854  case ocNotEqual: return EXC_TOKID_NE;
855  default:;
856  }
857  return EXC_TOKID_NONE;
858 }
859 
861 sal_uInt8 lclGetConcatTokenId( OpCode eOpCode )
862 {
863  return (eOpCode == ocAmpersand) ? EXC_TOKID_CONCAT : EXC_TOKID_NONE;
864 }
865 
867 sal_uInt8 lclGetAddSubTokenId( OpCode eOpCode )
868 {
869  switch( eOpCode )
870  {
871  case ocAdd: return EXC_TOKID_ADD;
872  case ocSub: return EXC_TOKID_SUB;
873  default:;
874  }
875  return EXC_TOKID_NONE;
876 }
877 
879 sal_uInt8 lclGetMulDivTokenId( OpCode eOpCode )
880 {
881  switch( eOpCode )
882  {
883  case ocMul: return EXC_TOKID_MUL;
884  case ocDiv: return EXC_TOKID_DIV;
885  default:;
886  }
887  return EXC_TOKID_NONE;
888 }
889 
891 sal_uInt8 lclGetPowTokenId( OpCode eOpCode )
892 {
893  return (eOpCode == ocPow) ? EXC_TOKID_POWER : EXC_TOKID_NONE;
894 }
895 
897 sal_uInt8 lclGetUnaryPostTokenId( OpCode eOpCode )
898 {
899  return (eOpCode == ocPercentSign) ? EXC_TOKID_PERCENT : EXC_TOKID_NONE;
900 }
901 
903 sal_uInt8 lclGetUnaryPreTokenId( OpCode eOpCode )
904 {
905  switch( eOpCode )
906  {
907  case ocAdd: return EXC_TOKID_UPLUS; // +(1)
908  case ocNeg: return EXC_TOKID_UMINUS; // NEG(1)
909  case ocNegSub: return EXC_TOKID_UMINUS; // -(1)
910  default:;
911  }
912  return EXC_TOKID_NONE;
913 }
914 
916 sal_uInt8 lclGetListTokenId( OpCode eOpCode, bool bStopAtSep )
917 {
918  return ((eOpCode == ocUnion) || (!bStopAtSep && (eOpCode == ocSep))) ? EXC_TOKID_LIST : EXC_TOKID_NONE;
919 }
920 
922 sal_uInt8 lclGetIntersectTokenId( OpCode eOpCode )
923 {
924  return (eOpCode == ocIntersect) ? EXC_TOKID_ISECT : EXC_TOKID_NONE;
925 }
926 
928 sal_uInt8 lclGetRangeTokenId( OpCode eOpCode )
929 {
930  return (eOpCode == ocRange) ? EXC_TOKID_RANGE : EXC_TOKID_NONE;
931 }
932 
933 } // namespace
934 
935 XclExpScToken XclExpFmlaCompImpl::Expression( XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep )
936 {
937  if( mxData->mbOk && aTokData.Is() )
938  {
939  // remember old stop-at-ocSep mode, restored below
940  bool bOldStopAtSep = mxData->mbStopAtSep;
941  mxData->mbStopAtSep = bStopAtSep;
942  // start compilation of the subexpression
943  aTokData = OrTerm( aTokData, bInParentheses );
944  // restore old stop-at-ocSep mode
945  mxData->mbStopAtSep = bOldStopAtSep;
946  }
947  return aTokData;
948 }
949 
950 XclExpScToken XclExpFmlaCompImpl::SkipExpression( XclExpScToken aTokData, bool bStopAtSep )
951 {
952  while( mxData->mbOk && aTokData.Is() && (aTokData.GetOpCode() != ocClose) && (!bStopAtSep || (aTokData.GetOpCode() != ocSep)) )
953  {
954  if( aTokData.GetOpCode() == ocOpen )
955  {
956  aTokData = SkipExpression( GetNextToken(), false );
957  if( mxData->mbOk ) mxData->mbOk = aTokData.GetOpCode() == ocClose;
958  }
959  aTokData = GetNextToken();
960  }
961  return aTokData;
962 }
963 
964 XclExpScToken XclExpFmlaCompImpl::OrTerm( XclExpScToken aTokData, bool bInParentheses )
965 {
966  aTokData = AndTerm( aTokData, bInParentheses );
968  while( mxData->mbOk && (aTokData.GetOpCode() == ocOr) )
969  {
971  aTokData = AndTerm( GetNextToken(), bInParentheses );
973  ++nParamCount;
974  if( mxData->mbOk ) mxData->mbOk = nParamCount <= EXC_FUNC_MAXPARAM;
975  }
976  if( mxData->mbOk && (nParamCount > 1) )
978  return aTokData;
979 }
980 
981 XclExpScToken XclExpFmlaCompImpl::AndTerm( XclExpScToken aTokData, bool bInParentheses )
982 {
983  aTokData = CompareTerm( aTokData, bInParentheses );
985  while( mxData->mbOk && (aTokData.GetOpCode() == ocAnd) )
986  {
988  aTokData = CompareTerm( GetNextToken(), bInParentheses );
990  ++nParamCount;
991  if( mxData->mbOk ) mxData->mbOk = nParamCount <= EXC_FUNC_MAXPARAM;
992  }
993  if( mxData->mbOk && (nParamCount > 1) )
995  return aTokData;
996 }
997 
998 XclExpScToken XclExpFmlaCompImpl::CompareTerm( XclExpScToken aTokData, bool bInParentheses )
999 {
1000  aTokData = ConcatTerm( aTokData, bInParentheses );
1001  while( mxData->mbOk )
1002  {
1003  sal_uInt8 nOpTokenId = lclGetConcatTokenId( aTokData.GetOpCode() );
1004  if (nOpTokenId == EXC_TOKID_NONE)
1005  break;
1006  sal_uInt8 nSpaces = aTokData.mnSpaces;
1007  aTokData = ConcatTerm( GetNextToken(), bInParentheses );
1008  AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1009  }
1010  return aTokData;
1011 }
1012 
1013 XclExpScToken XclExpFmlaCompImpl::ConcatTerm( XclExpScToken aTokData, bool bInParentheses )
1014 {
1015  aTokData = AddSubTerm( aTokData, bInParentheses );
1016  while( mxData->mbOk )
1017  {
1018  sal_uInt8 nOpTokenId = lclGetCompareTokenId( aTokData.GetOpCode() );
1019  if (nOpTokenId == EXC_TOKID_NONE)
1020  break;
1021  sal_uInt8 nSpaces = aTokData.mnSpaces;
1022  aTokData = AddSubTerm( GetNextToken(), bInParentheses );
1023  AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1024  }
1025  return aTokData;
1026 }
1027 
1028 XclExpScToken XclExpFmlaCompImpl::AddSubTerm( XclExpScToken aTokData, bool bInParentheses )
1029 {
1030  aTokData = MulDivTerm( aTokData, bInParentheses );
1031  while( mxData->mbOk )
1032  {
1033  sal_uInt8 nOpTokenId = lclGetAddSubTokenId( aTokData.GetOpCode() );
1034  if (nOpTokenId == EXC_TOKID_NONE)
1035  break;
1036  sal_uInt8 nSpaces = aTokData.mnSpaces;
1037  aTokData = MulDivTerm( GetNextToken(), bInParentheses );
1038  AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1039  }
1040  return aTokData;
1041 }
1042 
1043 XclExpScToken XclExpFmlaCompImpl::MulDivTerm( XclExpScToken aTokData, bool bInParentheses )
1044 {
1045  aTokData = PowTerm( aTokData, bInParentheses );
1046  while( mxData->mbOk )
1047  {
1048  sal_uInt8 nOpTokenId = lclGetMulDivTokenId( aTokData.GetOpCode() );
1049  if (nOpTokenId == EXC_TOKID_NONE)
1050  break;
1051  sal_uInt8 nSpaces = aTokData.mnSpaces;
1052  aTokData = PowTerm( GetNextToken(), bInParentheses );
1053  AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1054  }
1055  return aTokData;
1056 }
1057 
1058 XclExpScToken XclExpFmlaCompImpl::PowTerm( XclExpScToken aTokData, bool bInParentheses )
1059 {
1060  aTokData = UnaryPostTerm( aTokData, bInParentheses );
1061  sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1062  while( mxData->mbOk )
1063  {
1064  nOpTokenId = lclGetPowTokenId( aTokData.GetOpCode() );
1065  if (nOpTokenId == EXC_TOKID_NONE)
1066  break;
1067  sal_uInt8 nSpaces = aTokData.mnSpaces;
1068  aTokData = UnaryPostTerm( GetNextToken(), bInParentheses );
1069  AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1070  }
1071  return aTokData;
1072 }
1073 
1074 XclExpScToken XclExpFmlaCompImpl::UnaryPostTerm( XclExpScToken aTokData, bool bInParentheses )
1075 {
1076  aTokData = UnaryPreTerm( aTokData, bInParentheses );
1077  sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1078  while( mxData->mbOk )
1079  {
1080  nOpTokenId = lclGetUnaryPostTokenId( aTokData.GetOpCode() );
1081  if (nOpTokenId == EXC_TOKID_NONE)
1082  break;
1083  AppendUnaryOperatorToken( nOpTokenId, aTokData.mnSpaces );
1084  GetNextToken( aTokData );
1085  }
1086  return aTokData;
1087 }
1088 
1089 XclExpScToken XclExpFmlaCompImpl::UnaryPreTerm( XclExpScToken aTokData, bool bInParentheses )
1090 {
1091  sal_uInt8 nOpTokenId = mxData->mbOk ? lclGetUnaryPreTokenId( aTokData.GetOpCode() ) : EXC_TOKID_NONE;
1092  if( nOpTokenId != EXC_TOKID_NONE )
1093  {
1094  sal_uInt8 nSpaces = aTokData.mnSpaces;
1095  aTokData = UnaryPreTerm( GetNextToken(), bInParentheses );
1096  AppendUnaryOperatorToken( nOpTokenId, nSpaces );
1097  }
1098  else
1099  {
1100  aTokData = ListTerm( aTokData, bInParentheses );
1101  }
1102  return aTokData;
1103 }
1104 
1105 XclExpScToken XclExpFmlaCompImpl::ListTerm( XclExpScToken aTokData, bool bInParentheses )
1106 {
1107  sal_uInt16 nSubExprPos = GetSize();
1108  bool bHasAnyRefOp = false;
1109  bool bHasListOp = false;
1110  aTokData = IntersectTerm( aTokData, bHasAnyRefOp );
1111  while( mxData->mbOk )
1112  {
1113  sal_uInt8 nOpTokenId = lclGetListTokenId( aTokData.GetOpCode(), mxData->mbStopAtSep );
1114  if (nOpTokenId == EXC_TOKID_NONE)
1115  break;
1116  sal_uInt8 nSpaces = aTokData.mnSpaces;
1117  aTokData = IntersectTerm( GetNextToken(), bHasAnyRefOp );
1118  AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
1119  bHasAnyRefOp = bHasListOp = true;
1120  }
1121  if( bHasAnyRefOp )
1122  {
1123  // add a tMemFunc token enclosing the entire reference subexpression
1124  sal_uInt16 nSubExprSize = GetSize() - nSubExprPos;
1125  InsertZeros( nSubExprPos, 3 );
1126  mxData->maTokVec[ nSubExprPos ] = GetTokenId( EXC_TOKID_MEMFUNC, EXC_TOKCLASS_REF );
1127  Overwrite( nSubExprPos + 1, nSubExprSize );
1128  // update the operand/operator stack (set the list expression as operand of the tMemFunc)
1129  XclExpOperandListRef xOperands = std::make_shared<XclExpOperandList>();
1130  xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_VAL, false );
1131  PushOperatorPos( nSubExprPos, xOperands );
1132  }
1133  // #i86439# enclose list operator into parentheses, e.g. Calc's =AREAS(A1~A2) to Excel's =AREAS((A1;A2))
1134  if( bHasListOp && !bInParentheses )
1135  AppendParenToken();
1136  return aTokData;
1137 }
1138 
1139 XclExpScToken XclExpFmlaCompImpl::IntersectTerm( XclExpScToken aTokData, bool& rbHasRefOp )
1140 {
1141  aTokData = RangeTerm( aTokData, rbHasRefOp );
1142  while( mxData->mbOk )
1143  {
1144  sal_uInt8 nOpTokenId = lclGetIntersectTokenId( aTokData.GetOpCode() );
1145  if (nOpTokenId ==EXC_TOKID_NONE)
1146  break;
1147  sal_uInt8 nSpaces = aTokData.mnSpaces;
1148  aTokData = RangeTerm( GetNextToken(), rbHasRefOp );
1149  AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
1150  rbHasRefOp = true;
1151  }
1152  return aTokData;
1153 }
1154 
1155 XclExpScToken XclExpFmlaCompImpl::RangeTerm( XclExpScToken aTokData, bool& rbHasRefOp )
1156 {
1157  aTokData = Factor( aTokData );
1158  while( mxData->mbOk )
1159  {
1160  sal_uInt8 nOpTokenId = lclGetRangeTokenId( aTokData.GetOpCode() );
1161  if (nOpTokenId == EXC_TOKID_NONE)
1162  break;
1163  sal_uInt8 nSpaces = aTokData.mnSpaces;
1164  aTokData = Factor( GetNextToken() );
1165  AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
1166  rbHasRefOp = true;
1167  }
1168  return aTokData;
1169 }
1170 
1171 XclExpScToken XclExpFmlaCompImpl::Factor( XclExpScToken aTokData )
1172 {
1173  if( !mxData->mbOk || !aTokData.Is() ) return XclExpScToken();
1174 
1175  switch( aTokData.GetType() )
1176  {
1177  case svUnknown: mxData->mbOk = false; break;
1178  case svDouble: ProcessDouble( aTokData ); break;
1179  case svString: ProcessString( aTokData ); break;
1180  case svSingleRef: ProcessCellRef( aTokData ); break;
1181  case svDoubleRef: ProcessRangeRef( aTokData ); break;
1182  case svExternalSingleRef: ProcessExternalCellRef( aTokData ); break;
1183  case svExternalDoubleRef: ProcessExternalRangeRef( aTokData ); break;
1184  case svExternalName: ProcessExternalName( aTokData ); break;
1185  case svMatrix: ProcessMatrix( aTokData ); break;
1186  case svExternal: ProcessExternal( aTokData ); break;
1187 
1188  default: switch( aTokData.GetOpCode() )
1189  {
1190  case ocNone: /* do nothing */ break;
1191  case ocMissing: ProcessMissing( aTokData ); break;
1192  case ocBad: ProcessBad( aTokData ); break;
1193  case ocOpen: ProcessParentheses( aTokData ); break;
1194  case ocName: ProcessDefinedName( aTokData ); break;
1195  case ocFalse:
1196  case ocTrue: ProcessBoolean( aTokData ); break;
1197  case ocDde: ProcessDdeLink( aTokData ); break;
1198  default: ProcessFunction( aTokData );
1199  }
1200  }
1201 
1202  return GetNextToken();
1203 }
1204 
1205 // formula structure ----------------------------------------------------------
1206 
1207 void XclExpFmlaCompImpl::ProcessDouble( const XclExpScToken& rTokData )
1208 {
1209  double fValue = rTokData.mpScToken->GetDouble();
1210  double fInt;
1211  double fFrac = modf( fValue, &fInt );
1212  if( (fFrac == 0.0) && (0.0 <= fInt) && (fInt <= 65535.0) )
1213  AppendIntToken( static_cast< sal_uInt16 >( fInt ), rTokData.mnSpaces );
1214  else
1215  AppendNumToken( fValue, rTokData.mnSpaces );
1216 }
1217 
1218 void XclExpFmlaCompImpl::ProcessString( const XclExpScToken& rTokData )
1219 {
1220  AppendOperandTokenId( EXC_TOKID_STR, rTokData.mnSpaces );
1221  Append( rTokData.mpScToken->GetString().getString() );
1222 }
1223 
1224 void XclExpFmlaCompImpl::ProcessMissing( const XclExpScToken& rTokData )
1225 {
1226  AppendMissingToken( rTokData.mnSpaces );
1227 }
1228 
1229 void XclExpFmlaCompImpl::ProcessBad( const XclExpScToken& rTokData )
1230 {
1231  AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
1232 }
1233 
1234 void XclExpFmlaCompImpl::ProcessParentheses( const XclExpScToken& rTokData )
1235 {
1236  XclExpScToken aTokData = Expression( GetNextToken(), true, false );
1237  mxData->mbOk = aTokData.GetOpCode() == ocClose;
1238  AppendParenToken( rTokData.mnSpaces, aTokData.mnSpaces );
1239 }
1240 
1241 void XclExpFmlaCompImpl::ProcessBoolean( const XclExpScToken& rTokData )
1242 {
1243  mxData->mbOk = GetNextToken().GetOpCode() == ocOpen;
1244  if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocClose;
1245  if( mxData->mbOk )
1246  AppendBoolToken( rTokData.GetOpCode() == ocTrue, rTokData.mnSpaces );
1247 }
1248 
1249 namespace {
1250 
1251 bool lclGetTokenString( OUString& rString, const XclExpScToken& rTokData )
1252 {
1253  bool bIsStr = (rTokData.GetType() == svString) && (rTokData.GetOpCode() == ocPush);
1254  if( bIsStr )
1255  rString = rTokData.mpScToken->GetString().getString();
1256  return bIsStr;
1257 }
1258 
1259 } // namespace
1260 
1261 void XclExpFmlaCompImpl::ProcessDdeLink( const XclExpScToken& rTokData )
1262 {
1263  OUString aApplic, aTopic, aItem;
1264 
1265  mxData->mbOk = GetNextToken().GetOpCode() == ocOpen;
1266  if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aApplic, GetNextToken() );
1267  if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocSep;
1268  if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aTopic, GetNextToken() );
1269  if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocSep;
1270  if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aItem, GetNextToken() );
1271  if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocClose;
1272  if( mxData->mbOk ) mxData->mbOk = !aApplic.isEmpty() && !aTopic.isEmpty() && !aItem.isEmpty();
1273  if( mxData->mbOk )
1274  {
1275  sal_uInt16 nExtSheet(0), nExtName(0);
1276  if( mxData->mpLinkMgr && mxData->mpLinkMgr->InsertDde( nExtSheet, nExtName, aApplic, aTopic, aItem ) )
1277  AppendNameXToken( nExtSheet, nExtName, rTokData.mnSpaces );
1278  else
1279  AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
1280  }
1281 }
1282 
1283 void XclExpFmlaCompImpl::ProcessExternal( const XclExpScToken& rTokData )
1284 {
1285  /* #i47228# Excel import generates svExternal/ocMacro tokens for invalid
1286  names and for external/invalid function calls. This function looks for
1287  the next token in the token array. If it is an opening parenthesis, the
1288  token is processed as external function call, otherwise as undefined name. */
1289  const FormulaToken* pNextScToken = PeekNextRawToken();
1290  if( !pNextScToken || (pNextScToken->GetOpCode() != ocOpen) )
1291  AppendMissingNameToken( rTokData.mpScToken->GetExternal(), rTokData.mnSpaces );
1292  else
1293  ProcessFunction( rTokData );
1294 }
1295 
1296 void XclExpFmlaCompImpl::ProcessMatrix( const XclExpScToken& rTokData )
1297 {
1298  const ScMatrix* pMatrix = rTokData.mpScToken->GetMatrix();
1299  if( pMatrix && mxData->mrCfg.mbAllowArrays )
1300  {
1301  SCSIZE nScCols, nScRows;
1302  pMatrix->GetDimensions( nScCols, nScRows );
1303  OSL_ENSURE( (nScCols > 0) && (nScRows > 0), "XclExpFmlaCompImpl::ProcessMatrix - invalid matrix size" );
1304  sal_uInt16 nCols = ::limit_cast< sal_uInt16 >( nScCols, 0, 256 );
1305  sal_uInt16 nRows = ::limit_cast< sal_uInt16 >( nScRows, 0, 1024 );
1306 
1307  // create the tArray token
1309  Append( static_cast< sal_uInt8 >( (meBiff == EXC_BIFF8) ? (nCols - 1) : nCols ) );
1310  Append( static_cast< sal_uInt16 >( (meBiff == EXC_BIFF8) ? (nRows - 1) : nRows ) );
1311  Append( static_cast< sal_uInt32 >( 0 ) );
1312 
1313  // create the extended data containing the array values
1314  AppendExt( static_cast< sal_uInt8 >( (meBiff == EXC_BIFF8) ? (nCols - 1) : nCols ) );
1315  AppendExt( static_cast< sal_uInt16 >( (meBiff == EXC_BIFF8) ? (nRows - 1) : nRows ) );
1316  for( SCSIZE nScRow = 0; nScRow < nScRows; ++nScRow )
1317  {
1318  for( SCSIZE nScCol = 0; nScCol < nScCols; ++nScCol )
1319  {
1320  ScMatrixValue nMatVal = pMatrix->Get( nScCol, nScRow );
1321  if( ScMatrix::IsValueType( nMatVal.nType ) ) // value, boolean, or error
1322  {
1323  FormulaError nErr;
1324  if( ScMatrix::IsBooleanType( nMatVal.nType ) )
1325  {
1327  AppendExt( static_cast< sal_uInt8 >( nMatVal.GetBoolean() ? 1 : 0 ) );
1328  AppendExt( 0, 7 );
1329  }
1330  else if( (nErr = nMatVal.GetError()) != FormulaError::NONE )
1331  {
1334  AppendExt( 0, 7 );
1335  }
1336  else
1337  {
1339  AppendExt( nMatVal.fVal );
1340  }
1341  }
1342  else // string or empty
1343  {
1344  const OUString aStr( nMatVal.GetString().getString());
1345  if( aStr.isEmpty() )
1346  {
1348  AppendExt( 0, 8 );
1349  }
1350  else
1351  {
1353  AppendExt( aStr );
1354  }
1355  }
1356  }
1357  }
1358  }
1359  else
1360  {
1361  // array in places that do not allow it (cond fmts, data validation)
1362  AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
1363  }
1364 }
1365 
1366 void XclExpFmlaCompImpl::ProcessFunction( const XclExpScToken& rTokData )
1367 {
1368  OpCode eOpCode = rTokData.GetOpCode();
1369  const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromOpCode( eOpCode );
1370 
1371  XclExpExtFuncData aExtFuncData;
1372 
1373  // no exportable function found - try to create an external macro call
1374  if( !pFuncInfo && (eOpCode >= SC_OPCODE_START_NO_PAR) )
1375  {
1376  const OUString& rFuncName = ScCompiler::GetNativeSymbol( eOpCode );
1377  if( !rFuncName.isEmpty() )
1378  {
1379  aExtFuncData.Set( rFuncName, true, false );
1380  pFuncInfo = maFuncProv.GetFuncInfoFromOpCode( ocMacro );
1381  }
1382  }
1383 
1384  mxData->mbOk = pFuncInfo != nullptr;
1385  if( !mxData->mbOk ) return;
1386 
1387  // internal functions equivalent to an existing add-in
1388  if( pFuncInfo->IsAddInEquivalent() )
1389  aExtFuncData.Set( pFuncInfo->GetAddInEquivalentFuncName(), true, false );
1390  // functions simulated by a macro call in file format
1391  else if( pFuncInfo->IsMacroFunc() )
1392  aExtFuncData.Set( pFuncInfo->GetMacroFuncName(), false, true );
1393 
1394  XclExpFuncData aFuncData( rTokData, *pFuncInfo, aExtFuncData );
1395  XclExpScToken aTokData;
1396 
1397  // preparations for special functions, before function processing starts
1398  PrepareFunction( aFuncData );
1399 
1400  enum { STATE_START, STATE_OPEN, STATE_PARAM, STATE_SEP, STATE_CLOSE, STATE_END }
1401  eState = STATE_START;
1402  while( eState != STATE_END ) switch( eState )
1403  {
1404  case STATE_START:
1405  mxData->mbOk = GetNextToken( aTokData ) && (aTokData.GetOpCode() == ocOpen);
1406  eState = mxData->mbOk ? STATE_OPEN : STATE_END;
1407  break;
1408  case STATE_OPEN:
1409  mxData->mbOk = GetNextToken( aTokData );
1410  eState = mxData->mbOk ? ((aTokData.GetOpCode() == ocClose) ? STATE_CLOSE : STATE_PARAM) : STATE_END;
1411  break;
1412  case STATE_PARAM:
1413  aTokData = ProcessParam( aTokData, aFuncData );
1414  switch( aTokData.GetOpCode() )
1415  {
1416  case ocSep: eState = STATE_SEP; break;
1417  case ocClose: eState = STATE_CLOSE; break;
1418  default: mxData->mbOk = false;
1419  }
1420  if( !mxData->mbOk ) eState = STATE_END;
1421  break;
1422  case STATE_SEP:
1423  mxData->mbOk = (aFuncData.GetParamCount() < EXC_FUNC_MAXPARAM) && GetNextToken( aTokData );
1424  eState = mxData->mbOk ? STATE_PARAM : STATE_END;
1425  break;
1426  case STATE_CLOSE:
1427  FinishFunction( aFuncData, aTokData.mnSpaces );
1428  eState = STATE_END;
1429  break;
1430  default:;
1431  }
1432 }
1433 
1434 void XclExpFmlaCompImpl::PrepareFunction( const XclExpFuncData& rFuncData )
1435 {
1436  // For OOXML these are not rewritten anymore.
1437  if (GetOutput() == EXC_OUTPUT_XML_2007)
1438  return;
1439 
1440  switch( rFuncData.GetOpCode() )
1441  {
1442  case ocCosecant: // simulate CSC(x) by (1/SIN(x))
1443  case ocSecant: // simulate SEC(x) by (1/COS(x))
1444  case ocCot: // simulate COT(x) by (1/TAN(x))
1445  case ocCosecantHyp: // simulate CSCH(x) by (1/SINH(x))
1446  case ocSecantHyp: // simulate SECH(x) by (1/COSH(x))
1447  case ocCotHyp: // simulate COTH(x) by (1/TANH(x))
1448  AppendIntToken( 1 );
1449  break;
1450  case ocArcCot: // simulate ACOT(x) by (PI/2-ATAN(x))
1451  AppendNumToken( F_PI2 );
1452  break;
1453  default:;
1454  }
1455 }
1456 
1457 void XclExpFmlaCompImpl::FinishFunction( XclExpFuncData& rFuncData, sal_uInt8 nCloseSpaces )
1458 {
1459  // append missing parameters required in Excel, may modify param count
1460  AppendTrailingParam( rFuncData );
1461 
1462  // check if parameter count fits into the limits of the function
1463  sal_uInt8 nParamCount = rFuncData.GetParamCount();
1464  if( (rFuncData.GetMinParamCount() <= nParamCount) && (nParamCount <= rFuncData.GetMaxParamCount()) )
1465  {
1466  // first put the tAttrSpace tokens, they must not be included in tAttrGoto handling
1468  AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, rFuncData.GetSpaces() );
1469 
1470  // add tAttrGoto tokens for IF or CHOOSE functions
1471  switch( rFuncData.GetOpCode() )
1472  {
1473  case ocIf:
1474  case ocChoose:
1475  AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );
1476  break;
1477  default:;
1478  }
1479 
1480  // put the tFunc or tFuncVar token (or another special token, e.g. tAttrSum)
1481  AppendFuncToken( rFuncData );
1482 
1483  // update volatile flag - is set if at least one used function is volatile
1484  mxData->mbVolatile |= rFuncData.IsVolatile();
1485 
1486  // update jump tokens for specific functions, add additional tokens
1487  switch( rFuncData.GetOpCode() )
1488  {
1489  case ocIf:
1490  FinishIfFunction( rFuncData );
1491  break;
1492  case ocChoose:
1493  FinishChooseFunction( rFuncData );
1494  break;
1495 
1496  case ocCosecant: // simulate CSC(x) by (1/SIN(x))
1497  case ocSecant: // simulate SEC(x) by (1/COS(x))
1498  case ocCot: // simulate COT(x) by (1/TAN(x))
1499  case ocCosecantHyp: // simulate CSCH(x) by (1/SINH(x))
1500  case ocSecantHyp: // simulate SECH(x) by (1/COSH(x))
1501  case ocCotHyp: // simulate COTH(x) by (1/TANH(x))
1502  // For OOXML not rewritten anymore.
1503  if (GetOutput() != EXC_OUTPUT_XML_2007)
1504  {
1506  AppendParenToken();
1507  }
1508  break;
1509  case ocArcCot: // simulate ACOT(x) by (PI/2-ATAN(x))
1510  // For OOXML not rewritten anymore.
1511  if (GetOutput() != EXC_OUTPUT_XML_2007)
1512  {
1514  AppendParenToken();
1515  }
1516  break;
1517 
1518  default:;
1519  }
1520  }
1521  else
1522  mxData->mbOk = false;
1523 }
1524 
1525 void XclExpFmlaCompImpl::FinishIfFunction( XclExpFuncData& rFuncData )
1526 {
1527  sal_uInt16 nParamCount = rFuncData.GetParamCount();
1528  OSL_ENSURE( (nParamCount == 2) || (nParamCount == 3), "XclExpFmlaCompImpl::FinishIfFunction - wrong parameter count" );
1529  const ScfUInt16Vec& rAttrPos = rFuncData.GetAttrPosVec();
1530  OSL_ENSURE( nParamCount == rAttrPos.size(), "XclExpFmlaCompImpl::FinishIfFunction - wrong number of tAttr tokens" );
1531  // update tAttrIf token following the condition parameter
1532  Overwrite( rAttrPos[ 0 ] + 2, static_cast< sal_uInt16 >( rAttrPos[ 1 ] - rAttrPos[ 0 ] ) );
1533  // update the tAttrGoto tokens following true and false parameters
1534  UpdateAttrGoto( rAttrPos[ 1 ] );
1535  if( nParamCount == 3 )
1536  UpdateAttrGoto( rAttrPos[ 2 ] );
1537 }
1538 
1539 void XclExpFmlaCompImpl::FinishChooseFunction( XclExpFuncData& rFuncData )
1540 {
1541  sal_uInt16 nParamCount = rFuncData.GetParamCount();
1542  ScfUInt16Vec& rAttrPos = rFuncData.GetAttrPosVec();
1543  OSL_ENSURE( nParamCount == rAttrPos.size(), "XclExpFmlaCompImpl::FinishChooseFunction - wrong number of tAttr tokens" );
1544  // number of choices is parameter count minus 1
1545  sal_uInt16 nChoices = nParamCount - 1;
1546  // tAttrChoose token contains number of choices
1547  Overwrite( rAttrPos[ 0 ] + 2, nChoices );
1548  // cache position of the jump table (follows number of choices in tAttrChoose token)
1549  sal_uInt16 nJumpArrPos = rAttrPos[ 0 ] + 4;
1550  // size of jump table: number of choices, plus 1 for error position
1551  sal_uInt16 nJumpArrSize = 2 * (nChoices + 1);
1552  // insert the jump table into the tAttrChoose token
1553  InsertZeros( nJumpArrPos, nJumpArrSize );
1554  // update positions of tAttrGoto tokens after jump table insertion
1555  sal_uInt16 nIdx;
1556  for( nIdx = 1; nIdx < nParamCount; ++nIdx )
1557  rAttrPos[ nIdx ] = rAttrPos[ nIdx ] + nJumpArrSize;
1558  // update the tAttrGoto tokens (they contain a value one-less to real distance)
1559  for( nIdx = 1; nIdx < nParamCount; ++nIdx )
1560  UpdateAttrGoto( rAttrPos[ nIdx ] );
1561  // update the distances in the jump table
1562  Overwrite( nJumpArrPos, nJumpArrSize );
1563  for( nIdx = 1; nIdx < nParamCount; ++nIdx )
1564  Overwrite( nJumpArrPos + 2 * nIdx, static_cast< sal_uInt16 >( rAttrPos[ nIdx ] + 4 - nJumpArrPos ) );
1565 }
1566 
1567 XclExpScToken XclExpFmlaCompImpl::ProcessParam( XclExpScToken aTokData, XclExpFuncData& rFuncData )
1568 {
1569  if( rFuncData.IsCalcOnlyParam() )
1570  {
1571  // skip Calc-only parameter, stop at next ocClose or ocSep
1572  aTokData = SkipExpression( aTokData, true );
1573  rFuncData.IncParamInfoIdx();
1574  }
1575  else
1576  {
1577  // insert Excel-only parameters, modifies param count and class in rFuncData
1578  while( rFuncData.IsExcelOnlyParam() )
1579  AppendDefaultParam( rFuncData );
1580 
1581  // process the parameter, stop at next ocClose or ocSep
1582  PrepareParam( rFuncData );
1583  /* #i37355# insert tMissArg token for missing parameters --
1584  Excel import filter adds ocMissing token (handled in Factor()),
1585  but Calc itself does not do this if a new formula is entered. */
1586  switch( aTokData.GetOpCode() )
1587  {
1588  case ocSep:
1589  case ocClose: AppendMissingToken(); break; // empty parameter
1590  default: aTokData = Expression( aTokData, false, true );
1591  }
1592  // finalize the parameter and add special tokens, e.g. for IF or CHOOSE parameters
1593  if( mxData->mbOk ) FinishParam( rFuncData );
1594  }
1595  return aTokData;
1596 }
1597 
1598 void XclExpFmlaCompImpl::PrepareParam( XclExpFuncData& rFuncData )
1599 {
1600  // index of this parameter is equal to number of already finished parameters
1601  sal_uInt8 nParamIdx = rFuncData.GetParamCount();
1602 
1603  switch( rFuncData.GetOpCode() )
1604  {
1605  case ocIf:
1606  switch( nParamIdx )
1607  {
1608  // add a tAttrIf token before true-parameter (second parameter)
1609  case 1: AppendJumpToken( rFuncData, EXC_TOK_ATTR_IF ); break;
1610  // add a tAttrGoto token before false-parameter (third parameter)
1611  case 2: AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO ); break;
1612  }
1613  break;
1614 
1615  case ocChoose:
1616  switch( nParamIdx )
1617  {
1618  // do nothing for first parameter
1619  case 0: break;
1620  // add a tAttrChoose token before first value parameter (second parameter)
1621  case 1: AppendJumpToken( rFuncData, EXC_TOK_ATTR_CHOOSE ); break;
1622  // add a tAttrGoto token before other value parameters
1623  default: AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );
1624  }
1625  break;
1626 
1627  case ocArcCotHyp: // simulate ACOTH(x) by ATANH(1/(x))
1628  if( nParamIdx == 0 )
1629  AppendIntToken( 1 );
1630  break;
1631  default:;
1632  }
1633 }
1634 
1635 void XclExpFmlaCompImpl::FinishParam( XclExpFuncData& rFuncData )
1636 {
1637  // increase parameter count, update operand stack
1638  rFuncData.FinishParam( PopOperandPos() );
1639 
1640  // append more tokens for parameters of some special functions
1641  sal_uInt8 nParamIdx = rFuncData.GetParamCount() - 1;
1642  switch( rFuncData.GetOpCode() )
1643  {
1644  case ocArcCotHyp: // simulate ACOTH(x) by ATANH(1/(x))
1645  if( nParamIdx == 0 )
1646  {
1647  AppendParenToken();
1649  }
1650  break;
1651  default:;
1652  }
1653 }
1654 
1655 void XclExpFmlaCompImpl::AppendDefaultParam( XclExpFuncData& rFuncData )
1656 {
1657  // prepare parameters of some special functions
1658  PrepareParam( rFuncData );
1659 
1660  switch( rFuncData.GetOpCode() )
1661  {
1662  case ocExternal:
1663  AppendAddInCallToken( rFuncData.GetExtFuncData() );
1664  break;
1665  case ocEuroConvert:
1666  AppendEuroToolCallToken( rFuncData.GetExtFuncData() );
1667  break;
1668  case ocMacro:
1669  // Do not write the OOXML <definedName> element.
1670  if (GetOutput() == EXC_OUTPUT_XML_2007)
1671  AppendNameToken( 0 ); // dummy to keep parameter count valid
1672  else
1673  AppendMacroCallToken( rFuncData.GetExtFuncData() );
1674  break;
1675  default:
1676  {
1677  if( rFuncData.IsAddInEquivalent() )
1678  {
1679  AppendAddInCallToken( rFuncData.GetExtFuncData() );
1680  }
1681  else if( rFuncData.IsMacroFunc() )
1682  {
1683  // Do not write the OOXML <definedName> element for new _xlfn.
1684  // prefixed functions.
1685  if (GetOutput() == EXC_OUTPUT_XML_2007)
1686  AppendNameToken( 0 ); // dummy to keep parameter count valid
1687  else
1688  AppendMacroCallToken( rFuncData.GetExtFuncData() );
1689  }
1690  else
1691  {
1692  SAL_WARN( "sc.filter", "XclExpFmlaCompImpl::AppendDefaultParam - unknown opcode" );
1693  AppendMissingToken(); // to keep parameter count valid
1694  }
1695  }
1696  }
1697 
1698  // update parameter count, add special parameter tokens
1699  FinishParam( rFuncData );
1700 }
1701 
1702 void XclExpFmlaCompImpl::AppendTrailingParam( XclExpFuncData& rFuncData )
1703 {
1704  sal_uInt8 nParamCount = rFuncData.GetParamCount();
1705  switch( rFuncData.GetOpCode() )
1706  {
1707  case ocIf:
1708  if( nParamCount == 1 )
1709  {
1710  // Excel needs at least two parameters in IF function
1711  PrepareParam( rFuncData );
1712  AppendBoolToken( true );
1713  FinishParam( rFuncData );
1714  }
1715  break;
1716 
1717  case ocRound:
1718  case ocRoundUp:
1719  case ocRoundDown:
1720  if( nParamCount == 1 )
1721  {
1722  // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
1723  PrepareParam( rFuncData );
1724  AppendIntToken( 0 );
1725  FinishParam( rFuncData );
1726  }
1727  break;
1728 
1729  case ocIndex:
1730  if( nParamCount == 1 )
1731  {
1732  // INDEX function needs at least 2 parameters in Excel
1733  PrepareParam( rFuncData );
1735  FinishParam( rFuncData );
1736  }
1737  break;
1738 
1739  case ocExternal:
1740  case ocMacro:
1741  // external or macro call without parameters needs the external name reference
1742  if( nParamCount == 0 )
1743  AppendDefaultParam( rFuncData );
1744  break;
1745 
1746  case ocGammaDist:
1747  if( nParamCount == 3 )
1748  {
1749  // GAMMADIST function needs 4 parameters in Excel
1750  PrepareParam( rFuncData );
1751  AppendIntToken( 1 );
1752  FinishParam( rFuncData );
1753  }
1754  break;
1755 
1756  case ocPoissonDist:
1757  if( nParamCount == 2 )
1758  {
1759  // POISSON function needs 3 parameters in Excel
1760  PrepareParam( rFuncData );
1761  AppendIntToken( 1 );
1762  FinishParam( rFuncData );
1763  }
1764  break;
1765 
1766  case ocNormDist:
1767  if( nParamCount == 3 )
1768  {
1769  // NORMDIST function needs 4 parameters in Excel
1770  PrepareParam( rFuncData );
1771  AppendBoolToken( true );
1772  FinishParam( rFuncData );
1773  }
1774  break;
1775 
1776  case ocLogNormDist:
1777  case ocLogInv:
1778  switch( nParamCount )
1779  {
1780  // LOGNORMDIST function needs 3 parameters in Excel
1781  case 1:
1782  PrepareParam( rFuncData );
1783  AppendIntToken( 0 );
1784  FinishParam( rFuncData );
1785  [[fallthrough]]; // add next default parameter
1786  case 2:
1787  PrepareParam( rFuncData );
1788  AppendIntToken( 1 );
1789  FinishParam( rFuncData );
1790  break;
1791  default:;
1792  }
1793 
1794  break;
1795 
1796  default:
1797  // #i108420# function without parameters stored as macro call needs the external name reference
1798  if( (nParamCount == 0) && rFuncData.IsMacroFunc() )
1799  AppendDefaultParam( rFuncData );
1800 
1801  }
1802 }
1803 
1804 // reference handling ---------------------------------------------------------
1805 
1806 namespace {
1807 
1808 bool lclIsRefRel2D( const ScSingleRefData& rRefData )
1809 {
1810  return rRefData.IsColRel() || rRefData.IsRowRel();
1811 }
1812 
1813 bool lclIsRefDel2D( const ScSingleRefData& rRefData )
1814 {
1815  return rRefData.IsColDeleted() || rRefData.IsRowDeleted();
1816 }
1817 
1818 bool lclIsRefRel2D( const ScComplexRefData& rRefData )
1819 {
1820  return lclIsRefRel2D( rRefData.Ref1 ) || lclIsRefRel2D( rRefData.Ref2 );
1821 }
1822 
1823 bool lclIsRefDel2D( const ScComplexRefData& rRefData )
1824 {
1825  return lclIsRefDel2D( rRefData.Ref1 ) || lclIsRefDel2D( rRefData.Ref2 );
1826 }
1827 
1828 } // namespace
1829 
1831 {
1832  if (rRefData.IsTabDeleted())
1833  return SCTAB_INVALID;
1834 
1835  if (!rRefData.IsTabRel())
1836  // absolute address
1837  return rRefData.Tab();
1838 
1839  if (!mxData->mpScBasePos)
1840  return SCTAB_INVALID;
1841 
1842  return rRefData.toAbs(&GetRoot().GetDoc(), *mxData->mpScBasePos).Tab();
1843 }
1844 
1845 bool XclExpFmlaCompImpl::IsRef2D( const ScSingleRefData& rRefData, bool bCheck3DFlag ) const
1846 {
1847  /* rRefData.IsFlag3D() determines if sheet name is always visible, even on
1848  the own sheet. If 3D references are allowed, the passed reference does
1849  not count as 2D reference. */
1850 
1851  // conditional formatting does not allow 3D refs in xls
1852  if (mxData && mxData->mrCfg.meType == EXC_FMLATYPE_CONDFMT)
1853  return true;
1854 
1855  if (bCheck3DFlag && rRefData.IsFlag3D())
1856  return false;
1857 
1858  if (rRefData.IsTabDeleted())
1859  return false;
1860 
1861  if (rRefData.IsTabRel())
1862  return rRefData.Tab() == 0;
1863  else
1864  return rRefData.Tab() == GetCurrScTab();
1865 }
1866 
1867 bool XclExpFmlaCompImpl::IsRef2D( const ScComplexRefData& rRefData, bool bCheck3DFlag ) const
1868 {
1869  return IsRef2D(rRefData.Ref1, bCheck3DFlag) && IsRef2D(rRefData.Ref2, bCheck3DFlag);
1870 }
1871 
1873  ScSingleRefData& rRefData, XclAddress& rXclPos,
1874  bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow ) const
1875 {
1876  if( mxData->mpScBasePos )
1877  {
1878  // *** reference position exists (cell, matrix) - convert to absolute ***
1879  ScAddress aAbs = rRefData.toAbs(&GetRoot().GetDoc(), *mxData->mpScBasePos);
1880 
1881  // convert column index
1882  if (bTruncMaxCol && (aAbs.Col() == mnMaxScCol))
1883  aAbs.SetCol(mnMaxAbsCol);
1884  else if ((aAbs.Col() < 0) || (aAbs.Col() > mnMaxAbsCol))
1885  rRefData.SetColDeleted(true);
1886  rXclPos.mnCol = static_cast<sal_uInt16>(aAbs.Col()) & mnMaxColMask;
1887 
1888  // convert row index
1889  if (bTruncMaxRow && (aAbs.Row() == mnMaxScRow))
1890  aAbs.SetRow(mnMaxAbsRow);
1891  else if ((aAbs.Row() < 0) || (aAbs.Row() > mnMaxAbsRow))
1892  rRefData.SetRowDeleted(true);
1893  rXclPos.mnRow = static_cast<sal_uInt32>(aAbs.Row()) & mnMaxRowMask;
1894 
1895  // Update the reference.
1896  rRefData.SetAddress(GetRoot().GetDoc().GetSheetLimits(), aAbs, *mxData->mpScBasePos);
1897  }
1898  else
1899  {
1900  // *** no reference position (shared, names, condfmt) - use relative values ***
1901 
1902  // convert column index (2-step-cast ScsCOL->sal_Int16->sal_uInt16 to get all bits correctly)
1903  sal_Int16 nXclRelCol = static_cast<sal_Int16>(rRefData.Col());
1904  rXclPos.mnCol = static_cast< sal_uInt16 >( nXclRelCol ) & mnMaxColMask;
1905 
1906  // convert row index (2-step-cast ScsROW->sal_Int32->sal_uInt32 to get all bits correctly)
1907  sal_Int32 nXclRelRow = static_cast<sal_Int32>(rRefData.Row());
1908  rXclPos.mnRow = static_cast< sal_uInt32 >( nXclRelRow ) & mnMaxRowMask;
1909  }
1910 
1911  // flags for relative column and row
1912  if( bNatLangRef )
1913  {
1914  OSL_ENSURE( meBiff == EXC_BIFF8, "XclExpFmlaCompImpl::ConvertRefData - NLRs only for BIFF8" );
1915  // Calc does not support absolute reference mode in natural language references
1916  ::set_flag( rXclPos.mnCol, EXC_TOK_NLR_REL );
1917  }
1918  else
1919  {
1920  sal_uInt16 rnRelRow = rXclPos.mnRow;
1921  sal_uInt16& rnRelField = (meBiff <= EXC_BIFF5) ? rnRelRow : rXclPos.mnCol;
1922  ::set_flag( rnRelField, EXC_TOK_REF_COLREL, rRefData.IsColRel() );
1923  ::set_flag( rnRelField, EXC_TOK_REF_ROWREL, rRefData.IsRowRel() );
1924  }
1925 }
1926 
1928  ScComplexRefData& rRefData, XclRange& rXclRange, bool bNatLangRef ) const
1929 {
1930  // convert start and end of the range
1931  ConvertRefData( rRefData.Ref1, rXclRange.maFirst, bNatLangRef, false, false );
1932  bool bTruncMaxCol = !rRefData.Ref1.IsColDeleted() && (rXclRange.maFirst.mnCol == 0);
1933  bool bTruncMaxRow = !rRefData.Ref1.IsRowDeleted() && (rXclRange.maFirst.mnRow == 0);
1934  ConvertRefData( rRefData.Ref2, rXclRange.maLast, bNatLangRef, bTruncMaxCol, bTruncMaxRow );
1935 }
1936 
1938 {
1939  if( mxData->mpRefLog )
1940  {
1941  mxData->mpRefLog->emplace_back();
1942  return &mxData->mpRefLog->back();
1943  }
1944  return nullptr;
1945 }
1946 
1947 void XclExpFmlaCompImpl::ProcessCellRef( const XclExpScToken& rTokData )
1948 {
1949  // get the Excel address components, adjust internal data in aRefData
1950  bool bNatLangRef = (meBiff == EXC_BIFF8) && mxData->mpScBasePos && (rTokData.GetOpCode() == ocColRowName);
1951  ScSingleRefData aRefData = *rTokData.mpScToken->GetSingleRef();
1953  ConvertRefData( aRefData, aXclPos, bNatLangRef, false, false );
1954 
1955  if( bNatLangRef )
1956  {
1957  OSL_ENSURE( aRefData.IsColRel() != aRefData.IsRowRel(),
1958  "XclExpFmlaCompImpl::ProcessCellRef - broken natural language reference" );
1959  // create tNlr token for natural language reference
1960  sal_uInt8 nSubId = aRefData.IsColRel() ? EXC_TOK_NLR_COLV : EXC_TOK_NLR_ROWV;
1961  AppendOperandTokenId( EXC_TOKID_NLR, rTokData.mnSpaces );
1962  Append( nSubId );
1963  AppendAddress( aXclPos );
1964  }
1965  else
1966  {
1967  // store external cell contents in CRN records
1968  if( mxData->mrCfg.mbFromCell && mxData->mpLinkMgr && mxData->mpScBasePos )
1969  mxData->mpLinkMgr->StoreCell(aRefData, *mxData->mpScBasePos);
1970 
1971  // create the tRef, tRefErr, tRefN, tRef3d, or tRefErr3d token
1972  if (!mxData->mrCfg.mb3DRefOnly && IsRef2D(aRefData, mxData->mpLinkMgr != nullptr))
1973  {
1974  // 2D reference (not in defined names, but allowed in range lists)
1975  sal_uInt8 nBaseId = (!mxData->mpScBasePos && lclIsRefRel2D( aRefData )) ? EXC_TOKID_REFN :
1976  (lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR : EXC_TOKID_REF);
1977  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
1978  AppendAddress( aXclPos );
1979  }
1980  else if( mxData->mpLinkMgr ) // 3D reference
1981  {
1982  // 1-based EXTERNSHEET index and 0-based Excel sheet index
1983  sal_uInt16 nExtSheet, nXclTab;
1984  mxData->mpLinkMgr->FindExtSheet( nExtSheet, nXclTab, GetScTab( aRefData ), GetNewRefLogEntry() );
1985  // write the token
1986  sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
1987  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
1988  Append( nExtSheet );
1989  if( meBiff <= EXC_BIFF5 )
1990  {
1991  Append( 0, 8 );
1992  Append( nXclTab );
1993  Append( nXclTab );
1994  }
1995  AppendAddress( aXclPos );
1996  }
1997  else
1998  {
1999  // 3D ref in cond. format, or 2D ref in name
2000  AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
2001  }
2002  }
2003 }
2004 
2005 void XclExpFmlaCompImpl::ProcessRangeRef( const XclExpScToken& rTokData )
2006 {
2007  // get the Excel address components, adjust internal data in aRefData
2008  ScComplexRefData aRefData = *rTokData.mpScToken->GetDoubleRef();
2009  XclRange aXclRange( ScAddress::UNINITIALIZED );
2010  ConvertRefData( aRefData, aXclRange, false );
2011 
2012  // store external cell contents in CRN records
2013  if( mxData->mrCfg.mbFromCell && mxData->mpLinkMgr && mxData->mpScBasePos )
2014  mxData->mpLinkMgr->StoreCellRange(aRefData, *mxData->mpScBasePos);
2015 
2016  // create the tArea, tAreaErr, tAreaN, tArea3d, or tAreaErr3d token
2017  if (!mxData->mrCfg.mb3DRefOnly && IsRef2D(aRefData, mxData->mpLinkMgr != nullptr))
2018  {
2019  // 2D reference (not in name formulas, but allowed in range lists)
2020  sal_uInt8 nBaseId = (!mxData->mpScBasePos && lclIsRefRel2D( aRefData )) ? EXC_TOKID_AREAN :
2021  (lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR : EXC_TOKID_AREA);
2022  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
2023  AppendRange( aXclRange );
2024  }
2025  else if( mxData->mpLinkMgr ) // 3D reference
2026  {
2027  // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
2028  sal_uInt16 nExtSheet, nFirstXclTab, nLastXclTab;
2029  mxData->mpLinkMgr->FindExtSheet( nExtSheet, nFirstXclTab, nLastXclTab,
2030  GetScTab( aRefData.Ref1 ), GetScTab( aRefData.Ref2 ), GetNewRefLogEntry() );
2031  // write the token
2032  sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
2033  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
2034  Append( nExtSheet );
2035  if( meBiff <= EXC_BIFF5 )
2036  {
2037  Append( 0, 8 );
2038  Append( nFirstXclTab );
2039  Append( nLastXclTab );
2040  }
2041  AppendRange( aXclRange );
2042  }
2043  else
2044  {
2045  // 3D ref in cond. format, or 2D ref in name
2046  AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
2047  }
2048 }
2049 
2050 void XclExpFmlaCompImpl::ProcessExternalCellRef( const XclExpScToken& rTokData )
2051 {
2052  if( mxData->mpLinkMgr )
2053  {
2054  // get the Excel address components, adjust internal data in aRefData
2055  ScSingleRefData aRefData = *rTokData.mpScToken->GetSingleRef();
2057  ConvertRefData( aRefData, aXclPos, false, false, false );
2058 
2059  // store external cell contents in CRN records
2060  sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
2061  OUString aTabName = rTokData.mpScToken->GetString().getString();
2062  if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos )
2063  mxData->mpLinkMgr->StoreCell(nFileId, aTabName, aRefData.toAbs(&GetRoot().GetDoc(), *mxData->mpScBasePos));
2064 
2065  // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
2066  sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
2067  mxData->mpLinkMgr->FindExtSheet( nFileId, aTabName, 1, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry() );
2068  // write the token
2069  sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
2070  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
2071  Append( nExtSheet );
2072  if( meBiff <= EXC_BIFF5 )
2073  {
2074  Append( 0, 8 );
2075  Append( nFirstSBTab );
2076  Append( nLastSBTab );
2077  }
2078  AppendAddress( aXclPos );
2079  }
2080  else
2081  {
2082  AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
2083  }
2084 }
2085 
2086 void XclExpFmlaCompImpl::ProcessExternalRangeRef( const XclExpScToken& rTokData )
2087 {
2088  if( mxData->mpLinkMgr )
2089  {
2090  // get the Excel address components, adjust internal data in aRefData
2091  ScComplexRefData aRefData = *rTokData.mpScToken->GetDoubleRef();
2092  XclRange aXclRange( ScAddress::UNINITIALIZED );
2093  ConvertRefData( aRefData, aXclRange, false );
2094 
2095  // store external cell contents in CRN records
2096  sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
2097  OUString aTabName = rTokData.mpScToken->GetString().getString();
2098  if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos )
2099  mxData->mpLinkMgr->StoreCellRange(nFileId, aTabName, aRefData.toAbs(&GetRoot().GetDoc(), *mxData->mpScBasePos));
2100 
2101  // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
2102  sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
2103  sal_uInt16 nTabSpan = static_cast<sal_uInt16>(aRefData.Ref2.Tab() - aRefData.Ref1.Tab() + 1);
2104  mxData->mpLinkMgr->FindExtSheet(
2105  nFileId, aTabName, nTabSpan, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry());
2106  // write the token
2107  sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
2108  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
2109  Append( nExtSheet );
2110  if( meBiff <= EXC_BIFF5 )
2111  {
2112  Append( 0, 8 );
2113  Append( nFirstSBTab );
2114  Append( nLastSBTab );
2115  }
2116  AppendRange( aXclRange );
2117  }
2118  else
2119  {
2120  AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
2121  }
2122 }
2123 
2124 void XclExpFmlaCompImpl::ProcessDefinedName( const XclExpScToken& rTokData )
2125 {
2126  sal_Int16 nSheet = rTokData.mpScToken->GetSheet();
2127  SCTAB nTab = (nSheet < 0 ? SCTAB_GLOBAL : nSheet);
2128 
2129  XclExpNameManager& rNameMgr = GetNameManager();
2130  sal_uInt16 nNameIdx = rNameMgr.InsertName(nTab, rTokData.mpScToken->GetIndex(), GetCurrScTab());
2131  if( nNameIdx != 0 )
2132  {
2133  // global names always with tName token, local names dependent on config
2134  SCTAB nScTab = rNameMgr.GetScTab( nNameIdx );
2135  if( (nScTab == SCTAB_GLOBAL) || (!mxData->mrCfg.mb3DRefOnly && (nScTab == GetCurrScTab())) )
2136  {
2137  AppendNameToken( nNameIdx, rTokData.mnSpaces );
2138  }
2139  else if( mxData->mpLinkMgr )
2140  {
2141  // use the same special EXTERNNAME to refer to any local name
2142  sal_uInt16 nExtSheet = mxData->mpLinkMgr->FindExtSheet( EXC_EXTSH_OWNDOC );
2143  AppendNameXToken( nExtSheet, nNameIdx, rTokData.mnSpaces );
2144  }
2145  else
2146  AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
2147  // volatile names (containing volatile functions)
2148  mxData->mbVolatile |= rNameMgr.IsVolatile( nNameIdx );
2149  }
2150  else
2151  AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
2152 }
2153 
2154 void XclExpFmlaCompImpl::ProcessExternalName( const XclExpScToken& rTokData )
2155 {
2156  if( mxData->mpLinkMgr )
2157  {
2159  sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
2160  OUString aName = rTokData.mpScToken->GetString().getString();
2161  ScExternalRefCache::TokenArrayRef xArray = rExtRefMgr.getRangeNameTokens( nFileId, aName );
2162  if( xArray )
2163  {
2164  // store external cell contents in CRN records
2165  if( mxData->mpScBasePos )
2166  {
2167  FormulaTokenArrayPlainIterator aIter(*xArray);
2168  for( FormulaToken* pScToken = aIter.First(); pScToken; pScToken = aIter.Next() )
2169  {
2170  if( pScToken->IsExternalRef() )
2171  {
2172  switch( pScToken->GetType() )
2173  {
2174  case svExternalSingleRef:
2175  {
2176  ScSingleRefData aRefData = *pScToken->GetSingleRef();
2177  mxData->mpLinkMgr->StoreCell(
2178  nFileId, pScToken->GetString().getString(), aRefData.toAbs(&GetRoot().GetDoc(), *mxData->mpScBasePos));
2179  }
2180  break;
2181  case svExternalDoubleRef:
2182  {
2183  ScComplexRefData aRefData = *pScToken->GetDoubleRef();
2184  mxData->mpLinkMgr->StoreCellRange(
2185  nFileId, pScToken->GetString().getString(), aRefData.toAbs(&GetRoot().GetDoc(), *mxData->mpScBasePos));
2186  }
2187  break;
2188  default:
2189  ; // nothing, avoid compiler warning
2190  }
2191  }
2192  }
2193  }
2194 
2195  // insert the new external name and create the tNameX token
2196  sal_uInt16 nExtSheet = 0, nExtName = 0;
2197  const OUString* pFile = rExtRefMgr.getExternalFileName( nFileId );
2198  if( pFile && mxData->mpLinkMgr->InsertExtName( nExtSheet, nExtName, *pFile, aName, xArray ) )
2199  {
2200  AppendNameXToken( nExtSheet, nExtName, rTokData.mnSpaces );
2201  return;
2202  }
2203  }
2204  }
2205 
2206  // on any error: create a #NAME? error
2207  AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
2208 }
2209 
2210 // token vector ---------------------------------------------------------------
2211 
2212 void XclExpFmlaCompImpl::PushOperandPos( sal_uInt16 nTokPos )
2213 {
2214  mxData->maOpPosStack.push_back( nTokPos );
2215 }
2216 
2217 void XclExpFmlaCompImpl::PushOperatorPos( sal_uInt16 nTokPos, const XclExpOperandListRef& rxOperands )
2218 {
2219  PushOperandPos( nTokPos );
2220  OSL_ENSURE( rxOperands, "XclExpFmlaCompImpl::AppendOperatorTokenId - missing operand list" );
2221  if( mxData->maOpListVec.size() <= nTokPos )
2222  mxData->maOpListVec.resize( nTokPos + 1, XclExpOperandListRef() );
2223  mxData->maOpListVec[ nTokPos ] = rxOperands;
2224 }
2225 
2227 {
2228  OSL_ENSURE( !mxData->mbOk || !mxData->maOpPosStack.empty(), "XclExpFmlaCompImpl::PopOperandPos - token stack broken" );
2229  mxData->mbOk &= !mxData->maOpPosStack.empty();
2230  if( mxData->mbOk )
2231  {
2232  sal_uInt16 nTokPos = mxData->maOpPosStack.back();
2233  mxData->maOpPosStack.pop_back();
2234  return nTokPos;
2235  }
2236  return 0;
2237 }
2238 
2239 namespace {
2240 
2241 void lclAppend( ScfUInt8Vec& orVector, sal_uInt16 nData )
2242 {
2243  orVector.resize( orVector.size() + 2 );
2244  ShortToSVBT16( nData, &*(orVector.end() - 2) );
2245 }
2246 
2247 void lclAppend( ScfUInt8Vec& orVector, sal_uInt32 nData )
2248 {
2249  orVector.resize( orVector.size() + 4 );
2250  UInt32ToSVBT32( nData, &*(orVector.end() - 4) );
2251 }
2252 
2253 void lclAppend( ScfUInt8Vec& orVector, double fData )
2254 {
2255  orVector.resize( orVector.size() + 8 );
2256  DoubleToSVBT64( fData, &*(orVector.end() - 8) );
2257 }
2258 
2259 void lclAppend( ScfUInt8Vec& orVector, const XclExpRoot& rRoot, const OUString& rString, XclStrFlags nStrFlags )
2260 {
2261  XclExpStringRef xXclStr = XclExpStringHelper::CreateString( rRoot, rString, nStrFlags, EXC_TOK_STR_MAXLEN );
2262  size_t nSize = orVector.size();
2263  orVector.resize( nSize + xXclStr->GetSize() );
2264  xXclStr->WriteToMem( &orVector[ nSize ] );
2265 }
2266 
2267 } // namespace
2268 
2270 {
2271  mxData->maTokVec.push_back( nData );
2272 }
2273 
2274 void XclExpFmlaCompImpl::Append( sal_uInt8 nData, size_t nCount )
2275 {
2276  mxData->maTokVec.resize( mxData->maTokVec.size() + nCount, nData );
2277 }
2278 
2279 void XclExpFmlaCompImpl::Append( sal_uInt16 nData )
2280 {
2281  lclAppend( mxData->maTokVec, nData );
2282 }
2283 
2284 void XclExpFmlaCompImpl::Append( sal_uInt32 nData )
2285 {
2286  lclAppend( mxData->maTokVec, nData );
2287 }
2288 
2289 void XclExpFmlaCompImpl::Append( double fData )
2290 {
2291  lclAppend( mxData->maTokVec, fData );
2292 }
2293 
2294 void XclExpFmlaCompImpl::Append( const OUString& rString )
2295 {
2296  lclAppend( mxData->maTokVec, GetRoot(), rString, XclStrFlags::EightBitLength );
2297 }
2298 
2300 {
2301  Append( static_cast<sal_uInt16>(rXclPos.mnRow) );
2302  if( meBiff <= EXC_BIFF5 )
2303  Append( static_cast< sal_uInt8 >( rXclPos.mnCol ) );
2304  else
2305  Append( rXclPos.mnCol );
2306 }
2307 
2309 {
2310  Append( static_cast<sal_uInt16>(rXclRange.maFirst.mnRow) );
2311  Append( static_cast<sal_uInt16>(rXclRange.maLast.mnRow) );
2312  if( meBiff <= EXC_BIFF5 )
2313  {
2314  Append( static_cast< sal_uInt8 >( rXclRange.maFirst.mnCol ) );
2315  Append( static_cast< sal_uInt8 >( rXclRange.maLast.mnCol ) );
2316  }
2317  else
2318  {
2319  Append( rXclRange.maFirst.mnCol );
2320  Append( rXclRange.maLast.mnCol );
2321  }
2322 }
2323 
2325 {
2326  if( nCount > 0 )
2327  {
2330  Append( nType );
2331  Append( nCount );
2332  }
2333 }
2334 
2336 {
2338  PushOperandPos( GetSize() );
2339  Append( nTokenId );
2340 }
2341 
2342 void XclExpFmlaCompImpl::AppendIntToken( sal_uInt16 nValue, sal_uInt8 nSpaces )
2343 {
2344  AppendOperandTokenId( EXC_TOKID_INT, nSpaces );
2345  Append( nValue );
2346 }
2347 
2348 void XclExpFmlaCompImpl::AppendNumToken( double fValue, sal_uInt8 nSpaces )
2349 {
2350  AppendOperandTokenId( EXC_TOKID_NUM, nSpaces );
2351  Append( fValue );
2352 }
2353 
2355 {
2358 }
2359 
2361 {
2362  AppendOperandTokenId( EXC_TOKID_ERR, nSpaces );
2363  Append( nErrCode );
2364 }
2365 
2367 {
2369 }
2370 
2371 void XclExpFmlaCompImpl::AppendNameToken( sal_uInt16 nNameIdx, sal_uInt8 nSpaces )
2372 {
2373  if( nNameIdx > 0 )
2374  {
2376  Append( nNameIdx );
2377  Append( 0, (meBiff <= EXC_BIFF5) ? 12 : 2 );
2378  }
2379  else
2381 }
2382 
2383 void XclExpFmlaCompImpl::AppendMissingNameToken( const OUString& rName, sal_uInt8 nSpaces )
2384 {
2385  sal_uInt16 nNameIdx = GetNameManager().InsertRawName( rName );
2386  AppendNameToken( nNameIdx, nSpaces );
2387 }
2388 
2389 void XclExpFmlaCompImpl::AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces )
2390 {
2392  Append( nExtSheet );
2393  if( meBiff <= EXC_BIFF5 )
2394  Append( 0, 8 );
2395  Append( nExtName );
2396  Append( 0, (meBiff <= EXC_BIFF5) ? 12 : 2 );
2397 }
2398 
2399 void XclExpFmlaCompImpl::AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData )
2400 {
2401  sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( rExtFuncData.maFuncName, rExtFuncData.mbVBasic, true, rExtFuncData.mbHidden );
2402  AppendNameToken( nNameIdx );
2403 }
2404 
2405 void XclExpFmlaCompImpl::AppendAddInCallToken( const XclExpExtFuncData& rExtFuncData )
2406 {
2407  OUString aXclFuncName;
2408  if( mxData->mpLinkMgr && ScGlobal::GetAddInCollection()->GetExcelName( rExtFuncData.maFuncName, GetUILanguage(), aXclFuncName ) )
2409  {
2410  sal_uInt16 nExtSheet, nExtName;
2411  if( mxData->mpLinkMgr->InsertAddIn( nExtSheet, nExtName, aXclFuncName ) )
2412  {
2413  AppendNameXToken( nExtSheet, nExtName );
2414  return;
2415  }
2416  }
2417  AppendMacroCallToken( rExtFuncData );
2418 }
2419 
2420 void XclExpFmlaCompImpl::AppendEuroToolCallToken( const XclExpExtFuncData& rExtFuncData )
2421 {
2422  sal_uInt16 nExtSheet(0), nExtName(0);
2423  if( mxData->mpLinkMgr && mxData->mpLinkMgr->InsertEuroTool( nExtSheet, nExtName, rExtFuncData.maFuncName ) )
2424  AppendNameXToken( nExtSheet, nExtName );
2425  else
2426  AppendMacroCallToken( rExtFuncData );
2427 }
2428 
2429 void XclExpFmlaCompImpl::AppendOperatorTokenId( sal_uInt8 nTokenId, const XclExpOperandListRef& rxOperands, sal_uInt8 nSpaces )
2430 {
2432  PushOperatorPos( GetSize(), rxOperands );
2433  Append( nTokenId );
2434 }
2435 
2437 {
2438  XclExpOperandListRef xOperands = std::make_shared<XclExpOperandList>();
2439  xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, true );
2440  AppendOperatorTokenId( nTokenId, xOperands, nSpaces );
2441 }
2442 
2444 {
2445  XclExpOperandListRef xOperands = std::make_shared<XclExpOperandList>();
2446  xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, bValType );
2447  xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, bValType );
2448  AppendOperatorTokenId( nTokenId, xOperands, nSpaces );
2449 }
2450 
2451 void XclExpFmlaCompImpl::AppendLogicalOperatorToken( sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount )
2452 {
2453  XclExpOperandListRef xOperands = std::make_shared<XclExpOperandList>();
2454  for( sal_uInt8 nOpIdx = 0; nOpIdx < nOpCount; ++nOpIdx )
2455  xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPX, false );
2457  Append( nOpCount );
2458  Append( nXclFuncIdx );
2459 }
2460 
2461 void XclExpFmlaCompImpl::AppendFuncToken( const XclExpFuncData& rFuncData )
2462 {
2463  sal_uInt16 nXclFuncIdx = rFuncData.GetXclFuncIdx();
2464  sal_uInt8 nParamCount = rFuncData.GetParamCount();
2465  sal_uInt8 nRetClass = rFuncData.GetReturnClass();
2466 
2467  if( (nXclFuncIdx == EXC_FUNCID_SUM) && (nParamCount == 1) )
2468  {
2469  // SUM with only one parameter
2470  AppendOperatorTokenId( EXC_TOKID_ATTR, rFuncData.GetOperandList() );
2472  Append( sal_uInt16( 0 ) );
2473  }
2474  else if( rFuncData.IsFixedParamCount() )
2475  {
2476  // fixed number of parameters
2477  AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNC, nRetClass ), rFuncData.GetOperandList() );
2478  Append( nXclFuncIdx );
2479  }
2480  else
2481  {
2482  // variable number of parameters
2483  AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNCVAR, nRetClass ), rFuncData.GetOperandList() );
2484  Append( nParamCount );
2485  Append( nXclFuncIdx );
2486  }
2487 }
2488 
2490 {
2494 }
2495 
2496 void XclExpFmlaCompImpl::AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType )
2497 {
2498  // store the start position of the token
2499  rFuncData.AppendAttrPos( GetSize() );
2500  // create the tAttr token
2502  Append( nAttrType );
2503  Append( sal_uInt16( 0 ) ); // placeholder that will be updated later
2504 }
2505 
2506 void XclExpFmlaCompImpl::InsertZeros( sal_uInt16 nInsertPos, sal_uInt16 nInsertSize )
2507 {
2508  // insert zeros into the token array
2509  OSL_ENSURE( nInsertPos < mxData->maTokVec.size(), "XclExpFmlaCompImpl::Insert - invalid position" );
2510  mxData->maTokVec.insert( mxData->maTokVec.begin() + nInsertPos, nInsertSize, 0 );
2511 
2512  // update positions of operands waiting for an operator
2513  for( auto& rOpPos : mxData->maOpPosStack )
2514  if( nInsertPos <= rOpPos )
2515  rOpPos += nInsertSize;
2516 
2517  // update operand lists of all operator tokens
2518  if( nInsertPos < mxData->maOpListVec.size() )
2519  mxData->maOpListVec.insert( mxData->maOpListVec.begin() + nInsertPos, nInsertSize, XclExpOperandListRef() );
2520  for( auto& rxOpList : mxData->maOpListVec )
2521  if( rxOpList )
2522  for( auto& rOp : *rxOpList )
2523  if( nInsertPos <= rOp.mnTokPos )
2524  rOp.mnTokPos += nInsertSize;
2525 }
2526 
2527 void XclExpFmlaCompImpl::Overwrite( sal_uInt16 nWriteToPos, sal_uInt16 nOffset )
2528 {
2529  OSL_ENSURE( o3tl::make_unsigned( nWriteToPos + 1 ) < mxData->maTokVec.size(), "XclExpFmlaCompImpl::Overwrite - invalid position" );
2530  ShortToSVBT16( nOffset, &mxData->maTokVec[ nWriteToPos ] );
2531 }
2532 
2533 void XclExpFmlaCompImpl::UpdateAttrGoto( sal_uInt16 nAttrPos )
2534 {
2535  /* tAttrGoto contains distance from end of tAttr token to position behind
2536  the function token (for IF or CHOOSE function), which is currently at
2537  the end of the token array. Additionally this distance is decreased by
2538  one, for whatever reason. So we have to subtract 4 and 1 from the
2539  distance between the tAttr token start and the end of the token array. */
2540  Overwrite( nAttrPos + 2, static_cast< sal_uInt16 >( GetSize() - nAttrPos - 5 ) );
2541 }
2542 
2543 bool XclExpFmlaCompImpl::IsSpaceToken( sal_uInt16 nPos ) const
2544 {
2545  return
2546  (o3tl::make_unsigned( nPos + 4 ) <= mxData->maTokVec.size()) &&
2547  (mxData->maTokVec[ nPos ] == EXC_TOKID_ATTR) &&
2548  (mxData->maTokVec[ nPos + 1 ] == EXC_TOK_ATTR_SPACE);
2549 }
2550 
2552 {
2553  // remove trailing tParen token
2554  if( !mxData->maTokVec.empty() && (mxData->maTokVec.back() == EXC_TOKID_PAREN) )
2555  mxData->maTokVec.pop_back();
2556  // remove remaining tAttrSpace tokens
2557  while( (mxData->maTokVec.size() >= 4) && IsSpaceToken( GetSize() - 4 ) )
2558  mxData->maTokVec.erase( mxData->maTokVec.end() - 4, mxData->maTokVec.end() );
2559 }
2560 
2562 {
2563  mxData->maExtDataVec.push_back( nData );
2564 }
2565 
2566 void XclExpFmlaCompImpl::AppendExt( sal_uInt8 nData, size_t nCount )
2567 {
2568  mxData->maExtDataVec.resize( mxData->maExtDataVec.size() + nCount, nData );
2569 }
2570 
2571 void XclExpFmlaCompImpl::AppendExt( sal_uInt16 nData )
2572 {
2573  lclAppend( mxData->maExtDataVec, nData );
2574 }
2575 
2576 void XclExpFmlaCompImpl::AppendExt( double fData )
2577 {
2578  lclAppend( mxData->maExtDataVec, fData );
2579 }
2580 
2581 void XclExpFmlaCompImpl::AppendExt( const OUString& rString )
2582 {
2583  lclAppend( mxData->maExtDataVec, GetRoot(), rString, (meBiff == EXC_BIFF8) ? XclStrFlags::NONE : XclStrFlags::EightBitLength );
2584 }
2585 
2586 namespace {
2587 
2588 void lclInitOwnTab( ScSingleRefData& rRef, const ScAddress& rScPos, SCTAB nCurrScTab, bool b3DRefOnly )
2589 {
2590  if( b3DRefOnly )
2591  {
2592  // no reduction to 2D reference, if global link manager is used
2593  rRef.SetFlag3D(true);
2594  }
2595  else if( rScPos.Tab() == nCurrScTab )
2596  {
2597  rRef.SetRelTab(0);
2598  }
2599 }
2600 
2601 void lclPutCellToTokenArray( ScTokenArray& rScTokArr, const ScAddress& rScPos, SCTAB nCurrScTab, bool b3DRefOnly )
2602 {
2603  ScSingleRefData aRef;
2604  aRef.InitAddress( rScPos );
2605  lclInitOwnTab( aRef, rScPos, nCurrScTab, b3DRefOnly );
2606  rScTokArr.AddSingleReference( aRef );
2607 }
2608 
2609 void lclPutRangeToTokenArray( ScTokenArray& rScTokArr, const ScRange& rScRange, SCTAB nCurrScTab, bool b3DRefOnly )
2610 {
2611  if( rScRange.aStart == rScRange.aEnd )
2612  {
2613  lclPutCellToTokenArray( rScTokArr, rScRange.aStart, nCurrScTab, b3DRefOnly );
2614  }
2615  else
2616  {
2617  ScComplexRefData aRef;
2618  aRef.InitRange( rScRange );
2619  lclInitOwnTab( aRef.Ref1, rScRange.aStart, nCurrScTab, b3DRefOnly );
2620  lclInitOwnTab( aRef.Ref2, rScRange.aEnd, nCurrScTab, b3DRefOnly );
2621  rScTokArr.AddDoubleReference( aRef );
2622  }
2623 }
2624 
2625 } // namespace
2626 
2628  XclExpRoot( rRoot ),
2629  mxImpl( std::make_shared<XclExpFmlaCompImpl>( rRoot ) )
2630 {
2631 }
2632 
2634 {
2635 }
2636 
2638  XclFormulaType eType, const ScTokenArray& rScTokArr,
2639  const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
2640 {
2641  return mxImpl->CreateFormula( eType, rScTokArr, pScBasePos, pRefLog );
2642 }
2643 
2645 {
2646  ScTokenArray aScTokArr(&GetRoot().GetDoc());
2647  lclPutCellToTokenArray( aScTokArr, rScPos, GetCurrScTab(), mxImpl->Is3DRefOnly( eType ) );
2648  return mxImpl->CreateFormula( eType, aScTokArr );
2649 }
2650 
2652 {
2653  ScTokenArray aScTokArr(&GetRoot().GetDoc());
2654  lclPutRangeToTokenArray( aScTokArr, rScRange, GetCurrScTab(), mxImpl->Is3DRefOnly( eType ) );
2655  return mxImpl->CreateFormula( eType, aScTokArr );
2656 }
2657 
2659 {
2660  size_t nCount = rScRanges.size();
2661  if( nCount == 0 )
2662  return XclTokenArrayRef();
2663 
2664  ScTokenArray aScTokArr(&GetRoot().GetDoc());
2665  SCTAB nCurrScTab = GetCurrScTab();
2666  bool b3DRefOnly = mxImpl->Is3DRefOnly( eType );
2667  for( size_t nIdx = 0; nIdx < nCount; ++nIdx )
2668  {
2669  if( nIdx > 0 )
2670  aScTokArr.AddOpCode( ocUnion );
2671  lclPutRangeToTokenArray( aScTokArr, rScRanges[ nIdx ], nCurrScTab, b3DRefOnly );
2672  }
2673  return mxImpl->CreateFormula( eType, aScTokArr );
2674 }
2675 
2677 {
2678  return mxImpl->CreateErrorFormula( nErrCode );
2679 }
2680 
2682  sal_uInt8 nTokenId, const XclAddress& rXclPos )
2683 {
2684  return mxImpl->CreateSpecialRefFormula( nTokenId, rXclPos );
2685 }
2686 
2688  sal_uInt16 nExtSheet, sal_uInt16 nExtName )
2689 {
2690  return mxImpl->CreateNameXFormula( nExtSheet, nExtName );
2691 }
2692 
2694 {
2695  return mxImpl->IsRef2D(rRefData, true);
2696 }
2697 
2699 {
2700  return mxImpl->IsRef2D(rRefData, true);
2701 }
2702 
2703 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsTabRel() const
Definition: refdata.hxx:70
const sal_uInt8 EXC_TOKID_PAREN
Percent sign.
Definition: xlformula.hxx:73
const sal_uInt8 EXC_TOKID_AREAERR
Deleted 2D cell reference.
Definition: xlformula.hxx:98
void AppendNumToken(double fValue, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2348
ocChoose
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:113
const SCCOL mnMaxScCol
Maximum row index.
Definition: xeformula.cxx:466
formula::FormulaToken * AddDoubleReference(const ScComplexRefData &rRef)
Definition: token.cxx:2212
ocStop
svString
void PushOperandPos(sal_uInt16 nTokPos)
Definition: xeformula.cxx:2212
const sal_uInt8 EXC_FUNC_MAXPARAM
Definition: xlformula.hxx:285
static void ChangeTokenClass(sal_uInt8 &rnTokenId, sal_uInt8 nTokenClass)
Changes the token class in the passed classified token ID.
Definition: xlformula.hxx:545
SCCOL Col() const
Definition: refdata.cxx:247
StackVar
::std::vector< sal_uInt8 > ScfUInt8Vec
Definition: ftools.hxx:251
static SC_DLLPUBLIC ScUnoAddInCollection * GetAddInCollection()
Definition: global.cxx:272
const sal_uInt8 EXC_TOKID_ARRAY
Floating-point constant.
Definition: xlformula.hxx:87
void ProcessDdeLink(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1261
XclExpScToken MulDivTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1043
void ProcessDefinedName(const XclExpScToken &rTokData)
Definition: xeformula.cxx:2124
bool IsTabDeleted() const
Definition: refdata.hxx:87
const sal_uInt8 EXC_TOKID_LE
Less than operator.
Definition: xlformula.hxx:62
OUString getString() const
XclBiff
An enumeration for all Excel file format types (BIFF types).
Definition: xlconst.hxx:30
ScAddress aStart
Definition: address.hxx:500
const sal_uInt8 EXC_ERR_NA
Definition: xlconst.hxx:111
void AppendNameXToken(sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2389
const sal_uInt8 EXC_TOKID_STR
Missing argument.
Definition: xlformula.hxx:75
XclExpRefLogEntry()
Calc index of the last sheet.
Definition: xeformula.cxx:43
MS Excel binary .xls.
Definition: xlconst.hxx:44
void AppendLogicalOperatorToken(sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount)
Definition: xeformula.cxx:2451
ocArcCotHyp
ocName
void ProcessExternalRangeRef(const XclExpScToken &rTokData)
Definition: xeformula.cxx:2086
ocCosecantHyp
SCROW Row() const
Definition: address.hxx:262
const FormulaToken * PeekNextRawToken() const
Definition: xeformula.cxx:813
bool IsVolatile(sal_uInt16 nNameIdx) const
Returns true, if the specified defined name is volatile.
Definition: xename.cxx:852
Single reference (one address) into the sheet.
Definition: refdata.hxx:30
XclStrFlags
Flags used to specify import/export mode of strings.
Definition: xlstring.hxx:29
XclTokenArrayRef CreateFormula(XclFormulaType eType, const ScTokenArray &rScTokArr, const ScAddress *pScBasePos=nullptr, XclExpRefLog *pRefLog=nullptr)
Creates an Excel token array from the passed Calc token array.
Definition: xeformula.cxx:488
const sal_uInt8 EXC_TOK_ATTR_SPACE_SP_OPEN
Line breaks before next token.
Definition: xlformula.hxx:127
void AppendNameToken(sal_uInt16 nNameIdx, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2371
void PushOperatorPos(sal_uInt16 nTokPos, const XclExpOperandListRef &rxOperands)
Definition: xeformula.cxx:2217
const sal_uInt8 EXC_TOK_NLR_ROWV
NLR: Column index.
Definition: xlformula.hxx:144
const sal_uInt8 EXC_TOKCLASS_REF
00-1F: Base tokens.
Definition: xlformula.hxx:44
bool mbValType
Token class conversion type.
Definition: xlformula.hxx:280
const sal_uInt8 EXC_TOKID_REF
Defined name.
Definition: xlformula.hxx:91
const sal_uInt16 mnMaxColMask
Maximum row index in Calc itself.
Definition: xeformula.cxx:468
void AppendOperandTokenId(sal_uInt8 nTokenId, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2335
const sal_uInt8 EXC_TOKID_REFERR3D
3D area reference.
Definition: xlformula.hxx:107
XclExpLinkManager & GetLocalLinkManager() const
Returns the local link manager for the current sheet.
Definition: xeroot.cxx:135
const sal_uInt8 EXC_TOKID_CONCAT
Power operator.
Definition: xlformula.hxx:60
const sal_uInt8 EXC_TOKID_GE
Equal operator.
Definition: xlformula.hxx:64
void AppendFuncToken(const XclExpFuncData &rFuncData)
Definition: xeformula.cxx:2461
const sal_uInt8 EXC_TOKID_MEMFUNC
Constant reference subexpression without result.
Definition: xlformula.hxx:96
XclExpScToken OrTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:964
Convert tokens to VAL class.
Definition: xlformula.hxx:190
void ProcessBad(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1229
XclExpScToken AddSubTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1028
const sal_uInt8 EXC_TOK_ATTR_GOTO
Jump array of CHOOSE function.
Definition: xlformula.hxx:120
void AppendIntToken(sal_uInt16 nValue, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2342
Conditional format.
Definition: xlformula.hxx:166
ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const
: If bString the ScMatrixValue->pS may still be NULL to indicate an empty string! ...
Definition: scmatrix.cxx:3078
void SetRelTab(SCTAB nVal)
Definition: refdata.cxx:99
ocOpen
const sal_uInt8 EXC_TOKID_LT
String concatenation operator.
Definition: xlformula.hxx:61
Parameter supported by Calc only.
Definition: xlformula.hxx:182
ocCosecant
#define F_PI2
bool IsMacroFunc() const
Returns true, if the function is simulated by a macro call.
Definition: xlformula.hxx:333
formula::FormulaToken * AddSingleReference(const ScSingleRefData &rRef)
ScSingleRefToken with ocPush.
Definition: token.cxx:2202
void UpdateAttrGoto(sal_uInt16 nAttrPos)
Definition: xeformula.cxx:2533
ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const OUString &rName, const ScAddress *pCurPos=nullptr)
Get an array of tokens corresponding with a specified name in a specified file.
SC_DLLPUBLIC ScRange toAbs(ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:493
void AppendAddInCallToken(const XclExpExtFuncData &rExtFuncData)
Definition: xeformula.cxx:2405
const sal_uInt8 EXC_TOKCLASS_ARR
40-5F: Value class tokens.
Definition: xlformula.hxx:46
ocLogNormDist
const sal_uInt8 EXC_TOK_BOOL_TRUE
sal_False value of a tBool token.
Definition: xlformula.hxx:115
XclTokenArrayRef CreateNameXFormula(sal_uInt16 nExtSheet, sal_uInt16 nExtName)
Creates a single tNameXR token for a reference to an external name.
Definition: xeformula.cxx:2687
ScAddress aEnd
Definition: address.hxx:501
void set_flag(Type &rnBitField, Type nMask, bool bSet=true)
Sets or clears (according to bSet) all set bits of nMask in rnBitField.
Definition: ftools.hxx:93
XclAddress maLast
Definition: xladdress.hxx:61
void AppendDefaultParam(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1655
XclExpScToken UnaryPreTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1089
sal_uInt32 mnRow
Definition: xladdress.hxx:33
const SCROW mnMaxAbsRow
Maximum column index.
Definition: xeformula.cxx:465
void ProcessExternalCellRef(const XclExpScToken &rTokData)
Definition: xeformula.cxx:2050
XclExpScToken ConcatTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1013
ReturnType limit_cast(Type nValue, ReturnType nMin, ReturnType nMax)
Returns the value, if it is not less than nMin and not greater than nMax, otherwise one of the limits...
Definition: ftools.hxx:61
SCTAB GetScTab(sal_uInt16 nNameIdx) const
Returns the Calc sheet of a local defined name, or SCTAB_GLOBAL for global defined names...
Definition: xename.cxx:846
XclTokenArrayRef CreateNameXFormula(sal_uInt16 nExtSheet, sal_uInt16 nExtName)
Creates a single tNameXR token for a reference to an external name.
Definition: xeformula.cxx:546
XclAddress maFirst
Definition: xladdress.hxx:60
XclExpRefLogEntry * GetNewRefLogEntry()
Definition: xeformula.cxx:1937
std::shared_ptr< T > make_shared(Args &&...args)
void Init(XclFormulaType eType)
Definition: xeformula.cxx:568
const sal_uInt8 EXC_CACHEDVAL_ERROR
Definition: xlconst.hxx:119
ScDocument & GetDoc() const
Returns reference to the destination document (import) or source document (export).
Definition: xlroot.cxx:278
const sal_uInt8 EXC_TOKID_AREA3D
3D cell reference.
Definition: xlformula.hxx:106
ocSpaces
Parameter supported by Calc and Excel.
Definition: xlformula.hxx:181
Shared formula.
Definition: xlformula.hxx:165
ocUnion
XclExpScToken Expression(XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep)
Definition: xeformula.cxx:935
const sal_uInt8 EXC_TOKID_NAMEX
Definition: xlformula.hxx:104
const sal_uInt8 EXC_TOKID_BOOL
Error constant.
Definition: xlformula.hxx:81
svExternalName
const size_t EXC_FUNCINFO_PARAMINFO_COUNT
Maximum parameter count.
Definition: xlformula.hxx:287
Web query source range.
Definition: xlformula.hxx:171
void RecalcTokenClass(const XclExpTokenConvInfo &rConvInfo, XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass)
Definition: xeformula.cxx:642
Try NOT to use this struct.
Definition: scmatrix.hxx:53
ocIf
XclFuncParamConv
Enumerates different types of token class conversion in function parameters.
Definition: xlformula.hxx:186
void FinishIfFunction(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1525
const sal_uInt8 EXC_TOKID_NONE
Definition: xlformula.hxx:52
ocLogInv
ocGammaDist
void ProcessFunction(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1366
const OUString * getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal=false)
It returns a pointer to the name of the URI associated with a given external file ID...
void SetRowDeleted(bool bVal)
Definition: refdata.cxx:115
const sal_uInt8 EXC_TOKID_ADD
Multiple operation reference.
Definition: xlformula.hxx:55
Implementation class of the export formula compiler.
Definition: xeformula.cxx:297
bool GetExcelName(const OUString &rCalcName, LanguageType eDestLang, OUString &rRetExcelName)
leave rRetExcelName unchanged, if no matching name is found
Definition: addincol.cxx:560
ocIndex
XclFormulaType
Mask for number of appended ranges.
Definition: xlformula.hxx:160
double fVal
Definition: scmatrix.hxx:55
const sal_uInt8 EXC_TOKID_LIST
Intersection operator.
Definition: xlformula.hxx:68
XclExpCompDataRef mxData
Excel function data provider.
Definition: xeformula.cxx:460
Access to global data from other classes.
Definition: xeroot.hxx:113
void ProcessExternal(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1283
bool GetBoolean() const
Only valid if ScMatrix methods indicate that this is a boolean.
Definition: scmatrix.hxx:66
char sal_uInt16 & nParamCount
Definition: callform.cxx:54
ocNegSub
void AppendBinaryOperatorToken(sal_uInt8 nTokenId, bool bValType, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2443
XclTokenArrayRef CreateTokenArray()
Definition: xeformula.cxx:785
void AppendOperatorTokenId(sal_uInt8 nTokenId, const XclExpOperandListRef &rxOperands, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2429
MS Excel 4.0.
Definition: xlconst.hxx:35
const sal_uInt16 EXC_TOK_REF_ROWREL
True = Column is relative.
Definition: xlformula.hxx:139
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:45
void RecalcTokenClasses()
Definition: xeformula.cxx:618
void ProcessCellRef(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1947
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
static sal_uInt8 GetTokenId(sal_uInt8 nBaseId, sal_uInt8 nTokenClass)
Returns the classified token ID from a base ID and the token class.
Definition: xlformula.hxx:538
const FormulaToken * GetNextRawToken()
Definition: xeformula.cxx:806
void AppendMissingToken(sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2366
const SCTAB SCTAB_INVALID
An invalid Excel sheet index, for common use.
Definition: xlconst.hxx:74
const sal_uInt8 EXC_TOKID_GT
Greater than or equal operator.
Definition: xlformula.hxx:65
ocRound
const sal_uInt8 EXC_TOKID_NE
Greater than operator.
Definition: xlformula.hxx:66
OpCode
int nCount
const sal_uInt8 EXC_TOKID_REF3D
External reference.
Definition: xlformula.hxx:105
void ProcessParentheses(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1234
void AppendBoolToken(bool bValue, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2354
XclTokenArrayRef CreateSpecialRefFormula(sal_uInt8 nTokenId, const XclAddress &rXclPos)
Creates a single token for a special cell reference.
Definition: xeformula.cxx:2681
ocGreater
XclExpFmlaClassType
Type of token class handling.
Definition: xeformula.cxx:224
SC_DLLPUBLIC ScExternalRefManager * GetExternalRefManager() const
Definition: documen3.cxx:604
XclExpCompConfigMap maCfgMap
Definition: xeformula.cxx:458
void FinishFunction(XclExpFuncData &rFuncData, sal_uInt8 nCloseSpaces)
Definition: xeformula.cxx:1457
ocEqual
svDouble
void AppendRange(const XclRange &rXclRange)
Definition: xeformula.cxx:2308
void SetColDeleted(bool bVal)
Definition: refdata.cxx:110
XclExpScToken Factor(XclExpScToken aTokData)
Definition: xeformula.cxx:1171
const sal_uInt16 EXC_FUNCID_SUM
Definition: xlformula.hxx:297
SCTAB Tab() const
Definition: address.hxx:271
LanguageType GetUILanguage() const
Returns the UI language.
Definition: xlroot.hxx:152
void SetRow(SCROW nRowP)
Definition: address.hxx:275
const sal_uInt8 EXC_TOKID_FUNCVAR
Function, fixed number of arguments.
Definition: xlformula.hxx:89
bool IsColRel() const
Definition: refdata.hxx:66
const sal_uInt8 EXC_TOKID_AREA
2D cell reference.
Definition: xlformula.hxx:92
Is
XclExpFmlaCompImplRef mxImpl
Definition: xeformula.hxx:89
const sal_uInt8 EXC_TOKID_UMINUS
Unary plus.
Definition: xlformula.hxx:71
const sal_uInt8 EXC_TOKID_NAME
Function, variable number of arguments.
Definition: xlformula.hxx:90
const SCTAB SCTAB_GLOBAL
An invalid Calc sheet index, for common use.
Definition: xlconst.hxx:75
ocCot
const sal_uInt8 EXC_TOKID_NUM
Integer constant.
Definition: xlformula.hxx:83
void SetCol(SCCOL nColP)
Definition: address.hxx:279
const sal_uInt8 EXC_ERR_REF
Definition: xlconst.hxx:108
void AppendEuroToolCallToken(const XclExpExtFuncData &rExtFuncData)
Definition: xeformula.cxx:2420
const sal_uInt8 EXC_TOKID_AREAERR3D
Deleted 3D cell reference.
Definition: xlformula.hxx:108
ocSep
DocumentType eType
XclTokenArrayRef CreateErrorFormula(sal_uInt8 nErrCode)
Creates a single error token containing the passed error code.
Definition: xeformula.cxx:2676
XclTokenArrayRef CreateSpecialRefFormula(sal_uInt8 nTokenId, const XclAddress &rXclPos)
Creates a single token for a special cell reference.
Definition: xeformula.cxx:537
void AppendMissingNameToken(const OUString &rName, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2383
const sal_uInt8 EXC_TOKID_UPLUS
Range operator.
Definition: xlformula.hxx:70
Matrix (array) formula.
Definition: xlformula.hxx:164
FormulaError GetError() const
Only valid if ScMatrix methods indicate that this is no string!
Definition: scmatrix.hxx:63
void ConvertRefData(ScSingleRefData &rRefData, XclAddress &rXclPos, bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow) const
Definition: xeformula.cxx:1872
const sal_uInt8 EXC_TOKID_SUB
Addition operator.
Definition: xlformula.hxx:56
XclExpLinkManager & GetGlobalLinkManager() const
Returns the global link manager for defined names.
Definition: xeroot.cxx:129
const sal_uInt8 EXC_TOKID_ERR
End of a sheet reference (BIFF2-BIFF4).
Definition: xlformula.hxx:80
XclExpScToken GetNextToken()
Definition: xeformula.cxx:835
ocDde
MS Excel 5.0, MS Excel 7.0 (95)
Definition: xlconst.hxx:36
Represents information for a spreadsheet function for import and export.
Definition: xlformula.hxx:311
const sal_uInt8 EXC_TOKID_REFN
Deleted 2D area reference.
Definition: xlformula.hxx:99
XclOutput GetOutput() const
Returns the current output format of the importer/exporter.
Definition: xlroot.hxx:142
static const OUString & GetNativeSymbol(OpCode eOp)
Defined name.
Definition: xlformula.hxx:168
void ProcessExternalName(const XclExpScToken &rTokData)
Definition: xeformula.cxx:2154
const size_t EXC_TOKARR_MAXLEN
Definition: xlformula.hxx:38
const sal_uInt32 mnMaxRowMask
Mask to delete invalid bits in column fields.
Definition: xeformula.cxx:469
OUString GetAddInEquivalentFuncName() const
Returns the programmatical name of the Add-In function as string.
Definition: xlformula.cxx:42
std::shared_ptr< XclExpCompData > XclExpCompDataRef
Definition: xeformula.cxx:456
const sal_uInt8 EXC_TOK_ATTR_SPACE_SP_CLOSE
Line breaks before opening parenthesis.
Definition: xlformula.hxx:129
void PrepareParam(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1598
void AppendUnaryOperatorToken(sal_uInt8 nTokenId, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2436
const sal_uInt8 EXC_TOK_ATTR_SPACE_SP
Spaces in formula representation.
Definition: xlformula.hxx:125
const sal_uInt8 EXC_TOK_ATTR_IF
Volatile function.
Definition: xlformula.hxx:118
Manager that stores all internal defined names (NAME records) of the document.
Definition: xename.hxx:32
static sal_uInt8 GetXclErrorCode(FormulaError nScError)
Converts a Calc error code to an Excel error code.
Definition: xltools.cxx:198
void SetFlag3D(bool bVal)
Definition: refdata.hxx:90
const sal_uInt8 EXC_TOKID_ATTR
Natural language reference (NLR).
Definition: xlformula.hxx:77
void GetDimensions(SCSIZE &rC, SCSIZE &rR) const
Definition: scmatrix.cxx:2968
void ProcessMatrix(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1296
sal_uInt16 PopOperandPos()
Definition: xeformula.cxx:2226
ocMul
void InitAddress(const ScAddress &rAdr)
InitAddress: InitFlags and set address.
Definition: refdata.cxx:27
sal_uInt16 InsertRawName(const OUString &rName)
Returns index of an existing name, or creates a name without definition.
Definition: xename.cxx:830
sal_Int16 SCCOL
Definition: types.hxx:22
void ProcessRangeRef(const XclExpScToken &rTokData)
Definition: xeformula.cxx:2005
const XclFunctionInfo * GetFuncInfoFromOpCode(OpCode eOpCode) const
Returns the function data for a Calc opcode, or 0 on error.
Definition: xlformula.cxx:692
ocPush
XclFunctionProvider maFuncProv
Compiler configuration map for all formula types.
Definition: xeformula.cxx:459
ocSub
const sal_uInt16 EXC_TOK_NLR_REL
NLR: Pivot table name.
Definition: xlformula.hxx:154
ocMissing
ScSingleRefData Ref1
Definition: refdata.hxx:125
static bool IsValueType(ScMatValType nType)
Value or boolean.
Definition: scmatrix.hxx:161
sal_uInt16 GetSize() const
Definition: xeformula.cxx:321
ocSecantHyp
ocPoissonDist
const sal_uInt16 EXC_FUNCID_AND
Definition: xlformula.hxx:298
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
size_t size() const
Definition: rangelst.hxx:90
void ProcessMissing(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1224
ScSingleRefData Ref2
Definition: refdata.hxx:126
bool IsSpaceToken(sal_uInt16 nPos) const
Definition: xeformula.cxx:2543
ocExternal
const sal_uInt8 EXC_TOK_NLR_COLV
NLR: Value in row.
Definition: xlformula.hxx:145
Repeat parent conversion in VALTYPE parameters.
Definition: xlformula.hxx:192
XclExpScToken ProcessParam(XclExpScToken aTokData, XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1567
const sal_uInt8 EXC_CACHEDVAL_BOOL
Definition: xlconst.hxx:118
svExternalDoubleRef
ocBad
FormulaError GetCodeError() const
ocNone
const sal_uInt8 EXC_TOK_ATTR_SPACE
BASIC style assignment.
Definition: xlformula.hxx:123
size
const sal_uInt8 EXC_TOKID_RANGE
List operator.
Definition: xlformula.hxx:69
svExternalSingleRef
::std::vector< XclExpRefLogEntry > XclExpRefLog
Vector containing a log for all external references in a formula, used i.e.
Definition: xeformula.hxx:44
const XclBiff meBiff
Stack for working data, when compiler is called recursively.
Definition: xeformula.cxx:463
const sal_uInt8 EXC_TOKID_EQ
Less than or equal operator.
Definition: xlformula.hxx:63
XclExpNameManager & GetNameManager() const
Returns the buffer that contains internal defined names.
Definition: xeroot.cxx:141
bool IsRowRel() const
Definition: refdata.hxx:68
static bool IsBooleanType(ScMatValType nType)
Boolean.
Definition: scmatrix.hxx:167
sal_uInt16 mnCol
Definition: xladdress.hxx:32
XclExpScToken IntersectTerm(XclExpScToken aTokData, bool &rbHasRefOp)
Definition: xeformula.cxx:1139
A 2D cell address struct with Excel column and row indexes.
Definition: xladdress.hxx:30
const ::formula::FormulaToken * Get() const
Definition: xlformula.hxx:451
void AppendExt(sal_uInt8 nData)
Definition: xeformula.cxx:2561
const sal_uInt8 EXC_TOKID_NLR
String constant.
Definition: xlformula.hxx:76
std::map< XclFormulaType, XclExpCompConfig > XclExpCompConfigMap
Definition: xeformula.cxx:455
ScMatValType nType
Definition: scmatrix.hxx:57
const sal_uInt8 EXC_CACHEDVAL_EMPTY
Definition: xlconst.hxx:115
ocLess
std::shared_ptr< XclTokenArray > XclTokenArrayRef
Definition: xlformula.hxx:417
SCTAB Tab() const
Definition: refdata.cxx:254
void Overwrite(sal_uInt16 nWriteToPos, sal_uInt16 nOffset)
Definition: xeformula.cxx:2527
Provides access to function info structs for all available functions.
Definition: xlformula.hxx:345
XclExpClassConv
Effective token class conversion types.
Definition: xeformula.cxx:70
svSingleRef
bool IsFlag3D() const
Definition: refdata.hxx:91
FormulaError
SCCOL Col() const
Definition: address.hxx:267
const XclExpRoot & GetRoot() const
Returns this root instance - for code readability in derived classes.
Definition: xeroot.hxx:119
SCTAB GetCurrScTab() const
Returns the current Calc sheet index.
Definition: xlroot.hxx:160
const sal_uInt8 EXC_TOKID_MISSARG
Parentheses.
Definition: xlformula.hxx:74
ocFalse
void AppendAddress(const XclAddress &rXclPos)
Definition: xeformula.cxx:2299
const sal_uInt16 EXC_TOK_STR_MAXLEN
Deleted 3D area reference.
Definition: xlformula.hxx:112
virtual ~XclExpFormulaCompiler() override
Definition: xeformula.cxx:2633
const sal_uInt8 EXC_TOKCLASS_VAL
20-3F: Reference class tokens.
Definition: xlformula.hxx:45
const sal_uInt8 EXC_TOK_ATTR_CHOOSE
Start of true condition in IF function.
Definition: xlformula.hxx:119
void AppendMacroCallToken(const XclExpExtFuncData &rExtFuncData)
Definition: xeformula.cxx:2399
const sal_uInt8 EXC_TOK_BOOL_FALSE
Maximum string length of a tStr token.
Definition: xlformula.hxx:114
ScAddress toAbs(ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:193
XclExpScToken UnaryPostTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1074
const svl::SharedString & GetString() const
Only valid if ScMatrix methods indicate so!
Definition: scmatrix.hxx:60
const sal_uInt8 EXC_CACHEDVAL_DOUBLE
Definition: xlconst.hxx:116
ocOr
svDoubleRef
virtual formula::FormulaToken * AddOpCode(OpCode eCode) override
Definition: token.cxx:2195
ocCotHyp
const sal_uInt8 EXC_TOKID_PERCENT
Unary minus.
Definition: xlformula.hxx:72
void ProcessBoolean(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1241
svUnknown
ocTrue
static sal_uInt8 GetTokenClass(sal_uInt8 nTokenId)
Returns the token class of the passed token ID.
Definition: xlformula.hxx:495
sal_Int32 SCROW
Definition: types.hxx:18
const sal_uInt8 EXC_TOKID_ISECT
Not equal operator.
Definition: xlformula.hxx:67
void ProcessString(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1218
XclExpScToken PowTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1058
void SetAddress(ScSheetLimits &rLimits, const ScAddress &rAddr, const ScAddress &rPos)
Definition: refdata.cxx:213
void PrepareFunction(const XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1434
const SCROW mnMaxScRow
Maximum column index in Calc itself.
Definition: xeformula.cxx:467
ocAdd
ocRoundUp
XclExpFormulaCompiler(const XclExpRoot &rRoot)
Definition: xeformula.cxx:2627
void ProcessDouble(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1207
XclExpScToken AndTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:981
::std::vector< sal_uInt16 > ScfUInt16Vec
Definition: ftools.hxx:253
void AppendSpaceToken(sal_uInt8 nType, sal_uInt8 nCount)
Definition: xeformula.cxx:2324
Stores all data for internal/external references (the link table).
Definition: xelink.hxx:146
std::vector< XclExpCompDataRef > maDataStack
Working data for current formula.
Definition: xeformula.cxx:462
sal_uInt16 InsertMacroCall(const OUString &rMacroName, bool bVBasic, bool bFunc, bool bHidden=false)
Searches or inserts a defined name describing a macro name.
Definition: xename.cxx:835
const sal_uInt8 EXC_CACHEDVAL_STRING
Definition: xlconst.hxx:117
unsigned char sal_uInt8
const sal_uInt8 EXC_ERR_NAME
Definition: xlconst.hxx:109
Convert tokens to ARR class.
Definition: xlformula.hxx:191
ocEuroConvert
const sal_uInt8 EXC_TOKID_POWER
Division operator.
Definition: xlformula.hxx:59
ocAnd
void InsertZeros(sal_uInt16 nInsertPos, sal_uInt16 nInsertSize)
Definition: xeformula.cxx:2506
bool IsRef2D(const ScSingleRefData &rRefData, bool bCheck3DFlag) const
Definition: xeformula.cxx:1845
void AppendErrorToken(sal_uInt8 nErrCode, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2360
OUString aName
std::shared_ptr< ScTokenArray > TokenArrayRef
ocArcCot
Always use UCS-2 characters (default: try to compress). BIFF8 only.
svMatrix
const sal_uInt8 EXC_TOKID_MUL
Subtraction operator.
Definition: xlformula.hxx:57
void InitRange(const ScRange &rRange)
Definition: refdata.hxx:130
const sal_uInt16 EXC_FUNCID_OR
Definition: xlformula.hxx:299
svExternal
SCTAB GetScTab(const ScSingleRefData &rRefData) const
Definition: xeformula.cxx:1830
ocColRowName
SCROW Row() const
Definition: refdata.cxx:240
XclTokenArrayRef CreateFormula(XclFormulaType eType, const ScTokenArray &rScTokArr, const ScAddress *pScBasePos=nullptr, XclExpRefLog *pRefLog=nullptr)
Creates and returns the token array of a formula.
Definition: xeformula.cxx:2637
const sal_uInt8 EXC_TOKID_INT
Boolean constant.
Definition: xlformula.hxx:82
XclFuncParamConv meConv
Parameter validity.
Definition: xlformula.hxx:279
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:401
void MoveRelWrap()
Definition: compiler.cxx:4976
ocRoundDown
Simple cell formula, also used in change tracking.
Definition: xlformula.hxx:163
FunctionParamInfo mpParamInfos[FUNCINFO_PARAMINFOCOUNT]
BIFF token class of the return value.
void FinishChooseFunction(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1539
Log entry for external references in a formula, used i.e.
Definition: xeformula.hxx:32
ocNeg
XclTokenArrayRef CreateErrorFormula(sal_uInt8 nErrCode)
Creates a single error token containing the passed error code.
Definition: xeformula.cxx:530
#define SC_OPCODE_START_NO_PAR
Data validation.
Definition: xlformula.hxx:167
ocDiv
bool Is3DRefOnly(XclFormulaType eType) const
Returns true, if the passed formula type allows 3D references only.
Definition: xeformula.cxx:553
Complex reference (a range) into the sheet.
Definition: refdata.hxx:123
const XclExpCompConfig * GetConfigForType(XclFormulaType eType) const
Definition: xeformula.cxx:561
const sal_uInt8 EXC_TOK_ATTR_SUM
Jump to token.
Definition: xlformula.hxx:121
XclExpScToken RangeTerm(XclExpScToken aTokData, bool &rbHasRefOp)
Definition: xeformula.cxx:1155
void Append(sal_uInt8 nData)
Definition: xeformula.cxx:2269
sal_uInt16 InsertName(SCTAB nTab, sal_uInt16 nScNameIdx, SCTAB nCurrTab)
Inserts the Calc name with the passed index and returns the Excel NAME index.
Definition: xename.cxx:802
ocMacro
static XclExpStringRef CreateString(const XclExpRoot &rRoot, const OUString &rString, XclStrFlags nFlags=XclStrFlags::NONE, sal_uInt16 nMaxLen=EXC_STR_MAXLEN)
Creates a new unformatted string from the passed string.
Definition: xehelper.cxx:526
#define SAL_WARN(area, stream)
ocNormDist
ocNotEqual
ocSecant
const sal_uInt8 EXC_TOKID_AREAN
Relative 2D cell reference (in names).
Definition: xlformula.hxx:100
ocLessEqual
XclExpScToken SkipExpression(XclExpScToken aTokData, bool bStopAtSep)
Definition: xeformula.cxx:950
std::shared_ptr< XclExpString > XclExpStringRef
Definition: xeroot.hxx:36
Repeat parent conversion in REFTYPE parameters.
Definition: xlformula.hxx:193
void AppendTrailingParam(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1702
const sal_uInt16 EXC_TOK_REF_COLREL
Mask for parameter count.
Definition: xlformula.hxx:138
A helper with Excel specific token array functions.
Definition: xlformula.hxx:486
const sal_uInt8 EXC_TOKID_FUNC
Array constant.
Definition: xlformula.hxx:88
bool IsAddInEquivalent() const
Returns true, if the function is stored as an add-in call.
Definition: xlformula.hxx:335
void AppendJumpToken(XclExpFuncData &rFuncData, sal_uInt8 nAttrType)
Definition: xeformula.cxx:2496
bool IsRowDeleted() const
Definition: refdata.hxx:85
Chart source ranges.
Definition: xlformula.hxx:169
const SCCOL mnMaxAbsCol
Cached BIFF version to save GetBiff() calls.
Definition: xeformula.cxx:464
Special token array iterator for the Excel filters.
Definition: xlformula.hxx:439
void AppendParenToken(sal_uInt8 nOpenSpaces=0, sal_uInt8 nCloseSpaces=0)
Definition: xeformula.cxx:2489
RedlineType meType
void RemoveTrailingParen()
Definition: xeformula.cxx:2551
aStr
ocClose
Spreadsheet links in form controls.
Definition: xlformula.hxx:170
std::unique_ptr< ScTokenArray > Clone() const
Definition: token.cxx:1920
A 2D cell range address struct with Excel column and row indexes.
Definition: xladdress.hxx:58
XclExpFmlaCompImpl(const XclExpRoot &rRoot)
Definition: xeformula.cxx:472
bool IsRef2D(const ScSingleRefData &rRefData) const
Definition: xeformula.cxx:2693
Structure that contains all needed information for a parameter in a function.
Definition: xlformula.hxx:276
sal_Int16 SCTAB
Definition: types.hxx:23
bool IsColDeleted() const
Definition: refdata.hxx:83
OUString GetMacroFuncName() const
Returns the name of the external function as string.
Definition: xlformula.cxx:35
XclExpScToken CompareTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:998
Use original class of current token.
Definition: xlformula.hxx:189
void FinishParam(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1635
ocGreaterEqual
XclExpScToken ListTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1105
const sal_uInt8 EXC_TOKID_DIV
Multiplication operator.
Definition: xlformula.hxx:58
const sal_uInt8 EXC_TOKID_REFERR
Variable reference subexpression.
Definition: xlformula.hxx:97
const sal_uInt8 EXC_TOK_ATTR_VOLATILE
sal_True value of a tBool token.
Definition: xlformula.hxx:117