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 = 0;
830  /* TODO: handle ocWhitespace characters? */
831  while (rTokData.GetOpCode() == ocSpaces || rTokData.GetOpCode() == ocWhitespace)
832  {
833  rTokData.mnSpaces += rTokData.mpScToken->GetByte();
834  rTokData.mpScToken = GetNextRawToken();
835  }
836  return rTokData.Is();
837 }
838 
840 {
841  XclExpScToken aTokData;
842  GetNextToken( aTokData );
843  return aTokData;
844 }
845 
846 namespace {
847 
849 sal_uInt8 lclGetCompareTokenId( OpCode eOpCode )
850 {
851  switch( eOpCode )
852  {
853  case ocLess: return EXC_TOKID_LT;
854  case ocLessEqual: return EXC_TOKID_LE;
855  case ocEqual: return EXC_TOKID_EQ;
856  case ocGreaterEqual: return EXC_TOKID_GE;
857  case ocGreater: return EXC_TOKID_GT;
858  case ocNotEqual: return EXC_TOKID_NE;
859  default:;
860  }
861  return EXC_TOKID_NONE;
862 }
863 
865 sal_uInt8 lclGetConcatTokenId( OpCode eOpCode )
866 {
867  return (eOpCode == ocAmpersand) ? EXC_TOKID_CONCAT : EXC_TOKID_NONE;
868 }
869 
871 sal_uInt8 lclGetAddSubTokenId( OpCode eOpCode )
872 {
873  switch( eOpCode )
874  {
875  case ocAdd: return EXC_TOKID_ADD;
876  case ocSub: return EXC_TOKID_SUB;
877  default:;
878  }
879  return EXC_TOKID_NONE;
880 }
881 
883 sal_uInt8 lclGetMulDivTokenId( OpCode eOpCode )
884 {
885  switch( eOpCode )
886  {
887  case ocMul: return EXC_TOKID_MUL;
888  case ocDiv: return EXC_TOKID_DIV;
889  default:;
890  }
891  return EXC_TOKID_NONE;
892 }
893 
895 sal_uInt8 lclGetPowTokenId( OpCode eOpCode )
896 {
897  return (eOpCode == ocPow) ? EXC_TOKID_POWER : EXC_TOKID_NONE;
898 }
899 
901 sal_uInt8 lclGetUnaryPostTokenId( OpCode eOpCode )
902 {
903  return (eOpCode == ocPercentSign) ? EXC_TOKID_PERCENT : EXC_TOKID_NONE;
904 }
905 
907 sal_uInt8 lclGetUnaryPreTokenId( OpCode eOpCode )
908 {
909  switch( eOpCode )
910  {
911  case ocAdd: return EXC_TOKID_UPLUS; // +(1)
912  case ocNeg: return EXC_TOKID_UMINUS; // NEG(1)
913  case ocNegSub: return EXC_TOKID_UMINUS; // -(1)
914  default:;
915  }
916  return EXC_TOKID_NONE;
917 }
918 
920 sal_uInt8 lclGetListTokenId( OpCode eOpCode, bool bStopAtSep )
921 {
922  return ((eOpCode == ocUnion) || (!bStopAtSep && (eOpCode == ocSep))) ? EXC_TOKID_LIST : EXC_TOKID_NONE;
923 }
924 
926 sal_uInt8 lclGetIntersectTokenId( OpCode eOpCode )
927 {
928  return (eOpCode == ocIntersect) ? EXC_TOKID_ISECT : EXC_TOKID_NONE;
929 }
930 
932 sal_uInt8 lclGetRangeTokenId( OpCode eOpCode )
933 {
934  return (eOpCode == ocRange) ? EXC_TOKID_RANGE : EXC_TOKID_NONE;
935 }
936 
937 } // namespace
938 
939 XclExpScToken XclExpFmlaCompImpl::Expression( XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep )
940 {
941  if( mxData->mbOk && aTokData.Is() )
942  {
943  // remember old stop-at-ocSep mode, restored below
944  bool bOldStopAtSep = mxData->mbStopAtSep;
945  mxData->mbStopAtSep = bStopAtSep;
946  // start compilation of the subexpression
947  aTokData = OrTerm( aTokData, bInParentheses );
948  // restore old stop-at-ocSep mode
949  mxData->mbStopAtSep = bOldStopAtSep;
950  }
951  return aTokData;
952 }
953 
954 XclExpScToken XclExpFmlaCompImpl::SkipExpression( XclExpScToken aTokData, bool bStopAtSep )
955 {
956  while( mxData->mbOk && aTokData.Is() && (aTokData.GetOpCode() != ocClose) && (!bStopAtSep || (aTokData.GetOpCode() != ocSep)) )
957  {
958  if( aTokData.GetOpCode() == ocOpen )
959  {
960  aTokData = SkipExpression( GetNextToken(), false );
961  if( mxData->mbOk ) mxData->mbOk = aTokData.GetOpCode() == ocClose;
962  }
963  aTokData = GetNextToken();
964  }
965  return aTokData;
966 }
967 
968 XclExpScToken XclExpFmlaCompImpl::OrTerm( XclExpScToken aTokData, bool bInParentheses )
969 {
970  aTokData = AndTerm( aTokData, bInParentheses );
972  while( mxData->mbOk && (aTokData.GetOpCode() == ocOr) )
973  {
975  aTokData = AndTerm( GetNextToken(), bInParentheses );
977  ++nParamCount;
978  if( mxData->mbOk ) mxData->mbOk = nParamCount <= EXC_FUNC_MAXPARAM;
979  }
980  if( mxData->mbOk && (nParamCount > 1) )
982  return aTokData;
983 }
984 
985 XclExpScToken XclExpFmlaCompImpl::AndTerm( XclExpScToken aTokData, bool bInParentheses )
986 {
987  aTokData = CompareTerm( aTokData, bInParentheses );
989  while( mxData->mbOk && (aTokData.GetOpCode() == ocAnd) )
990  {
992  aTokData = CompareTerm( GetNextToken(), bInParentheses );
994  ++nParamCount;
995  if( mxData->mbOk ) mxData->mbOk = nParamCount <= EXC_FUNC_MAXPARAM;
996  }
997  if( mxData->mbOk && (nParamCount > 1) )
999  return aTokData;
1000 }
1001 
1002 XclExpScToken XclExpFmlaCompImpl::CompareTerm( XclExpScToken aTokData, bool bInParentheses )
1003 {
1004  aTokData = ConcatTerm( aTokData, bInParentheses );
1005  while( mxData->mbOk )
1006  {
1007  sal_uInt8 nOpTokenId = lclGetConcatTokenId( aTokData.GetOpCode() );
1008  if (nOpTokenId == EXC_TOKID_NONE)
1009  break;
1010  sal_uInt8 nSpaces = aTokData.mnSpaces;
1011  aTokData = ConcatTerm( GetNextToken(), bInParentheses );
1012  AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1013  }
1014  return aTokData;
1015 }
1016 
1017 XclExpScToken XclExpFmlaCompImpl::ConcatTerm( XclExpScToken aTokData, bool bInParentheses )
1018 {
1019  aTokData = AddSubTerm( aTokData, bInParentheses );
1020  while( mxData->mbOk )
1021  {
1022  sal_uInt8 nOpTokenId = lclGetCompareTokenId( aTokData.GetOpCode() );
1023  if (nOpTokenId == EXC_TOKID_NONE)
1024  break;
1025  sal_uInt8 nSpaces = aTokData.mnSpaces;
1026  aTokData = AddSubTerm( GetNextToken(), bInParentheses );
1027  AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1028  }
1029  return aTokData;
1030 }
1031 
1032 XclExpScToken XclExpFmlaCompImpl::AddSubTerm( XclExpScToken aTokData, bool bInParentheses )
1033 {
1034  aTokData = MulDivTerm( aTokData, bInParentheses );
1035  while( mxData->mbOk )
1036  {
1037  sal_uInt8 nOpTokenId = lclGetAddSubTokenId( aTokData.GetOpCode() );
1038  if (nOpTokenId == EXC_TOKID_NONE)
1039  break;
1040  sal_uInt8 nSpaces = aTokData.mnSpaces;
1041  aTokData = MulDivTerm( GetNextToken(), bInParentheses );
1042  AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1043  }
1044  return aTokData;
1045 }
1046 
1047 XclExpScToken XclExpFmlaCompImpl::MulDivTerm( XclExpScToken aTokData, bool bInParentheses )
1048 {
1049  aTokData = PowTerm( aTokData, bInParentheses );
1050  while( mxData->mbOk )
1051  {
1052  sal_uInt8 nOpTokenId = lclGetMulDivTokenId( aTokData.GetOpCode() );
1053  if (nOpTokenId == EXC_TOKID_NONE)
1054  break;
1055  sal_uInt8 nSpaces = aTokData.mnSpaces;
1056  aTokData = PowTerm( GetNextToken(), bInParentheses );
1057  AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1058  }
1059  return aTokData;
1060 }
1061 
1062 XclExpScToken XclExpFmlaCompImpl::PowTerm( XclExpScToken aTokData, bool bInParentheses )
1063 {
1064  aTokData = UnaryPostTerm( aTokData, bInParentheses );
1065  sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1066  while( mxData->mbOk )
1067  {
1068  nOpTokenId = lclGetPowTokenId( aTokData.GetOpCode() );
1069  if (nOpTokenId == EXC_TOKID_NONE)
1070  break;
1071  sal_uInt8 nSpaces = aTokData.mnSpaces;
1072  aTokData = UnaryPostTerm( GetNextToken(), bInParentheses );
1073  AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1074  }
1075  return aTokData;
1076 }
1077 
1078 XclExpScToken XclExpFmlaCompImpl::UnaryPostTerm( XclExpScToken aTokData, bool bInParentheses )
1079 {
1080  aTokData = UnaryPreTerm( aTokData, bInParentheses );
1081  sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1082  while( mxData->mbOk )
1083  {
1084  nOpTokenId = lclGetUnaryPostTokenId( aTokData.GetOpCode() );
1085  if (nOpTokenId == EXC_TOKID_NONE)
1086  break;
1087  AppendUnaryOperatorToken( nOpTokenId, aTokData.mnSpaces );
1088  GetNextToken( aTokData );
1089  }
1090  return aTokData;
1091 }
1092 
1093 XclExpScToken XclExpFmlaCompImpl::UnaryPreTerm( XclExpScToken aTokData, bool bInParentheses )
1094 {
1095  sal_uInt8 nOpTokenId = mxData->mbOk ? lclGetUnaryPreTokenId( aTokData.GetOpCode() ) : EXC_TOKID_NONE;
1096  if( nOpTokenId != EXC_TOKID_NONE )
1097  {
1098  sal_uInt8 nSpaces = aTokData.mnSpaces;
1099  aTokData = UnaryPreTerm( GetNextToken(), bInParentheses );
1100  AppendUnaryOperatorToken( nOpTokenId, nSpaces );
1101  }
1102  else
1103  {
1104  aTokData = ListTerm( aTokData, bInParentheses );
1105  }
1106  return aTokData;
1107 }
1108 
1109 XclExpScToken XclExpFmlaCompImpl::ListTerm( XclExpScToken aTokData, bool bInParentheses )
1110 {
1111  sal_uInt16 nSubExprPos = GetSize();
1112  bool bHasAnyRefOp = false;
1113  bool bHasListOp = false;
1114  aTokData = IntersectTerm( aTokData, bHasAnyRefOp );
1115  while( mxData->mbOk )
1116  {
1117  sal_uInt8 nOpTokenId = lclGetListTokenId( aTokData.GetOpCode(), mxData->mbStopAtSep );
1118  if (nOpTokenId == EXC_TOKID_NONE)
1119  break;
1120  sal_uInt8 nSpaces = aTokData.mnSpaces;
1121  aTokData = IntersectTerm( GetNextToken(), bHasAnyRefOp );
1122  AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
1123  bHasAnyRefOp = bHasListOp = true;
1124  }
1125  if( bHasAnyRefOp )
1126  {
1127  // add a tMemFunc token enclosing the entire reference subexpression
1128  sal_uInt16 nSubExprSize = GetSize() - nSubExprPos;
1129  InsertZeros( nSubExprPos, 3 );
1130  mxData->maTokVec[ nSubExprPos ] = GetTokenId( EXC_TOKID_MEMFUNC, EXC_TOKCLASS_REF );
1131  Overwrite( nSubExprPos + 1, nSubExprSize );
1132  // update the operand/operator stack (set the list expression as operand of the tMemFunc)
1133  XclExpOperandListRef xOperands = std::make_shared<XclExpOperandList>();
1134  xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_VAL, false );
1135  PushOperatorPos( nSubExprPos, xOperands );
1136  }
1137  // #i86439# enclose list operator into parentheses, e.g. Calc's =AREAS(A1~A2) to Excel's =AREAS((A1;A2))
1138  if( bHasListOp && !bInParentheses )
1139  AppendParenToken();
1140  return aTokData;
1141 }
1142 
1143 XclExpScToken XclExpFmlaCompImpl::IntersectTerm( XclExpScToken aTokData, bool& rbHasRefOp )
1144 {
1145  aTokData = RangeTerm( aTokData, rbHasRefOp );
1146  while( mxData->mbOk )
1147  {
1148  sal_uInt8 nOpTokenId = lclGetIntersectTokenId( aTokData.GetOpCode() );
1149  if (nOpTokenId ==EXC_TOKID_NONE)
1150  break;
1151  sal_uInt8 nSpaces = aTokData.mnSpaces;
1152  aTokData = RangeTerm( GetNextToken(), rbHasRefOp );
1153  AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
1154  rbHasRefOp = true;
1155  }
1156  return aTokData;
1157 }
1158 
1159 XclExpScToken XclExpFmlaCompImpl::RangeTerm( XclExpScToken aTokData, bool& rbHasRefOp )
1160 {
1161  aTokData = Factor( aTokData );
1162  while( mxData->mbOk )
1163  {
1164  sal_uInt8 nOpTokenId = lclGetRangeTokenId( aTokData.GetOpCode() );
1165  if (nOpTokenId == EXC_TOKID_NONE)
1166  break;
1167  sal_uInt8 nSpaces = aTokData.mnSpaces;
1168  aTokData = Factor( GetNextToken() );
1169  AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
1170  rbHasRefOp = true;
1171  }
1172  return aTokData;
1173 }
1174 
1175 XclExpScToken XclExpFmlaCompImpl::Factor( XclExpScToken aTokData )
1176 {
1177  if( !mxData->mbOk || !aTokData.Is() ) return XclExpScToken();
1178 
1179  switch( aTokData.GetType() )
1180  {
1181  case svUnknown: mxData->mbOk = false; break;
1182  case svDouble: ProcessDouble( aTokData ); break;
1183  case svString: ProcessString( aTokData ); break;
1184  case svSingleRef: ProcessCellRef( aTokData ); break;
1185  case svDoubleRef: ProcessRangeRef( aTokData ); break;
1186  case svExternalSingleRef: ProcessExternalCellRef( aTokData ); break;
1187  case svExternalDoubleRef: ProcessExternalRangeRef( aTokData ); break;
1188  case svExternalName: ProcessExternalName( aTokData ); break;
1189  case svMatrix: ProcessMatrix( aTokData ); break;
1190  case svExternal: ProcessExternal( aTokData ); break;
1191 
1192  default: switch( aTokData.GetOpCode() )
1193  {
1194  case ocNone: /* do nothing */ break;
1195  case ocMissing: ProcessMissing( aTokData ); break;
1196  case ocBad: ProcessBad( aTokData ); break;
1197  case ocOpen: ProcessParentheses( aTokData ); break;
1198  case ocName: ProcessDefinedName( aTokData ); break;
1199  case ocFalse:
1200  case ocTrue: ProcessBoolean( aTokData ); break;
1201  case ocDde: ProcessDdeLink( aTokData ); break;
1202  default: ProcessFunction( aTokData );
1203  }
1204  }
1205 
1206  return GetNextToken();
1207 }
1208 
1209 // formula structure ----------------------------------------------------------
1210 
1211 void XclExpFmlaCompImpl::ProcessDouble( const XclExpScToken& rTokData )
1212 {
1213  double fValue = rTokData.mpScToken->GetDouble();
1214  double fInt;
1215  double fFrac = modf( fValue, &fInt );
1216  if( (fFrac == 0.0) && (0.0 <= fInt) && (fInt <= 65535.0) )
1217  AppendIntToken( static_cast< sal_uInt16 >( fInt ), rTokData.mnSpaces );
1218  else
1219  AppendNumToken( fValue, rTokData.mnSpaces );
1220 }
1221 
1222 void XclExpFmlaCompImpl::ProcessString( const XclExpScToken& rTokData )
1223 {
1224  AppendOperandTokenId( EXC_TOKID_STR, rTokData.mnSpaces );
1225  Append( rTokData.mpScToken->GetString().getString() );
1226 }
1227 
1228 void XclExpFmlaCompImpl::ProcessMissing( const XclExpScToken& rTokData )
1229 {
1230  AppendMissingToken( rTokData.mnSpaces );
1231 }
1232 
1233 void XclExpFmlaCompImpl::ProcessBad( const XclExpScToken& rTokData )
1234 {
1235  AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
1236 }
1237 
1238 void XclExpFmlaCompImpl::ProcessParentheses( const XclExpScToken& rTokData )
1239 {
1240  XclExpScToken aTokData = Expression( GetNextToken(), true, false );
1241  mxData->mbOk = aTokData.GetOpCode() == ocClose;
1242  AppendParenToken( rTokData.mnSpaces, aTokData.mnSpaces );
1243 }
1244 
1245 void XclExpFmlaCompImpl::ProcessBoolean( const XclExpScToken& rTokData )
1246 {
1247  mxData->mbOk = GetNextToken().GetOpCode() == ocOpen;
1248  if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocClose;
1249  if( mxData->mbOk )
1250  AppendBoolToken( rTokData.GetOpCode() == ocTrue, rTokData.mnSpaces );
1251 }
1252 
1253 namespace {
1254 
1255 bool lclGetTokenString( OUString& rString, const XclExpScToken& rTokData )
1256 {
1257  bool bIsStr = (rTokData.GetType() == svString) && (rTokData.GetOpCode() == ocPush);
1258  if( bIsStr )
1259  rString = rTokData.mpScToken->GetString().getString();
1260  return bIsStr;
1261 }
1262 
1263 } // namespace
1264 
1265 void XclExpFmlaCompImpl::ProcessDdeLink( const XclExpScToken& rTokData )
1266 {
1267  OUString aApplic, aTopic, aItem;
1268 
1269  mxData->mbOk = GetNextToken().GetOpCode() == ocOpen;
1270  if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aApplic, GetNextToken() );
1271  if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocSep;
1272  if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aTopic, GetNextToken() );
1273  if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocSep;
1274  if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aItem, GetNextToken() );
1275  if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocClose;
1276  if( mxData->mbOk ) mxData->mbOk = !aApplic.isEmpty() && !aTopic.isEmpty() && !aItem.isEmpty();
1277  if( mxData->mbOk )
1278  {
1279  sal_uInt16 nExtSheet(0), nExtName(0);
1280  if( mxData->mpLinkMgr && mxData->mpLinkMgr->InsertDde( nExtSheet, nExtName, aApplic, aTopic, aItem ) )
1281  AppendNameXToken( nExtSheet, nExtName, rTokData.mnSpaces );
1282  else
1283  AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
1284  }
1285 }
1286 
1287 void XclExpFmlaCompImpl::ProcessExternal( const XclExpScToken& rTokData )
1288 {
1289  /* #i47228# Excel import generates svExternal/ocMacro tokens for invalid
1290  names and for external/invalid function calls. This function looks for
1291  the next token in the token array. If it is an opening parenthesis, the
1292  token is processed as external function call, otherwise as undefined name. */
1293  const FormulaToken* pNextScToken = PeekNextRawToken();
1294  if( !pNextScToken || (pNextScToken->GetOpCode() != ocOpen) )
1295  AppendMissingNameToken( rTokData.mpScToken->GetExternal(), rTokData.mnSpaces );
1296  else
1297  ProcessFunction( rTokData );
1298 }
1299 
1300 void XclExpFmlaCompImpl::ProcessMatrix( const XclExpScToken& rTokData )
1301 {
1302  const ScMatrix* pMatrix = rTokData.mpScToken->GetMatrix();
1303  if( pMatrix && mxData->mrCfg.mbAllowArrays )
1304  {
1305  SCSIZE nScCols, nScRows;
1306  pMatrix->GetDimensions( nScCols, nScRows );
1307  OSL_ENSURE( (nScCols > 0) && (nScRows > 0), "XclExpFmlaCompImpl::ProcessMatrix - invalid matrix size" );
1308  sal_uInt16 nCols = ::limit_cast< sal_uInt16 >( nScCols, 0, 256 );
1309  sal_uInt16 nRows = ::limit_cast< sal_uInt16 >( nScRows, 0, 1024 );
1310 
1311  // create the tArray token
1313  Append( static_cast< sal_uInt8 >( (meBiff == EXC_BIFF8) ? (nCols - 1) : nCols ) );
1314  Append( static_cast< sal_uInt16 >( (meBiff == EXC_BIFF8) ? (nRows - 1) : nRows ) );
1315  Append( static_cast< sal_uInt32 >( 0 ) );
1316 
1317  // create the extended data containing the array values
1318  AppendExt( static_cast< sal_uInt8 >( (meBiff == EXC_BIFF8) ? (nCols - 1) : nCols ) );
1319  AppendExt( static_cast< sal_uInt16 >( (meBiff == EXC_BIFF8) ? (nRows - 1) : nRows ) );
1320  for( SCSIZE nScRow = 0; nScRow < nScRows; ++nScRow )
1321  {
1322  for( SCSIZE nScCol = 0; nScCol < nScCols; ++nScCol )
1323  {
1324  ScMatrixValue nMatVal = pMatrix->Get( nScCol, nScRow );
1325  if( ScMatrix::IsValueType( nMatVal.nType ) ) // value, boolean, or error
1326  {
1327  FormulaError nErr;
1328  if( ScMatrix::IsBooleanType( nMatVal.nType ) )
1329  {
1331  AppendExt( static_cast< sal_uInt8 >( nMatVal.GetBoolean() ? 1 : 0 ) );
1332  AppendExt( 0, 7 );
1333  }
1334  else if( (nErr = nMatVal.GetError()) != FormulaError::NONE )
1335  {
1338  AppendExt( 0, 7 );
1339  }
1340  else
1341  {
1343  AppendExt( nMatVal.fVal );
1344  }
1345  }
1346  else // string or empty
1347  {
1348  const OUString aStr( nMatVal.GetString().getString());
1349  if( aStr.isEmpty() )
1350  {
1352  AppendExt( 0, 8 );
1353  }
1354  else
1355  {
1357  AppendExt( aStr );
1358  }
1359  }
1360  }
1361  }
1362  }
1363  else
1364  {
1365  // array in places that do not allow it (cond fmts, data validation)
1366  AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
1367  }
1368 }
1369 
1370 void XclExpFmlaCompImpl::ProcessFunction( const XclExpScToken& rTokData )
1371 {
1372  OpCode eOpCode = rTokData.GetOpCode();
1373  const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromOpCode( eOpCode );
1374 
1375  XclExpExtFuncData aExtFuncData;
1376 
1377  // no exportable function found - try to create an external macro call
1378  if( !pFuncInfo && (eOpCode >= SC_OPCODE_START_NO_PAR) )
1379  {
1380  const OUString& rFuncName = ScCompiler::GetNativeSymbol( eOpCode );
1381  if( !rFuncName.isEmpty() )
1382  {
1383  aExtFuncData.Set( rFuncName, true, false );
1384  pFuncInfo = maFuncProv.GetFuncInfoFromOpCode( ocMacro );
1385  }
1386  }
1387 
1388  mxData->mbOk = pFuncInfo != nullptr;
1389  if( !mxData->mbOk ) return;
1390 
1391  // internal functions equivalent to an existing add-in
1392  if( pFuncInfo->IsAddInEquivalent() )
1393  aExtFuncData.Set( pFuncInfo->GetAddInEquivalentFuncName(), true, false );
1394  // functions simulated by a macro call in file format
1395  else if( pFuncInfo->IsMacroFunc() )
1396  aExtFuncData.Set( pFuncInfo->GetMacroFuncName(), false, true );
1397 
1398  XclExpFuncData aFuncData( rTokData, *pFuncInfo, aExtFuncData );
1399  XclExpScToken aTokData;
1400 
1401  // preparations for special functions, before function processing starts
1402  PrepareFunction( aFuncData );
1403 
1404  enum { STATE_START, STATE_OPEN, STATE_PARAM, STATE_SEP, STATE_CLOSE, STATE_END }
1405  eState = STATE_START;
1406  while( eState != STATE_END ) switch( eState )
1407  {
1408  case STATE_START:
1409  mxData->mbOk = GetNextToken( aTokData ) && (aTokData.GetOpCode() == ocOpen);
1410  eState = mxData->mbOk ? STATE_OPEN : STATE_END;
1411  break;
1412  case STATE_OPEN:
1413  mxData->mbOk = GetNextToken( aTokData );
1414  eState = mxData->mbOk ? ((aTokData.GetOpCode() == ocClose) ? STATE_CLOSE : STATE_PARAM) : STATE_END;
1415  break;
1416  case STATE_PARAM:
1417  aTokData = ProcessParam( aTokData, aFuncData );
1418  switch( aTokData.GetOpCode() )
1419  {
1420  case ocSep: eState = STATE_SEP; break;
1421  case ocClose: eState = STATE_CLOSE; break;
1422  default: mxData->mbOk = false;
1423  }
1424  if( !mxData->mbOk ) eState = STATE_END;
1425  break;
1426  case STATE_SEP:
1427  mxData->mbOk = (aFuncData.GetParamCount() < EXC_FUNC_MAXPARAM) && GetNextToken( aTokData );
1428  eState = mxData->mbOk ? STATE_PARAM : STATE_END;
1429  break;
1430  case STATE_CLOSE:
1431  FinishFunction( aFuncData, aTokData.mnSpaces );
1432  eState = STATE_END;
1433  break;
1434  default:;
1435  }
1436 }
1437 
1438 void XclExpFmlaCompImpl::PrepareFunction( const XclExpFuncData& rFuncData )
1439 {
1440  // For OOXML these are not rewritten anymore.
1441  if (GetOutput() == EXC_OUTPUT_XML_2007)
1442  return;
1443 
1444  switch( rFuncData.GetOpCode() )
1445  {
1446  case ocCosecant: // simulate CSC(x) by (1/SIN(x))
1447  case ocSecant: // simulate SEC(x) by (1/COS(x))
1448  case ocCot: // simulate COT(x) by (1/TAN(x))
1449  case ocCosecantHyp: // simulate CSCH(x) by (1/SINH(x))
1450  case ocSecantHyp: // simulate SECH(x) by (1/COSH(x))
1451  case ocCotHyp: // simulate COTH(x) by (1/TANH(x))
1452  AppendIntToken( 1 );
1453  break;
1454  case ocArcCot: // simulate ACOT(x) by (PI/2-ATAN(x))
1455  AppendNumToken( F_PI2 );
1456  break;
1457  default:;
1458  }
1459 }
1460 
1461 void XclExpFmlaCompImpl::FinishFunction( XclExpFuncData& rFuncData, sal_uInt8 nCloseSpaces )
1462 {
1463  // append missing parameters required in Excel, may modify param count
1464  AppendTrailingParam( rFuncData );
1465 
1466  // check if parameter count fits into the limits of the function
1467  sal_uInt8 nParamCount = rFuncData.GetParamCount();
1468  if( (rFuncData.GetMinParamCount() <= nParamCount) && (nParamCount <= rFuncData.GetMaxParamCount()) )
1469  {
1470  // first put the tAttrSpace tokens, they must not be included in tAttrGoto handling
1472  AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, rFuncData.GetSpaces() );
1473 
1474  // add tAttrGoto tokens for IF or CHOOSE functions
1475  switch( rFuncData.GetOpCode() )
1476  {
1477  case ocIf:
1478  case ocChoose:
1479  AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );
1480  break;
1481  default:;
1482  }
1483 
1484  // put the tFunc or tFuncVar token (or another special token, e.g. tAttrSum)
1485  AppendFuncToken( rFuncData );
1486 
1487  // update volatile flag - is set if at least one used function is volatile
1488  mxData->mbVolatile |= rFuncData.IsVolatile();
1489 
1490  // update jump tokens for specific functions, add additional tokens
1491  switch( rFuncData.GetOpCode() )
1492  {
1493  case ocIf:
1494  FinishIfFunction( rFuncData );
1495  break;
1496  case ocChoose:
1497  FinishChooseFunction( rFuncData );
1498  break;
1499 
1500  case ocCosecant: // simulate CSC(x) by (1/SIN(x))
1501  case ocSecant: // simulate SEC(x) by (1/COS(x))
1502  case ocCot: // simulate COT(x) by (1/TAN(x))
1503  case ocCosecantHyp: // simulate CSCH(x) by (1/SINH(x))
1504  case ocSecantHyp: // simulate SECH(x) by (1/COSH(x))
1505  case ocCotHyp: // simulate COTH(x) by (1/TANH(x))
1506  // For OOXML not rewritten anymore.
1507  if (GetOutput() != EXC_OUTPUT_XML_2007)
1508  {
1510  AppendParenToken();
1511  }
1512  break;
1513  case ocArcCot: // simulate ACOT(x) by (PI/2-ATAN(x))
1514  // For OOXML not rewritten anymore.
1515  if (GetOutput() != EXC_OUTPUT_XML_2007)
1516  {
1518  AppendParenToken();
1519  }
1520  break;
1521 
1522  default:;
1523  }
1524  }
1525  else
1526  mxData->mbOk = false;
1527 }
1528 
1529 void XclExpFmlaCompImpl::FinishIfFunction( XclExpFuncData& rFuncData )
1530 {
1531  sal_uInt16 nParamCount = rFuncData.GetParamCount();
1532  OSL_ENSURE( (nParamCount == 2) || (nParamCount == 3), "XclExpFmlaCompImpl::FinishIfFunction - wrong parameter count" );
1533  const ScfUInt16Vec& rAttrPos = rFuncData.GetAttrPosVec();
1534  OSL_ENSURE( nParamCount == rAttrPos.size(), "XclExpFmlaCompImpl::FinishIfFunction - wrong number of tAttr tokens" );
1535  // update tAttrIf token following the condition parameter
1536  Overwrite( rAttrPos[ 0 ] + 2, static_cast< sal_uInt16 >( rAttrPos[ 1 ] - rAttrPos[ 0 ] ) );
1537  // update the tAttrGoto tokens following true and false parameters
1538  UpdateAttrGoto( rAttrPos[ 1 ] );
1539  if( nParamCount == 3 )
1540  UpdateAttrGoto( rAttrPos[ 2 ] );
1541 }
1542 
1543 void XclExpFmlaCompImpl::FinishChooseFunction( XclExpFuncData& rFuncData )
1544 {
1545  sal_uInt16 nParamCount = rFuncData.GetParamCount();
1546  ScfUInt16Vec& rAttrPos = rFuncData.GetAttrPosVec();
1547  OSL_ENSURE( nParamCount == rAttrPos.size(), "XclExpFmlaCompImpl::FinishChooseFunction - wrong number of tAttr tokens" );
1548  // number of choices is parameter count minus 1
1549  sal_uInt16 nChoices = nParamCount - 1;
1550  // tAttrChoose token contains number of choices
1551  Overwrite( rAttrPos[ 0 ] + 2, nChoices );
1552  // cache position of the jump table (follows number of choices in tAttrChoose token)
1553  sal_uInt16 nJumpArrPos = rAttrPos[ 0 ] + 4;
1554  // size of jump table: number of choices, plus 1 for error position
1555  sal_uInt16 nJumpArrSize = 2 * (nChoices + 1);
1556  // insert the jump table into the tAttrChoose token
1557  InsertZeros( nJumpArrPos, nJumpArrSize );
1558  // update positions of tAttrGoto tokens after jump table insertion
1559  sal_uInt16 nIdx;
1560  for( nIdx = 1; nIdx < nParamCount; ++nIdx )
1561  rAttrPos[ nIdx ] = rAttrPos[ nIdx ] + nJumpArrSize;
1562  // update the tAttrGoto tokens (they contain a value one-less to real distance)
1563  for( nIdx = 1; nIdx < nParamCount; ++nIdx )
1564  UpdateAttrGoto( rAttrPos[ nIdx ] );
1565  // update the distances in the jump table
1566  Overwrite( nJumpArrPos, nJumpArrSize );
1567  for( nIdx = 1; nIdx < nParamCount; ++nIdx )
1568  Overwrite( nJumpArrPos + 2 * nIdx, static_cast< sal_uInt16 >( rAttrPos[ nIdx ] + 4 - nJumpArrPos ) );
1569 }
1570 
1571 XclExpScToken XclExpFmlaCompImpl::ProcessParam( XclExpScToken aTokData, XclExpFuncData& rFuncData )
1572 {
1573  if( rFuncData.IsCalcOnlyParam() )
1574  {
1575  // skip Calc-only parameter, stop at next ocClose or ocSep
1576  aTokData = SkipExpression( aTokData, true );
1577  rFuncData.IncParamInfoIdx();
1578  }
1579  else
1580  {
1581  // insert Excel-only parameters, modifies param count and class in rFuncData
1582  while( rFuncData.IsExcelOnlyParam() )
1583  AppendDefaultParam( rFuncData );
1584 
1585  // process the parameter, stop at next ocClose or ocSep
1586  PrepareParam( rFuncData );
1587  /* #i37355# insert tMissArg token for missing parameters --
1588  Excel import filter adds ocMissing token (handled in Factor()),
1589  but Calc itself does not do this if a new formula is entered. */
1590  switch( aTokData.GetOpCode() )
1591  {
1592  case ocSep:
1593  case ocClose: AppendMissingToken(); break; // empty parameter
1594  default: aTokData = Expression( aTokData, false, true );
1595  }
1596  // finalize the parameter and add special tokens, e.g. for IF or CHOOSE parameters
1597  if( mxData->mbOk ) FinishParam( rFuncData );
1598  }
1599  return aTokData;
1600 }
1601 
1602 void XclExpFmlaCompImpl::PrepareParam( XclExpFuncData& rFuncData )
1603 {
1604  // index of this parameter is equal to number of already finished parameters
1605  sal_uInt8 nParamIdx = rFuncData.GetParamCount();
1606 
1607  switch( rFuncData.GetOpCode() )
1608  {
1609  case ocIf:
1610  switch( nParamIdx )
1611  {
1612  // add a tAttrIf token before true-parameter (second parameter)
1613  case 1: AppendJumpToken( rFuncData, EXC_TOK_ATTR_IF ); break;
1614  // add a tAttrGoto token before false-parameter (third parameter)
1615  case 2: AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO ); break;
1616  }
1617  break;
1618 
1619  case ocChoose:
1620  switch( nParamIdx )
1621  {
1622  // do nothing for first parameter
1623  case 0: break;
1624  // add a tAttrChoose token before first value parameter (second parameter)
1625  case 1: AppendJumpToken( rFuncData, EXC_TOK_ATTR_CHOOSE ); break;
1626  // add a tAttrGoto token before other value parameters
1627  default: AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );
1628  }
1629  break;
1630 
1631  case ocArcCotHyp: // simulate ACOTH(x) by ATANH(1/(x))
1632  if( nParamIdx == 0 )
1633  AppendIntToken( 1 );
1634  break;
1635  default:;
1636  }
1637 }
1638 
1639 void XclExpFmlaCompImpl::FinishParam( XclExpFuncData& rFuncData )
1640 {
1641  // increase parameter count, update operand stack
1642  rFuncData.FinishParam( PopOperandPos() );
1643 
1644  // append more tokens for parameters of some special functions
1645  sal_uInt8 nParamIdx = rFuncData.GetParamCount() - 1;
1646  switch( rFuncData.GetOpCode() )
1647  {
1648  case ocArcCotHyp: // simulate ACOTH(x) by ATANH(1/(x))
1649  if( nParamIdx == 0 )
1650  {
1651  AppendParenToken();
1653  }
1654  break;
1655  default:;
1656  }
1657 }
1658 
1659 void XclExpFmlaCompImpl::AppendDefaultParam( XclExpFuncData& rFuncData )
1660 {
1661  // prepare parameters of some special functions
1662  PrepareParam( rFuncData );
1663 
1664  switch( rFuncData.GetOpCode() )
1665  {
1666  case ocExternal:
1667  AppendAddInCallToken( rFuncData.GetExtFuncData() );
1668  break;
1669  case ocEuroConvert:
1670  AppendEuroToolCallToken( rFuncData.GetExtFuncData() );
1671  break;
1672  case ocMacro:
1673  // Do not write the OOXML <definedName> element.
1674  if (GetOutput() == EXC_OUTPUT_XML_2007)
1675  AppendNameToken( 0 ); // dummy to keep parameter count valid
1676  else
1677  AppendMacroCallToken( rFuncData.GetExtFuncData() );
1678  break;
1679  default:
1680  {
1681  if( rFuncData.IsAddInEquivalent() )
1682  {
1683  AppendAddInCallToken( rFuncData.GetExtFuncData() );
1684  }
1685  else if( rFuncData.IsMacroFunc() )
1686  {
1687  // Do not write the OOXML <definedName> element for new _xlfn.
1688  // prefixed functions.
1689  if (GetOutput() == EXC_OUTPUT_XML_2007)
1690  AppendNameToken( 0 ); // dummy to keep parameter count valid
1691  else
1692  AppendMacroCallToken( rFuncData.GetExtFuncData() );
1693  }
1694  else
1695  {
1696  SAL_WARN( "sc.filter", "XclExpFmlaCompImpl::AppendDefaultParam - unknown opcode" );
1697  AppendMissingToken(); // to keep parameter count valid
1698  }
1699  }
1700  }
1701 
1702  // update parameter count, add special parameter tokens
1703  FinishParam( rFuncData );
1704 }
1705 
1706 void XclExpFmlaCompImpl::AppendTrailingParam( XclExpFuncData& rFuncData )
1707 {
1708  sal_uInt8 nParamCount = rFuncData.GetParamCount();
1709  switch( rFuncData.GetOpCode() )
1710  {
1711  case ocIf:
1712  if( nParamCount == 1 )
1713  {
1714  // Excel needs at least two parameters in IF function
1715  PrepareParam( rFuncData );
1716  AppendBoolToken( true );
1717  FinishParam( rFuncData );
1718  }
1719  break;
1720 
1721  case ocRound:
1722  case ocRoundUp:
1723  case ocRoundDown:
1724  if( nParamCount == 1 )
1725  {
1726  // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
1727  PrepareParam( rFuncData );
1728  AppendIntToken( 0 );
1729  FinishParam( rFuncData );
1730  }
1731  break;
1732 
1733  case ocIndex:
1734  if( nParamCount == 1 )
1735  {
1736  // INDEX function needs at least 2 parameters in Excel
1737  PrepareParam( rFuncData );
1739  FinishParam( rFuncData );
1740  }
1741  break;
1742 
1743  case ocExternal:
1744  case ocMacro:
1745  // external or macro call without parameters needs the external name reference
1746  if( nParamCount == 0 )
1747  AppendDefaultParam( rFuncData );
1748  break;
1749 
1750  case ocGammaDist:
1751  if( nParamCount == 3 )
1752  {
1753  // GAMMADIST function needs 4 parameters in Excel
1754  PrepareParam( rFuncData );
1755  AppendIntToken( 1 );
1756  FinishParam( rFuncData );
1757  }
1758  break;
1759 
1760  case ocPoissonDist:
1761  if( nParamCount == 2 )
1762  {
1763  // POISSON function needs 3 parameters in Excel
1764  PrepareParam( rFuncData );
1765  AppendIntToken( 1 );
1766  FinishParam( rFuncData );
1767  }
1768  break;
1769 
1770  case ocNormDist:
1771  if( nParamCount == 3 )
1772  {
1773  // NORMDIST function needs 4 parameters in Excel
1774  PrepareParam( rFuncData );
1775  AppendBoolToken( true );
1776  FinishParam( rFuncData );
1777  }
1778  break;
1779 
1780  case ocLogNormDist:
1781  case ocLogInv:
1782  switch( nParamCount )
1783  {
1784  // LOGNORMDIST function needs 3 parameters in Excel
1785  case 1:
1786  PrepareParam( rFuncData );
1787  AppendIntToken( 0 );
1788  FinishParam( rFuncData );
1789  [[fallthrough]]; // add next default parameter
1790  case 2:
1791  PrepareParam( rFuncData );
1792  AppendIntToken( 1 );
1793  FinishParam( rFuncData );
1794  break;
1795  default:;
1796  }
1797 
1798  break;
1799 
1800  default:
1801  // #i108420# function without parameters stored as macro call needs the external name reference
1802  if( (nParamCount == 0) && rFuncData.IsMacroFunc() )
1803  AppendDefaultParam( rFuncData );
1804 
1805  }
1806 }
1807 
1808 // reference handling ---------------------------------------------------------
1809 
1810 namespace {
1811 
1812 bool lclIsRefRel2D( const ScSingleRefData& rRefData )
1813 {
1814  return rRefData.IsColRel() || rRefData.IsRowRel();
1815 }
1816 
1817 bool lclIsRefDel2D( const ScSingleRefData& rRefData )
1818 {
1819  return rRefData.IsColDeleted() || rRefData.IsRowDeleted();
1820 }
1821 
1822 bool lclIsRefRel2D( const ScComplexRefData& rRefData )
1823 {
1824  return lclIsRefRel2D( rRefData.Ref1 ) || lclIsRefRel2D( rRefData.Ref2 );
1825 }
1826 
1827 bool lclIsRefDel2D( const ScComplexRefData& rRefData )
1828 {
1829  return lclIsRefDel2D( rRefData.Ref1 ) || lclIsRefDel2D( rRefData.Ref2 );
1830 }
1831 
1832 } // namespace
1833 
1835 {
1836  if (rRefData.IsTabDeleted())
1837  return SCTAB_INVALID;
1838 
1839  if (!rRefData.IsTabRel())
1840  // absolute address
1841  return rRefData.Tab();
1842 
1843  if (!mxData->mpScBasePos)
1844  return SCTAB_INVALID;
1845 
1846  return rRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos).Tab();
1847 }
1848 
1849 bool XclExpFmlaCompImpl::IsRef2D( const ScSingleRefData& rRefData, bool bCheck3DFlag ) const
1850 {
1851  /* rRefData.IsFlag3D() determines if sheet name is always visible, even on
1852  the own sheet. If 3D references are allowed, the passed reference does
1853  not count as 2D reference. */
1854 
1855  // conditional formatting does not allow 3D refs in xls
1856  if (mxData && mxData->mrCfg.meType == EXC_FMLATYPE_CONDFMT)
1857  return true;
1858 
1859  if (bCheck3DFlag && rRefData.IsFlag3D())
1860  return false;
1861 
1862  if (rRefData.IsTabDeleted())
1863  return false;
1864 
1865  if (rRefData.IsTabRel())
1866  return rRefData.Tab() == 0;
1867  else
1868  return rRefData.Tab() == GetCurrScTab();
1869 }
1870 
1871 bool XclExpFmlaCompImpl::IsRef2D( const ScComplexRefData& rRefData, bool bCheck3DFlag ) const
1872 {
1873  return IsRef2D(rRefData.Ref1, bCheck3DFlag) && IsRef2D(rRefData.Ref2, bCheck3DFlag);
1874 }
1875 
1877  ScSingleRefData& rRefData, XclAddress& rXclPos,
1878  bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow ) const
1879 {
1880  if( mxData->mpScBasePos )
1881  {
1882  // *** reference position exists (cell, matrix) - convert to absolute ***
1883  ScAddress aAbs = rRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos);
1884 
1885  // convert column index
1886  if (bTruncMaxCol && (aAbs.Col() == mnMaxScCol))
1887  aAbs.SetCol(mnMaxAbsCol);
1888  else if ((aAbs.Col() < 0) || (aAbs.Col() > mnMaxAbsCol))
1889  rRefData.SetColDeleted(true);
1890  rXclPos.mnCol = static_cast<sal_uInt16>(aAbs.Col()) & mnMaxColMask;
1891 
1892  // convert row index
1893  if (bTruncMaxRow && (aAbs.Row() == mnMaxScRow))
1894  aAbs.SetRow(mnMaxAbsRow);
1895  else if ((aAbs.Row() < 0) || (aAbs.Row() > mnMaxAbsRow))
1896  rRefData.SetRowDeleted(true);
1897  rXclPos.mnRow = static_cast<sal_uInt32>(aAbs.Row()) & mnMaxRowMask;
1898 
1899  // Update the reference.
1900  rRefData.SetAddress(GetRoot().GetDoc().GetSheetLimits(), aAbs, *mxData->mpScBasePos);
1901  }
1902  else
1903  {
1904  // *** no reference position (shared, names, condfmt) - use relative values ***
1905 
1906  // convert column index (2-step-cast ScsCOL->sal_Int16->sal_uInt16 to get all bits correctly)
1907  sal_Int16 nXclRelCol = static_cast<sal_Int16>(rRefData.Col());
1908  rXclPos.mnCol = static_cast< sal_uInt16 >( nXclRelCol ) & mnMaxColMask;
1909 
1910  // convert row index (2-step-cast ScsROW->sal_Int32->sal_uInt32 to get all bits correctly)
1911  sal_Int32 nXclRelRow = static_cast<sal_Int32>(rRefData.Row());
1912  rXclPos.mnRow = static_cast< sal_uInt32 >( nXclRelRow ) & mnMaxRowMask;
1913  }
1914 
1915  // flags for relative column and row
1916  if( bNatLangRef )
1917  {
1918  OSL_ENSURE( meBiff == EXC_BIFF8, "XclExpFmlaCompImpl::ConvertRefData - NLRs only for BIFF8" );
1919  // Calc does not support absolute reference mode in natural language references
1920  ::set_flag( rXclPos.mnCol, EXC_TOK_NLR_REL );
1921  }
1922  else
1923  {
1924  sal_uInt16 rnRelRow = rXclPos.mnRow;
1925  sal_uInt16& rnRelField = (meBiff <= EXC_BIFF5) ? rnRelRow : rXclPos.mnCol;
1926  ::set_flag( rnRelField, EXC_TOK_REF_COLREL, rRefData.IsColRel() );
1927  ::set_flag( rnRelField, EXC_TOK_REF_ROWREL, rRefData.IsRowRel() );
1928  }
1929 }
1930 
1932  ScComplexRefData& rRefData, XclRange& rXclRange, bool bNatLangRef ) const
1933 {
1934  // convert start and end of the range
1935  ConvertRefData( rRefData.Ref1, rXclRange.maFirst, bNatLangRef, false, false );
1936  bool bTruncMaxCol = !rRefData.Ref1.IsColDeleted() && (rXclRange.maFirst.mnCol == 0);
1937  bool bTruncMaxRow = !rRefData.Ref1.IsRowDeleted() && (rXclRange.maFirst.mnRow == 0);
1938  ConvertRefData( rRefData.Ref2, rXclRange.maLast, bNatLangRef, bTruncMaxCol, bTruncMaxRow );
1939 }
1940 
1942 {
1943  if( mxData->mpRefLog )
1944  {
1945  mxData->mpRefLog->emplace_back();
1946  return &mxData->mpRefLog->back();
1947  }
1948  return nullptr;
1949 }
1950 
1951 void XclExpFmlaCompImpl::ProcessCellRef( const XclExpScToken& rTokData )
1952 {
1953  // get the Excel address components, adjust internal data in aRefData
1954  bool bNatLangRef = (meBiff == EXC_BIFF8) && mxData->mpScBasePos && (rTokData.GetOpCode() == ocColRowName);
1955  ScSingleRefData aRefData = *rTokData.mpScToken->GetSingleRef();
1957  ConvertRefData( aRefData, aXclPos, bNatLangRef, false, false );
1958 
1959  if( bNatLangRef )
1960  {
1961  OSL_ENSURE( aRefData.IsColRel() != aRefData.IsRowRel(),
1962  "XclExpFmlaCompImpl::ProcessCellRef - broken natural language reference" );
1963  // create tNlr token for natural language reference
1964  sal_uInt8 nSubId = aRefData.IsColRel() ? EXC_TOK_NLR_COLV : EXC_TOK_NLR_ROWV;
1965  AppendOperandTokenId( EXC_TOKID_NLR, rTokData.mnSpaces );
1966  Append( nSubId );
1967  AppendAddress( aXclPos );
1968  }
1969  else
1970  {
1971  // store external cell contents in CRN records
1972  if( mxData->mrCfg.mbFromCell && mxData->mpLinkMgr && mxData->mpScBasePos )
1973  mxData->mpLinkMgr->StoreCell(aRefData, *mxData->mpScBasePos);
1974 
1975  // create the tRef, tRefErr, tRefN, tRef3d, or tRefErr3d token
1976  if (!mxData->mrCfg.mb3DRefOnly && IsRef2D(aRefData, mxData->mpLinkMgr != nullptr))
1977  {
1978  // 2D reference (not in defined names, but allowed in range lists)
1979  sal_uInt8 nBaseId = (!mxData->mpScBasePos && lclIsRefRel2D( aRefData )) ? EXC_TOKID_REFN :
1980  (lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR : EXC_TOKID_REF);
1981  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
1982  AppendAddress( aXclPos );
1983  }
1984  else if( mxData->mpLinkMgr ) // 3D reference
1985  {
1986  // 1-based EXTERNSHEET index and 0-based Excel sheet index
1987  sal_uInt16 nExtSheet, nXclTab;
1988  mxData->mpLinkMgr->FindExtSheet( nExtSheet, nXclTab, GetScTab( aRefData ), GetNewRefLogEntry() );
1989  // write the token
1990  sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
1991  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
1992  Append( nExtSheet );
1993  if( meBiff <= EXC_BIFF5 )
1994  {
1995  Append( 0, 8 );
1996  Append( nXclTab );
1997  Append( nXclTab );
1998  }
1999  AppendAddress( aXclPos );
2000  }
2001  else
2002  {
2003  // 3D ref in cond. format, or 2D ref in name
2004  AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
2005  }
2006  }
2007 }
2008 
2009 void XclExpFmlaCompImpl::ProcessRangeRef( const XclExpScToken& rTokData )
2010 {
2011  // get the Excel address components, adjust internal data in aRefData
2012  ScComplexRefData aRefData = *rTokData.mpScToken->GetDoubleRef();
2013  XclRange aXclRange( ScAddress::UNINITIALIZED );
2014  ConvertRefData( aRefData, aXclRange, false );
2015 
2016  // store external cell contents in CRN records
2017  if( mxData->mrCfg.mbFromCell && mxData->mpLinkMgr && mxData->mpScBasePos )
2018  mxData->mpLinkMgr->StoreCellRange(aRefData, *mxData->mpScBasePos);
2019 
2020  // create the tArea, tAreaErr, tAreaN, tArea3d, or tAreaErr3d token
2021  if (!mxData->mrCfg.mb3DRefOnly && IsRef2D(aRefData, mxData->mpLinkMgr != nullptr))
2022  {
2023  // 2D reference (not in name formulas, but allowed in range lists)
2024  sal_uInt8 nBaseId = (!mxData->mpScBasePos && lclIsRefRel2D( aRefData )) ? EXC_TOKID_AREAN :
2025  (lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR : EXC_TOKID_AREA);
2026  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
2027  AppendRange( aXclRange );
2028  }
2029  else if( mxData->mpLinkMgr ) // 3D reference
2030  {
2031  // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
2032  sal_uInt16 nExtSheet, nFirstXclTab, nLastXclTab;
2033  mxData->mpLinkMgr->FindExtSheet( nExtSheet, nFirstXclTab, nLastXclTab,
2034  GetScTab( aRefData.Ref1 ), GetScTab( aRefData.Ref2 ), GetNewRefLogEntry() );
2035  // write the token
2036  sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
2037  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
2038  Append( nExtSheet );
2039  if( meBiff <= EXC_BIFF5 )
2040  {
2041  Append( 0, 8 );
2042  Append( nFirstXclTab );
2043  Append( nLastXclTab );
2044  }
2045  AppendRange( aXclRange );
2046  }
2047  else
2048  {
2049  // 3D ref in cond. format, or 2D ref in name
2050  AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
2051  }
2052 }
2053 
2054 void XclExpFmlaCompImpl::ProcessExternalCellRef( const XclExpScToken& rTokData )
2055 {
2056  if( mxData->mpLinkMgr )
2057  {
2058  // get the Excel address components, adjust internal data in aRefData
2059  ScSingleRefData aRefData = *rTokData.mpScToken->GetSingleRef();
2061  ConvertRefData( aRefData, aXclPos, false, false, false );
2062 
2063  // store external cell contents in CRN records
2064  sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
2065  OUString aTabName = rTokData.mpScToken->GetString().getString();
2066  if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos )
2067  mxData->mpLinkMgr->StoreCell(nFileId, aTabName, aRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos));
2068 
2069  // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
2070  sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
2071  mxData->mpLinkMgr->FindExtSheet( nFileId, aTabName, 1, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry() );
2072  // write the token
2073  sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
2074  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
2075  Append( nExtSheet );
2076  if( meBiff <= EXC_BIFF5 )
2077  {
2078  Append( 0, 8 );
2079  Append( nFirstSBTab );
2080  Append( nLastSBTab );
2081  }
2082  AppendAddress( aXclPos );
2083  }
2084  else
2085  {
2086  AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
2087  }
2088 }
2089 
2090 void XclExpFmlaCompImpl::ProcessExternalRangeRef( const XclExpScToken& rTokData )
2091 {
2092  if( mxData->mpLinkMgr )
2093  {
2094  // get the Excel address components, adjust internal data in aRefData
2095  ScComplexRefData aRefData = *rTokData.mpScToken->GetDoubleRef();
2096  XclRange aXclRange( ScAddress::UNINITIALIZED );
2097  ConvertRefData( aRefData, aXclRange, false );
2098 
2099  // store external cell contents in CRN records
2100  sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
2101  OUString aTabName = rTokData.mpScToken->GetString().getString();
2102  if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos )
2103  mxData->mpLinkMgr->StoreCellRange(nFileId, aTabName, aRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos));
2104 
2105  // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
2106  sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
2107  sal_uInt16 nTabSpan = static_cast<sal_uInt16>(aRefData.Ref2.Tab() - aRefData.Ref1.Tab() + 1);
2108  mxData->mpLinkMgr->FindExtSheet(
2109  nFileId, aTabName, nTabSpan, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry());
2110  // write the token
2111  sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
2112  AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
2113  Append( nExtSheet );
2114  if( meBiff <= EXC_BIFF5 )
2115  {
2116  Append( 0, 8 );
2117  Append( nFirstSBTab );
2118  Append( nLastSBTab );
2119  }
2120  AppendRange( aXclRange );
2121  }
2122  else
2123  {
2124  AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
2125  }
2126 }
2127 
2128 void XclExpFmlaCompImpl::ProcessDefinedName( const XclExpScToken& rTokData )
2129 {
2130  sal_Int16 nSheet = rTokData.mpScToken->GetSheet();
2131  SCTAB nTab = (nSheet < 0 ? SCTAB_GLOBAL : nSheet);
2132 
2133  XclExpNameManager& rNameMgr = GetNameManager();
2134  sal_uInt16 nNameIdx = rNameMgr.InsertName(nTab, rTokData.mpScToken->GetIndex(), GetCurrScTab());
2135  if( nNameIdx != 0 )
2136  {
2137  // global names always with tName token, local names dependent on config
2138  SCTAB nScTab = rNameMgr.GetScTab( nNameIdx );
2139  if( (nScTab == SCTAB_GLOBAL) || (!mxData->mrCfg.mb3DRefOnly && (nScTab == GetCurrScTab())) )
2140  {
2141  AppendNameToken( nNameIdx, rTokData.mnSpaces );
2142  }
2143  else if( mxData->mpLinkMgr )
2144  {
2145  // use the same special EXTERNNAME to refer to any local name
2146  sal_uInt16 nExtSheet = mxData->mpLinkMgr->FindExtSheet( EXC_EXTSH_OWNDOC );
2147  AppendNameXToken( nExtSheet, nNameIdx, rTokData.mnSpaces );
2148  }
2149  else
2150  AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
2151  // volatile names (containing volatile functions)
2152  mxData->mbVolatile |= rNameMgr.IsVolatile( nNameIdx );
2153  }
2154  else
2155  AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
2156 }
2157 
2158 void XclExpFmlaCompImpl::ProcessExternalName( const XclExpScToken& rTokData )
2159 {
2160  if( mxData->mpLinkMgr )
2161  {
2163  sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
2164  OUString aName = rTokData.mpScToken->GetString().getString();
2165  ScExternalRefCache::TokenArrayRef xArray = rExtRefMgr.getRangeNameTokens( nFileId, aName );
2166  if( xArray )
2167  {
2168  // store external cell contents in CRN records
2169  if( mxData->mpScBasePos )
2170  {
2171  FormulaTokenArrayPlainIterator aIter(*xArray);
2172  for( FormulaToken* pScToken = aIter.First(); pScToken; pScToken = aIter.Next() )
2173  {
2174  if( pScToken->IsExternalRef() )
2175  {
2176  switch( pScToken->GetType() )
2177  {
2178  case svExternalSingleRef:
2179  {
2180  ScSingleRefData aRefData = *pScToken->GetSingleRef();
2181  mxData->mpLinkMgr->StoreCell(
2182  nFileId, pScToken->GetString().getString(), aRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos));
2183  }
2184  break;
2185  case svExternalDoubleRef:
2186  {
2187  ScComplexRefData aRefData = *pScToken->GetDoubleRef();
2188  mxData->mpLinkMgr->StoreCellRange(
2189  nFileId, pScToken->GetString().getString(), aRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos));
2190  }
2191  break;
2192  default:
2193  ; // nothing, avoid compiler warning
2194  }
2195  }
2196  }
2197  }
2198 
2199  // insert the new external name and create the tNameX token
2200  sal_uInt16 nExtSheet = 0, nExtName = 0;
2201  const OUString* pFile = rExtRefMgr.getExternalFileName( nFileId );
2202  if( pFile && mxData->mpLinkMgr->InsertExtName( nExtSheet, nExtName, *pFile, aName, xArray ) )
2203  {
2204  AppendNameXToken( nExtSheet, nExtName, rTokData.mnSpaces );
2205  return;
2206  }
2207  }
2208  }
2209 
2210  // on any error: create a #NAME? error
2211  AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
2212 }
2213 
2214 // token vector ---------------------------------------------------------------
2215 
2216 void XclExpFmlaCompImpl::PushOperandPos( sal_uInt16 nTokPos )
2217 {
2218  mxData->maOpPosStack.push_back( nTokPos );
2219 }
2220 
2221 void XclExpFmlaCompImpl::PushOperatorPos( sal_uInt16 nTokPos, const XclExpOperandListRef& rxOperands )
2222 {
2223  PushOperandPos( nTokPos );
2224  OSL_ENSURE( rxOperands, "XclExpFmlaCompImpl::AppendOperatorTokenId - missing operand list" );
2225  if( mxData->maOpListVec.size() <= nTokPos )
2226  mxData->maOpListVec.resize( nTokPos + 1, XclExpOperandListRef() );
2227  mxData->maOpListVec[ nTokPos ] = rxOperands;
2228 }
2229 
2231 {
2232  OSL_ENSURE( !mxData->mbOk || !mxData->maOpPosStack.empty(), "XclExpFmlaCompImpl::PopOperandPos - token stack broken" );
2233  mxData->mbOk &= !mxData->maOpPosStack.empty();
2234  if( mxData->mbOk )
2235  {
2236  sal_uInt16 nTokPos = mxData->maOpPosStack.back();
2237  mxData->maOpPosStack.pop_back();
2238  return nTokPos;
2239  }
2240  return 0;
2241 }
2242 
2243 namespace {
2244 
2245 void lclAppend( ScfUInt8Vec& orVector, sal_uInt16 nData )
2246 {
2247  orVector.resize( orVector.size() + 2 );
2248  ShortToSVBT16( nData, &*(orVector.end() - 2) );
2249 }
2250 
2251 void lclAppend( ScfUInt8Vec& orVector, sal_uInt32 nData )
2252 {
2253  orVector.resize( orVector.size() + 4 );
2254  UInt32ToSVBT32( nData, &*(orVector.end() - 4) );
2255 }
2256 
2257 void lclAppend( ScfUInt8Vec& orVector, double fData )
2258 {
2259  orVector.resize( orVector.size() + 8 );
2260  DoubleToSVBT64( fData, &*(orVector.end() - 8) );
2261 }
2262 
2263 void lclAppend( ScfUInt8Vec& orVector, const XclExpRoot& rRoot, const OUString& rString, XclStrFlags nStrFlags )
2264 {
2265  XclExpStringRef xXclStr = XclExpStringHelper::CreateString( rRoot, rString, nStrFlags, EXC_TOK_STR_MAXLEN );
2266  size_t nSize = orVector.size();
2267  orVector.resize( nSize + xXclStr->GetSize() );
2268  xXclStr->WriteToMem( &orVector[ nSize ] );
2269 }
2270 
2271 } // namespace
2272 
2274 {
2275  mxData->maTokVec.push_back( nData );
2276 }
2277 
2278 void XclExpFmlaCompImpl::Append( sal_uInt8 nData, size_t nCount )
2279 {
2280  mxData->maTokVec.resize( mxData->maTokVec.size() + nCount, nData );
2281 }
2282 
2283 void XclExpFmlaCompImpl::Append( sal_uInt16 nData )
2284 {
2285  lclAppend( mxData->maTokVec, nData );
2286 }
2287 
2288 void XclExpFmlaCompImpl::Append( sal_uInt32 nData )
2289 {
2290  lclAppend( mxData->maTokVec, nData );
2291 }
2292 
2293 void XclExpFmlaCompImpl::Append( double fData )
2294 {
2295  lclAppend( mxData->maTokVec, fData );
2296 }
2297 
2298 void XclExpFmlaCompImpl::Append( const OUString& rString )
2299 {
2300  lclAppend( mxData->maTokVec, GetRoot(), rString, XclStrFlags::EightBitLength );
2301 }
2302 
2304 {
2305  Append( static_cast<sal_uInt16>(rXclPos.mnRow) );
2306  if( meBiff <= EXC_BIFF5 )
2307  Append( static_cast< sal_uInt8 >( rXclPos.mnCol ) );
2308  else
2309  Append( rXclPos.mnCol );
2310 }
2311 
2313 {
2314  Append( static_cast<sal_uInt16>(rXclRange.maFirst.mnRow) );
2315  Append( static_cast<sal_uInt16>(rXclRange.maLast.mnRow) );
2316  if( meBiff <= EXC_BIFF5 )
2317  {
2318  Append( static_cast< sal_uInt8 >( rXclRange.maFirst.mnCol ) );
2319  Append( static_cast< sal_uInt8 >( rXclRange.maLast.mnCol ) );
2320  }
2321  else
2322  {
2323  Append( rXclRange.maFirst.mnCol );
2324  Append( rXclRange.maLast.mnCol );
2325  }
2326 }
2327 
2329 {
2330  if( nCount > 0 )
2331  {
2334  Append( nType );
2335  Append( nCount );
2336  }
2337 }
2338 
2340 {
2342  PushOperandPos( GetSize() );
2343  Append( nTokenId );
2344 }
2345 
2346 void XclExpFmlaCompImpl::AppendIntToken( sal_uInt16 nValue, sal_uInt8 nSpaces )
2347 {
2348  AppendOperandTokenId( EXC_TOKID_INT, nSpaces );
2349  Append( nValue );
2350 }
2351 
2352 void XclExpFmlaCompImpl::AppendNumToken( double fValue, sal_uInt8 nSpaces )
2353 {
2354  AppendOperandTokenId( EXC_TOKID_NUM, nSpaces );
2355  Append( fValue );
2356 }
2357 
2359 {
2362 }
2363 
2365 {
2366  AppendOperandTokenId( EXC_TOKID_ERR, nSpaces );
2367  Append( nErrCode );
2368 }
2369 
2371 {
2373 }
2374 
2375 void XclExpFmlaCompImpl::AppendNameToken( sal_uInt16 nNameIdx, sal_uInt8 nSpaces )
2376 {
2377  if( nNameIdx > 0 )
2378  {
2380  Append( nNameIdx );
2381  Append( 0, (meBiff <= EXC_BIFF5) ? 12 : 2 );
2382  }
2383  else
2385 }
2386 
2387 void XclExpFmlaCompImpl::AppendMissingNameToken( const OUString& rName, sal_uInt8 nSpaces )
2388 {
2389  sal_uInt16 nNameIdx = GetNameManager().InsertRawName( rName );
2390  AppendNameToken( nNameIdx, nSpaces );
2391 }
2392 
2393 void XclExpFmlaCompImpl::AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces )
2394 {
2396  Append( nExtSheet );
2397  if( meBiff <= EXC_BIFF5 )
2398  Append( 0, 8 );
2399  Append( nExtName );
2400  Append( 0, (meBiff <= EXC_BIFF5) ? 12 : 2 );
2401 }
2402 
2403 void XclExpFmlaCompImpl::AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData )
2404 {
2405  sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( rExtFuncData.maFuncName, rExtFuncData.mbVBasic, true, rExtFuncData.mbHidden );
2406  AppendNameToken( nNameIdx );
2407 }
2408 
2409 void XclExpFmlaCompImpl::AppendAddInCallToken( const XclExpExtFuncData& rExtFuncData )
2410 {
2411  OUString aXclFuncName;
2412  if( mxData->mpLinkMgr && ScGlobal::GetAddInCollection()->GetExcelName( rExtFuncData.maFuncName, GetUILanguage(), aXclFuncName ) )
2413  {
2414  sal_uInt16 nExtSheet, nExtName;
2415  if( mxData->mpLinkMgr->InsertAddIn( nExtSheet, nExtName, aXclFuncName ) )
2416  {
2417  AppendNameXToken( nExtSheet, nExtName );
2418  return;
2419  }
2420  }
2421  AppendMacroCallToken( rExtFuncData );
2422 }
2423 
2424 void XclExpFmlaCompImpl::AppendEuroToolCallToken( const XclExpExtFuncData& rExtFuncData )
2425 {
2426  sal_uInt16 nExtSheet(0), nExtName(0);
2427  if( mxData->mpLinkMgr && mxData->mpLinkMgr->InsertEuroTool( nExtSheet, nExtName, rExtFuncData.maFuncName ) )
2428  AppendNameXToken( nExtSheet, nExtName );
2429  else
2430  AppendMacroCallToken( rExtFuncData );
2431 }
2432 
2433 void XclExpFmlaCompImpl::AppendOperatorTokenId( sal_uInt8 nTokenId, const XclExpOperandListRef& rxOperands, sal_uInt8 nSpaces )
2434 {
2436  PushOperatorPos( GetSize(), rxOperands );
2437  Append( nTokenId );
2438 }
2439 
2441 {
2442  XclExpOperandListRef xOperands = std::make_shared<XclExpOperandList>();
2443  xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, true );
2444  AppendOperatorTokenId( nTokenId, xOperands, nSpaces );
2445 }
2446 
2448 {
2449  XclExpOperandListRef xOperands = std::make_shared<XclExpOperandList>();
2450  xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, bValType );
2451  xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, bValType );
2452  AppendOperatorTokenId( nTokenId, xOperands, nSpaces );
2453 }
2454 
2455 void XclExpFmlaCompImpl::AppendLogicalOperatorToken( sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount )
2456 {
2457  XclExpOperandListRef xOperands = std::make_shared<XclExpOperandList>();
2458  for( sal_uInt8 nOpIdx = 0; nOpIdx < nOpCount; ++nOpIdx )
2459  xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPX, false );
2461  Append( nOpCount );
2462  Append( nXclFuncIdx );
2463 }
2464 
2465 void XclExpFmlaCompImpl::AppendFuncToken( const XclExpFuncData& rFuncData )
2466 {
2467  sal_uInt16 nXclFuncIdx = rFuncData.GetXclFuncIdx();
2468  sal_uInt8 nParamCount = rFuncData.GetParamCount();
2469  sal_uInt8 nRetClass = rFuncData.GetReturnClass();
2470 
2471  if( (nXclFuncIdx == EXC_FUNCID_SUM) && (nParamCount == 1) )
2472  {
2473  // SUM with only one parameter
2474  AppendOperatorTokenId( EXC_TOKID_ATTR, rFuncData.GetOperandList() );
2476  Append( sal_uInt16( 0 ) );
2477  }
2478  else if( rFuncData.IsFixedParamCount() )
2479  {
2480  // fixed number of parameters
2481  AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNC, nRetClass ), rFuncData.GetOperandList() );
2482  Append( nXclFuncIdx );
2483  }
2484  else
2485  {
2486  // variable number of parameters
2487  AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNCVAR, nRetClass ), rFuncData.GetOperandList() );
2488  Append( nParamCount );
2489  Append( nXclFuncIdx );
2490  }
2491 }
2492 
2494 {
2498 }
2499 
2500 void XclExpFmlaCompImpl::AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType )
2501 {
2502  // store the start position of the token
2503  rFuncData.AppendAttrPos( GetSize() );
2504  // create the tAttr token
2506  Append( nAttrType );
2507  Append( sal_uInt16( 0 ) ); // placeholder that will be updated later
2508 }
2509 
2510 void XclExpFmlaCompImpl::InsertZeros( sal_uInt16 nInsertPos, sal_uInt16 nInsertSize )
2511 {
2512  // insert zeros into the token array
2513  OSL_ENSURE( nInsertPos < mxData->maTokVec.size(), "XclExpFmlaCompImpl::Insert - invalid position" );
2514  mxData->maTokVec.insert( mxData->maTokVec.begin() + nInsertPos, nInsertSize, 0 );
2515 
2516  // update positions of operands waiting for an operator
2517  for( auto& rOpPos : mxData->maOpPosStack )
2518  if( nInsertPos <= rOpPos )
2519  rOpPos += nInsertSize;
2520 
2521  // update operand lists of all operator tokens
2522  if( nInsertPos < mxData->maOpListVec.size() )
2523  mxData->maOpListVec.insert( mxData->maOpListVec.begin() + nInsertPos, nInsertSize, XclExpOperandListRef() );
2524  for( auto& rxOpList : mxData->maOpListVec )
2525  if( rxOpList )
2526  for( auto& rOp : *rxOpList )
2527  if( nInsertPos <= rOp.mnTokPos )
2528  rOp.mnTokPos += nInsertSize;
2529 }
2530 
2531 void XclExpFmlaCompImpl::Overwrite( sal_uInt16 nWriteToPos, sal_uInt16 nOffset )
2532 {
2533  OSL_ENSURE( o3tl::make_unsigned( nWriteToPos + 1 ) < mxData->maTokVec.size(), "XclExpFmlaCompImpl::Overwrite - invalid position" );
2534  ShortToSVBT16( nOffset, &mxData->maTokVec[ nWriteToPos ] );
2535 }
2536 
2537 void XclExpFmlaCompImpl::UpdateAttrGoto( sal_uInt16 nAttrPos )
2538 {
2539  /* tAttrGoto contains distance from end of tAttr token to position behind
2540  the function token (for IF or CHOOSE function), which is currently at
2541  the end of the token array. Additionally this distance is decreased by
2542  one, for whatever reason. So we have to subtract 4 and 1 from the
2543  distance between the tAttr token start and the end of the token array. */
2544  Overwrite( nAttrPos + 2, static_cast< sal_uInt16 >( GetSize() - nAttrPos - 5 ) );
2545 }
2546 
2547 bool XclExpFmlaCompImpl::IsSpaceToken( sal_uInt16 nPos ) const
2548 {
2549  return
2550  (o3tl::make_unsigned( nPos + 4 ) <= mxData->maTokVec.size()) &&
2551  (mxData->maTokVec[ nPos ] == EXC_TOKID_ATTR) &&
2552  (mxData->maTokVec[ nPos + 1 ] == EXC_TOK_ATTR_SPACE);
2553 }
2554 
2556 {
2557  // remove trailing tParen token
2558  if( !mxData->maTokVec.empty() && (mxData->maTokVec.back() == EXC_TOKID_PAREN) )
2559  mxData->maTokVec.pop_back();
2560  // remove remaining tAttrSpace tokens
2561  while( (mxData->maTokVec.size() >= 4) && IsSpaceToken( GetSize() - 4 ) )
2562  mxData->maTokVec.erase( mxData->maTokVec.end() - 4, mxData->maTokVec.end() );
2563 }
2564 
2566 {
2567  mxData->maExtDataVec.push_back( nData );
2568 }
2569 
2570 void XclExpFmlaCompImpl::AppendExt( sal_uInt8 nData, size_t nCount )
2571 {
2572  mxData->maExtDataVec.resize( mxData->maExtDataVec.size() + nCount, nData );
2573 }
2574 
2575 void XclExpFmlaCompImpl::AppendExt( sal_uInt16 nData )
2576 {
2577  lclAppend( mxData->maExtDataVec, nData );
2578 }
2579 
2580 void XclExpFmlaCompImpl::AppendExt( double fData )
2581 {
2582  lclAppend( mxData->maExtDataVec, fData );
2583 }
2584 
2585 void XclExpFmlaCompImpl::AppendExt( const OUString& rString )
2586 {
2587  lclAppend( mxData->maExtDataVec, GetRoot(), rString, (meBiff == EXC_BIFF8) ? XclStrFlags::NONE : XclStrFlags::EightBitLength );
2588 }
2589 
2590 namespace {
2591 
2592 void lclInitOwnTab( ScSingleRefData& rRef, const ScAddress& rScPos, SCTAB nCurrScTab, bool b3DRefOnly )
2593 {
2594  if( b3DRefOnly )
2595  {
2596  // no reduction to 2D reference, if global link manager is used
2597  rRef.SetFlag3D(true);
2598  }
2599  else if( rScPos.Tab() == nCurrScTab )
2600  {
2601  rRef.SetRelTab(0);
2602  }
2603 }
2604 
2605 void lclPutCellToTokenArray( ScTokenArray& rScTokArr, const ScAddress& rScPos, SCTAB nCurrScTab, bool b3DRefOnly )
2606 {
2607  ScSingleRefData aRef;
2608  aRef.InitAddress( rScPos );
2609  lclInitOwnTab( aRef, rScPos, nCurrScTab, b3DRefOnly );
2610  rScTokArr.AddSingleReference( aRef );
2611 }
2612 
2613 void lclPutRangeToTokenArray( ScTokenArray& rScTokArr, const ScRange& rScRange, SCTAB nCurrScTab, bool b3DRefOnly )
2614 {
2615  if( rScRange.aStart == rScRange.aEnd )
2616  {
2617  lclPutCellToTokenArray( rScTokArr, rScRange.aStart, nCurrScTab, b3DRefOnly );
2618  }
2619  else
2620  {
2621  ScComplexRefData aRef;
2622  aRef.InitRange( rScRange );
2623  lclInitOwnTab( aRef.Ref1, rScRange.aStart, nCurrScTab, b3DRefOnly );
2624  lclInitOwnTab( aRef.Ref2, rScRange.aEnd, nCurrScTab, b3DRefOnly );
2625  rScTokArr.AddDoubleReference( aRef );
2626  }
2627 }
2628 
2629 } // namespace
2630 
2632  XclExpRoot( rRoot ),
2633  mxImpl( std::make_shared<XclExpFmlaCompImpl>( rRoot ) )
2634 {
2635 }
2636 
2638 {
2639 }
2640 
2642  XclFormulaType eType, const ScTokenArray& rScTokArr,
2643  const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
2644 {
2645  return mxImpl->CreateFormula( eType, rScTokArr, pScBasePos, pRefLog );
2646 }
2647 
2649 {
2650  ScTokenArray aScTokArr(GetRoot().GetDoc());
2651  lclPutCellToTokenArray( aScTokArr, rScPos, GetCurrScTab(), mxImpl->Is3DRefOnly( eType ) );
2652  return mxImpl->CreateFormula( eType, aScTokArr );
2653 }
2654 
2656 {
2657  ScTokenArray aScTokArr(GetRoot().GetDoc());
2658  lclPutRangeToTokenArray( aScTokArr, rScRange, GetCurrScTab(), mxImpl->Is3DRefOnly( eType ) );
2659  return mxImpl->CreateFormula( eType, aScTokArr );
2660 }
2661 
2663 {
2664  size_t nCount = rScRanges.size();
2665  if( nCount == 0 )
2666  return XclTokenArrayRef();
2667 
2668  ScTokenArray aScTokArr(GetRoot().GetDoc());
2669  SCTAB nCurrScTab = GetCurrScTab();
2670  bool b3DRefOnly = mxImpl->Is3DRefOnly( eType );
2671  for( size_t nIdx = 0; nIdx < nCount; ++nIdx )
2672  {
2673  if( nIdx > 0 )
2674  aScTokArr.AddOpCode( ocUnion );
2675  lclPutRangeToTokenArray( aScTokArr, rScRanges[ nIdx ], nCurrScTab, b3DRefOnly );
2676  }
2677  return mxImpl->CreateFormula( eType, aScTokArr );
2678 }
2679 
2681 {
2682  return mxImpl->CreateErrorFormula( nErrCode );
2683 }
2684 
2686  sal_uInt8 nTokenId, const XclAddress& rXclPos )
2687 {
2688  return mxImpl->CreateSpecialRefFormula( nTokenId, rXclPos );
2689 }
2690 
2692  sal_uInt16 nExtSheet, sal_uInt16 nExtName )
2693 {
2694  return mxImpl->CreateNameXFormula( nExtSheet, nExtName );
2695 }
2696 
2698 {
2699  return mxImpl->IsRef2D(rRefData, true);
2700 }
2701 
2703 {
2704  return mxImpl->IsRef2D(rRefData, true);
2705 }
2706 
2707 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsTabRel() const
Definition: refdata.hxx:69
const sal_uInt8 EXC_TOKID_PAREN
Percent sign.
Definition: xlformula.hxx:72
const sal_uInt8 EXC_TOKID_AREAERR
Deleted 2D cell reference.
Definition: xlformula.hxx:97
void AppendNumToken(double fValue, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2352
ocChoose
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:112
const SCCOL mnMaxScCol
Maximum row index.
Definition: xeformula.cxx:466
formula::FormulaToken * AddDoubleReference(const ScComplexRefData &rRef)
Definition: token.cxx:2214
ocStop
svString
void PushOperandPos(sal_uInt16 nTokPos)
Definition: xeformula.cxx:2216
const sal_uInt8 EXC_FUNC_MAXPARAM
Definition: xlformula.hxx:284
static void ChangeTokenClass(sal_uInt8 &rnTokenId, sal_uInt8 nTokenClass)
Changes the token class in the passed classified token ID.
Definition: xlformula.hxx:544
SCCOL Col() const
Definition: refdata.cxx:247
StackVar
::std::vector< sal_uInt8 > ScfUInt8Vec
Definition: ftools.hxx:253
static SC_DLLPUBLIC ScUnoAddInCollection * GetAddInCollection()
Definition: global.cxx:269
const sal_uInt8 EXC_TOKID_ARRAY
Floating-point constant.
Definition: xlformula.hxx:86
void ProcessDdeLink(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1265
XclExpScToken MulDivTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1047
void ProcessDefinedName(const XclExpScToken &rTokData)
Definition: xeformula.cxx:2128
bool IsTabDeleted() const
Definition: refdata.hxx:86
const sal_uInt8 EXC_TOKID_LE
Less than operator.
Definition: xlformula.hxx:61
OUString getString() const
XclBiff
An enumeration for all Excel file format types (BIFF types).
Definition: xlconst.hxx:29
ScAddress aStart
Definition: address.hxx:499
const sal_uInt8 EXC_ERR_NA
Definition: xlconst.hxx:110
void AppendNameXToken(sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2393
const sal_uInt8 EXC_TOKID_STR
Missing argument.
Definition: xlformula.hxx:74
XclExpRefLogEntry()
Calc index of the last sheet.
Definition: xeformula.cxx:43
MS Excel binary .xls.
Definition: xlconst.hxx:43
void AppendLogicalOperatorToken(sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount)
Definition: xeformula.cxx:2455
ocArcCotHyp
ocName
void ProcessExternalRangeRef(const XclExpScToken &rTokData)
Definition: xeformula.cxx:2090
ocCosecantHyp
SCROW Row() const
Definition: address.hxx:261
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
SC_DLLPUBLIC ScRange toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:493
Single reference (one address) into the sheet.
Definition: refdata.hxx:29
XclStrFlags
Flags used to specify import/export mode of strings.
Definition: xlstring.hxx:28
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:126
void AppendNameToken(sal_uInt16 nNameIdx, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2375
void PushOperatorPos(sal_uInt16 nTokPos, const XclExpOperandListRef &rxOperands)
Definition: xeformula.cxx:2221
const sal_uInt8 EXC_TOK_NLR_ROWV
NLR: Column index.
Definition: xlformula.hxx:143
const sal_uInt8 EXC_TOKCLASS_REF
00-1F: Base tokens.
Definition: xlformula.hxx:43
bool mbValType
Token class conversion type.
Definition: xlformula.hxx:279
const sal_uInt8 EXC_TOKID_REF
Defined name.
Definition: xlformula.hxx:90
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:2339
const sal_uInt8 EXC_TOKID_REFERR3D
3D area reference.
Definition: xlformula.hxx:106
XclExpLinkManager & GetLocalLinkManager() const
Returns the local link manager for the current sheet.
Definition: xeroot.cxx:137
const sal_uInt8 EXC_TOKID_CONCAT
Power operator.
Definition: xlformula.hxx:59
const sal_uInt8 EXC_TOKID_GE
Equal operator.
Definition: xlformula.hxx:63
ScAddress toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:193
void AppendFuncToken(const XclExpFuncData &rFuncData)
Definition: xeformula.cxx:2465
const sal_uInt8 EXC_TOKID_MEMFUNC
Constant reference subexpression without result.
Definition: xlformula.hxx:95
XclExpScToken OrTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:968
Convert tokens to VAL class.
Definition: xlformula.hxx:189
void ProcessBad(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1233
XclExpScToken AddSubTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1032
const sal_uInt8 EXC_TOK_ATTR_GOTO
Jump array of CHOOSE function.
Definition: xlformula.hxx:119
void AppendIntToken(sal_uInt16 nValue, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2346
Conditional format.
Definition: xlformula.hxx:165
ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const
: If bString the ScMatrixValue->pS may still be NULL to indicate an empty string! ...
Definition: scmatrix.cxx:3039
void SetRelTab(SCTAB nVal)
Definition: refdata.cxx:99
ocOpen
const sal_uInt8 EXC_TOKID_LT
String concatenation operator.
Definition: xlformula.hxx:60
Parameter supported by Calc only.
Definition: xlformula.hxx:181
ocCosecant
#define F_PI2
bool IsMacroFunc() const
Returns true, if the function is simulated by a macro call.
Definition: xlformula.hxx:332
formula::FormulaToken * AddSingleReference(const ScSingleRefData &rRef)
ScSingleRefToken with ocPush.
Definition: token.cxx:2204
void UpdateAttrGoto(sal_uInt16 nAttrPos)
Definition: xeformula.cxx:2537
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.
void AppendAddInCallToken(const XclExpExtFuncData &rExtFuncData)
Definition: xeformula.cxx:2409
const sal_uInt8 EXC_TOKCLASS_ARR
40-5F: Value class tokens.
Definition: xlformula.hxx:45
ocLogNormDist
const sal_uInt8 EXC_TOK_BOOL_TRUE
sal_False value of a tBool token.
Definition: xlformula.hxx:114
XclTokenArrayRef CreateNameXFormula(sal_uInt16 nExtSheet, sal_uInt16 nExtName)
Creates a single tNameXR token for a reference to an external name.
Definition: xeformula.cxx:2691
ScAddress aEnd
Definition: address.hxx:500
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:95
XclAddress maLast
Definition: xladdress.hxx:60
void AppendDefaultParam(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1659
XclExpScToken UnaryPreTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1093
sal_uInt32 mnRow
Definition: xladdress.hxx:32
const SCROW mnMaxAbsRow
Maximum column index.
Definition: xeformula.cxx:465
void ProcessExternalCellRef(const XclExpScToken &rTokData)
Definition: xeformula.cxx:2054
XclExpScToken ConcatTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1017
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:63
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:59
XclExpRefLogEntry * GetNewRefLogEntry()
Definition: xeformula.cxx:1941
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:118
ScDocument & GetDoc() const
Returns reference to the destination document (import) or source document (export).
Definition: xlroot.cxx:276
const sal_uInt8 EXC_TOKID_AREA3D
3D cell reference.
Definition: xlformula.hxx:105
ocSpaces
Parameter supported by Calc and Excel.
Definition: xlformula.hxx:180
Shared formula.
Definition: xlformula.hxx:164
ocUnion
XclExpScToken Expression(XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep)
Definition: xeformula.cxx:939
const sal_uInt8 EXC_TOKID_NAMEX
Definition: xlformula.hxx:103
const sal_uInt8 EXC_TOKID_BOOL
Error constant.
Definition: xlformula.hxx:80
svExternalName
const size_t EXC_FUNCINFO_PARAMINFO_COUNT
Maximum parameter count.
Definition: xlformula.hxx:286
Web query source range.
Definition: xlformula.hxx:170
void RecalcTokenClass(const XclExpTokenConvInfo &rConvInfo, XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass)
Definition: xeformula.cxx:642
Try NOT to use this struct.
Definition: scmatrix.hxx:52
ocIf
XclFuncParamConv
Enumerates different types of token class conversion in function parameters.
Definition: xlformula.hxx:185
void FinishIfFunction(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1529
const sal_uInt8 EXC_TOKID_NONE
Definition: xlformula.hxx:51
ocLogInv
ocGammaDist
void ProcessFunction(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1370
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:54
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:558
ocIndex
XclFormulaType
Mask for number of appended ranges.
Definition: xlformula.hxx:159
double fVal
Definition: scmatrix.hxx:54
const sal_uInt8 EXC_TOKID_LIST
Intersection operator.
Definition: xlformula.hxx:67
XclExpCompDataRef mxData
Excel function data provider.
Definition: xeformula.cxx:460
Access to global data from other classes.
Definition: xeroot.hxx:112
void ProcessExternal(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1287
bool GetBoolean() const
Only valid if ScMatrix methods indicate that this is a boolean.
Definition: scmatrix.hxx:65
char sal_uInt16 & nParamCount
Definition: callform.cxx:53
ocNegSub
void AppendBinaryOperatorToken(sal_uInt8 nTokenId, bool bValType, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2447
XclTokenArrayRef CreateTokenArray()
Definition: xeformula.cxx:785
void AppendOperatorTokenId(sal_uInt8 nTokenId, const XclExpOperandListRef &rxOperands, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2433
MS Excel 4.0.
Definition: xlconst.hxx:34
const sal_uInt16 EXC_TOK_REF_ROWREL
True = Column is relative.
Definition: xlformula.hxx:138
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:44
void RecalcTokenClasses()
Definition: xeformula.cxx:618
void ProcessCellRef(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1951
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:537
const FormulaToken * GetNextRawToken()
Definition: xeformula.cxx:806
void AppendMissingToken(sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2370
const SCTAB SCTAB_INVALID
An invalid Excel sheet index, for common use.
Definition: xlconst.hxx:73
const sal_uInt8 EXC_TOKID_GT
Greater than or equal operator.
Definition: xlformula.hxx:64
ocRound
const sal_uInt8 EXC_TOKID_NE
Greater than operator.
Definition: xlformula.hxx:65
OpCode
int nCount
const sal_uInt8 EXC_TOKID_REF3D
External reference.
Definition: xlformula.hxx:104
void ProcessParentheses(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1238
void AppendBoolToken(bool bValue, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2358
XclTokenArrayRef CreateSpecialRefFormula(sal_uInt8 nTokenId, const XclAddress &rXclPos)
Creates a single token for a special cell reference.
Definition: xeformula.cxx:2685
ocGreater
XclExpFmlaClassType
Type of token class handling.
Definition: xeformula.cxx:224
SC_DLLPUBLIC ScExternalRefManager * GetExternalRefManager() const
Definition: documen3.cxx:623
XclExpCompConfigMap maCfgMap
Definition: xeformula.cxx:458
void FinishFunction(XclExpFuncData &rFuncData, sal_uInt8 nCloseSpaces)
Definition: xeformula.cxx:1461
ocEqual
svDouble
void AppendRange(const XclRange &rXclRange)
Definition: xeformula.cxx:2312
void SetColDeleted(bool bVal)
Definition: refdata.cxx:110
XclExpScToken Factor(XclExpScToken aTokData)
Definition: xeformula.cxx:1175
const sal_uInt16 EXC_FUNCID_SUM
Definition: xlformula.hxx:296
SCTAB Tab() const
Definition: address.hxx:270
LanguageType GetUILanguage() const
Returns the UI language.
Definition: xlroot.hxx:152
void SetRow(SCROW nRowP)
Definition: address.hxx:274
const sal_uInt8 EXC_TOKID_FUNCVAR
Function, fixed number of arguments.
Definition: xlformula.hxx:88
bool IsColRel() const
Definition: refdata.hxx:65
const sal_uInt8 EXC_TOKID_AREA
2D cell reference.
Definition: xlformula.hxx:91
XclExpFmlaCompImplRef mxImpl
Definition: xeformula.hxx:88
const sal_uInt8 EXC_TOKID_UMINUS
Unary plus.
Definition: xlformula.hxx:70
const sal_uInt8 EXC_TOKID_NAME
Function, variable number of arguments.
Definition: xlformula.hxx:89
const SCTAB SCTAB_GLOBAL
An invalid Calc sheet index, for common use.
Definition: xlconst.hxx:74
ocCot
const sal_uInt8 EXC_TOKID_NUM
Integer constant.
Definition: xlformula.hxx:82
void SetCol(SCCOL nColP)
Definition: address.hxx:278
const sal_uInt8 EXC_ERR_REF
Definition: xlconst.hxx:107
void AppendEuroToolCallToken(const XclExpExtFuncData &rExtFuncData)
Definition: xeformula.cxx:2424
const sal_uInt8 EXC_TOKID_AREAERR3D
Deleted 3D cell reference.
Definition: xlformula.hxx:107
ocSep
DocumentType eType
XclTokenArrayRef CreateErrorFormula(sal_uInt8 nErrCode)
Creates a single error token containing the passed error code.
Definition: xeformula.cxx:2680
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:2387
const sal_uInt8 EXC_TOKID_UPLUS
Range operator.
Definition: xlformula.hxx:69
Matrix (array) formula.
Definition: xlformula.hxx:163
FormulaError GetError() const
Only valid if ScMatrix methods indicate that this is no string!
Definition: scmatrix.hxx:62
void ConvertRefData(ScSingleRefData &rRefData, XclAddress &rXclPos, bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow) const
Definition: xeformula.cxx:1876
const sal_uInt8 EXC_TOKID_SUB
Addition operator.
Definition: xlformula.hxx:55
XclExpLinkManager & GetGlobalLinkManager() const
Returns the global link manager for defined names.
Definition: xeroot.cxx:131
const sal_uInt8 EXC_TOKID_ERR
End of a sheet reference (BIFF2-BIFF4).
Definition: xlformula.hxx:79
XclExpScToken GetNextToken()
Definition: xeformula.cxx:839
ocDde
ocWhitespace
MS Excel 5.0, MS Excel 7.0 (95)
Definition: xlconst.hxx:35
Represents information for a spreadsheet function for import and export.
Definition: xlformula.hxx:310
const sal_uInt8 EXC_TOKID_REFN
Deleted 2D area reference.
Definition: xlformula.hxx:98
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:167
void ProcessExternalName(const XclExpScToken &rTokData)
Definition: xeformula.cxx:2158
const size_t EXC_TOKARR_MAXLEN
Definition: xlformula.hxx:37
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:128
void PrepareParam(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1602
void AppendUnaryOperatorToken(sal_uInt8 nTokenId, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2440
const sal_uInt8 EXC_TOK_ATTR_SPACE_SP
Spaces in formula representation.
Definition: xlformula.hxx:124
const sal_uInt8 EXC_TOK_ATTR_IF
Volatile function.
Definition: xlformula.hxx:117
Manager that stores all internal defined names (NAME records) of the document.
Definition: xename.hxx:31
static sal_uInt8 GetXclErrorCode(FormulaError nScError)
Converts a Calc error code to an Excel error code.
Definition: xltools.cxx:201
void SetFlag3D(bool bVal)
Definition: refdata.hxx:89
const sal_uInt8 EXC_TOKID_ATTR
Natural language reference (NLR).
Definition: xlformula.hxx:76
void GetDimensions(SCSIZE &rC, SCSIZE &rR) const
Definition: scmatrix.cxx:2929
void ProcessMatrix(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1300
sal_uInt16 PopOperandPos()
Definition: xeformula.cxx:2230
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:21
void ProcessRangeRef(const XclExpScToken &rTokData)
Definition: xeformula.cxx:2009
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:153
ocMissing
ScSingleRefData Ref1
Definition: refdata.hxx:124
static bool IsValueType(ScMatValType nType)
Value or boolean.
Definition: scmatrix.hxx:178
sal_uInt16 GetSize() const
Definition: xeformula.cxx:321
ocSecantHyp
ocPoissonDist
const sal_uInt16 EXC_FUNCID_AND
Definition: xlformula.hxx:297
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:89
void ProcessMissing(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1228
ScSingleRefData Ref2
Definition: refdata.hxx:125
bool IsSpaceToken(sal_uInt16 nPos) const
Definition: xeformula.cxx:2547
ocExternal
const sal_uInt8 EXC_TOK_NLR_COLV
NLR: Value in row.
Definition: xlformula.hxx:144
Repeat parent conversion in VALTYPE parameters.
Definition: xlformula.hxx:191
XclExpScToken ProcessParam(XclExpScToken aTokData, XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1571
const sal_uInt8 EXC_CACHEDVAL_BOOL
Definition: xlconst.hxx:117
svExternalDoubleRef
ocBad
FormulaError GetCodeError() const
ocNone
const sal_uInt8 EXC_TOK_ATTR_SPACE
BASIC style assignment.
Definition: xlformula.hxx:122
size
const sal_uInt8 EXC_TOKID_RANGE
List operator.
Definition: xlformula.hxx:68
svExternalSingleRef
::std::vector< XclExpRefLogEntry > XclExpRefLog
Vector containing a log for all external references in a formula, used i.e.
Definition: xeformula.hxx:43
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:62
XclExpNameManager & GetNameManager() const
Returns the buffer that contains internal defined names.
Definition: xeroot.cxx:143
bool IsRowRel() const
Definition: refdata.hxx:67
static bool IsBooleanType(ScMatValType nType)
Boolean.
Definition: scmatrix.hxx:184
sal_uInt16 mnCol
Definition: xladdress.hxx:31
XclExpScToken IntersectTerm(XclExpScToken aTokData, bool &rbHasRefOp)
Definition: xeformula.cxx:1143
A 2D cell address struct with Excel column and row indexes.
Definition: xladdress.hxx:29
const ::formula::FormulaToken * Get() const
Definition: xlformula.hxx:450
void AppendExt(sal_uInt8 nData)
Definition: xeformula.cxx:2565
const sal_uInt8 EXC_TOKID_NLR
String constant.
Definition: xlformula.hxx:75
std::map< XclFormulaType, XclExpCompConfig > XclExpCompConfigMap
Definition: xeformula.cxx:455
ScMatValType nType
Definition: scmatrix.hxx:56
const sal_uInt8 EXC_CACHEDVAL_EMPTY
Definition: xlconst.hxx:114
ocLess
std::shared_ptr< XclTokenArray > XclTokenArrayRef
Definition: xlformula.hxx:416
SCTAB Tab() const
Definition: refdata.cxx:254
void Overwrite(sal_uInt16 nWriteToPos, sal_uInt16 nOffset)
Definition: xeformula.cxx:2531
Provides access to function info structs for all available functions.
Definition: xlformula.hxx:344
XclExpClassConv
Effective token class conversion types.
Definition: xeformula.cxx:70
svSingleRef
bool IsFlag3D() const
Definition: refdata.hxx:90
FormulaError
SCCOL Col() const
Definition: address.hxx:266
const XclExpRoot & GetRoot() const
Returns this root instance - for code readability in derived classes.
Definition: xeroot.hxx:118
SCTAB GetCurrScTab() const
Returns the current Calc sheet index.
Definition: xlroot.hxx:160
const sal_uInt8 EXC_TOKID_MISSARG
Parentheses.
Definition: xlformula.hxx:73
ocFalse
void AppendAddress(const XclAddress &rXclPos)
Definition: xeformula.cxx:2303
const sal_uInt16 EXC_TOK_STR_MAXLEN
Deleted 3D area reference.
Definition: xlformula.hxx:111
virtual ~XclExpFormulaCompiler() override
Definition: xeformula.cxx:2637
const sal_uInt8 EXC_TOKCLASS_VAL
20-3F: Reference class tokens.
Definition: xlformula.hxx:44
const sal_uInt8 EXC_TOK_ATTR_CHOOSE
Start of true condition in IF function.
Definition: xlformula.hxx:118
void AppendMacroCallToken(const XclExpExtFuncData &rExtFuncData)
Definition: xeformula.cxx:2403
const sal_uInt8 EXC_TOK_BOOL_FALSE
Maximum string length of a tStr token.
Definition: xlformula.hxx:113
XclExpScToken UnaryPostTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1078
const svl::SharedString & GetString() const
Only valid if ScMatrix methods indicate so!
Definition: scmatrix.hxx:59
const sal_uInt8 EXC_CACHEDVAL_DOUBLE
Definition: xlconst.hxx:115
ocOr
svDoubleRef
virtual formula::FormulaToken * AddOpCode(OpCode eCode) override
Definition: token.cxx:2197
ocCotHyp
const sal_uInt8 EXC_TOKID_PERCENT
Unary minus.
Definition: xlformula.hxx:71
void ProcessBoolean(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1245
svUnknown
ocTrue
static sal_uInt8 GetTokenClass(sal_uInt8 nTokenId)
Returns the token class of the passed token ID.
Definition: xlformula.hxx:494
sal_Int32 SCROW
Definition: types.hxx:17
const sal_uInt8 EXC_TOKID_ISECT
Not equal operator.
Definition: xlformula.hxx:66
void ProcessString(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1222
XclExpScToken PowTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1062
void PrepareFunction(const XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1438
const SCROW mnMaxScRow
Maximum column index in Calc itself.
Definition: xeformula.cxx:467
ocAdd
ocRoundUp
XclExpFormulaCompiler(const XclExpRoot &rRoot)
Definition: xeformula.cxx:2631
void ProcessDouble(const XclExpScToken &rTokData)
Definition: xeformula.cxx:1211
XclExpScToken AndTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:985
::std::vector< sal_uInt16 > ScfUInt16Vec
Definition: ftools.hxx:255
void AppendSpaceToken(sal_uInt8 nType, sal_uInt8 nCount)
Definition: xeformula.cxx:2328
Stores all data for internal/external references (the link table).
Definition: xelink.hxx:145
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:116
unsigned char sal_uInt8
const sal_uInt8 EXC_ERR_NAME
Definition: xlconst.hxx:108
Convert tokens to ARR class.
Definition: xlformula.hxx:190
ocEuroConvert
const sal_uInt8 EXC_TOKID_POWER
Division operator.
Definition: xlformula.hxx:58
ocAnd
void InsertZeros(sal_uInt16 nInsertPos, sal_uInt16 nInsertSize)
Definition: xeformula.cxx:2510
bool IsRef2D(const ScSingleRefData &rRefData, bool bCheck3DFlag) const
Definition: xeformula.cxx:1849
void AppendErrorToken(sal_uInt8 nErrCode, sal_uInt8 nSpaces=0)
Definition: xeformula.cxx:2364
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:56
void InitRange(const ScRange &rRange)
Definition: refdata.hxx:130
const sal_uInt16 EXC_FUNCID_OR
Definition: xlformula.hxx:298
svExternal
SCTAB GetScTab(const ScSingleRefData &rRefData) const
Definition: xeformula.cxx:1834
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:2641
const sal_uInt8 EXC_TOKID_INT
Boolean constant.
Definition: xlformula.hxx:81
XclFuncParamConv meConv
Parameter validity.
Definition: xlformula.hxx:278
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:400
void MoveRelWrap()
Definition: compiler.cxx:5082
ocRoundDown
Simple cell formula, also used in change tracking.
Definition: xlformula.hxx:162
void SetAddress(const ScSheetLimits &rLimits, const ScAddress &rAddr, const ScAddress &rPos)
Definition: refdata.cxx:213
FunctionParamInfo mpParamInfos[FUNCINFO_PARAMINFOCOUNT]
BIFF token class of the return value.
void FinishChooseFunction(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1543
Log entry for external references in a formula, used i.e.
Definition: xeformula.hxx:31
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:166
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:122
const XclExpCompConfig * GetConfigForType(XclFormulaType eType) const
Definition: xeformula.cxx:561
const sal_uInt8 EXC_TOK_ATTR_SUM
Jump to token.
Definition: xlformula.hxx:120
XclExpScToken RangeTerm(XclExpScToken aTokData, bool &rbHasRefOp)
Definition: xeformula.cxx:1159
void Append(sal_uInt8 nData)
Definition: xeformula.cxx:2273
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:99
ocLessEqual
XclExpScToken SkipExpression(XclExpScToken aTokData, bool bStopAtSep)
Definition: xeformula.cxx:954
std::shared_ptr< XclExpString > XclExpStringRef
Definition: xeroot.hxx:35
Repeat parent conversion in REFTYPE parameters.
Definition: xlformula.hxx:192
void AppendTrailingParam(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1706
const sal_uInt16 EXC_TOK_REF_COLREL
Mask for parameter count.
Definition: xlformula.hxx:137
A helper with Excel specific token array functions.
Definition: xlformula.hxx:485
const sal_uInt8 EXC_TOKID_FUNC
Array constant.
Definition: xlformula.hxx:87
bool IsAddInEquivalent() const
Returns true, if the function is stored as an add-in call.
Definition: xlformula.hxx:334
void AppendJumpToken(XclExpFuncData &rFuncData, sal_uInt8 nAttrType)
Definition: xeformula.cxx:2500
bool IsRowDeleted() const
Definition: refdata.hxx:84
Chart source ranges.
Definition: xlformula.hxx:168
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:438
void AppendParenToken(sal_uInt8 nOpenSpaces=0, sal_uInt8 nCloseSpaces=0)
Definition: xeformula.cxx:2493
RedlineType meType
void RemoveTrailingParen()
Definition: xeformula.cxx:2555
aStr
ocClose
Spreadsheet links in form controls.
Definition: xlformula.hxx:169
std::unique_ptr< ScTokenArray > Clone() const
Definition: token.cxx:1921
A 2D cell range address struct with Excel column and row indexes.
Definition: xladdress.hxx:57
XclExpFmlaCompImpl(const XclExpRoot &rRoot)
Definition: xeformula.cxx:472
bool IsRef2D(const ScSingleRefData &rRefData) const
Definition: xeformula.cxx:2697
Structure that contains all needed information for a parameter in a function.
Definition: xlformula.hxx:275
sal_Int16 SCTAB
Definition: types.hxx:22
bool IsColDeleted() const
Definition: refdata.hxx:82
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:1002
Use original class of current token.
Definition: xlformula.hxx:188
void FinishParam(XclExpFuncData &rFuncData)
Definition: xeformula.cxx:1639
ocGreaterEqual
XclExpScToken ListTerm(XclExpScToken aTokData, bool bInParentheses)
Definition: xeformula.cxx:1109
const sal_uInt8 EXC_TOKID_DIV
Multiplication operator.
Definition: xlformula.hxx:57
const sal_uInt8 EXC_TOKID_REFERR
Variable reference subexpression.
Definition: xlformula.hxx:96
const sal_uInt8 EXC_TOK_ATTR_VOLATILE
sal_True value of a tBool token.
Definition: xlformula.hxx:116