LibreOffice Module sc (master)  1
parclass.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 <parclass.hxx>
21 #include <global.hxx>
22 #include <callform.hxx>
23 #include <addincol.hxx>
24 #include <formula/token.hxx>
25 #include <unotools/charclass.hxx>
26 #include <osl/diagnose.h>
27 #include <sal/log.hxx>
28 #include <string.h>
29 
30 #if DEBUG_SC_PARCLASSDOC
31 // the documentation thingy
32 #include <com/sun/star/sheet/FormulaLanguage.hpp>
33 #include <rtl/strbuf.hxx>
34 #include <formula/funcvarargs.h>
35 #include "compiler.hxx"
36 #endif
37 
38 using namespace formula;
39 
40 /* Following assumptions are made:
41  * - OpCodes not specified at all will have at least one and only parameters of
42  * type Value, no check is done on the count of parameters => no Bounds type
43  * is returned.
44  * - For OpCodes with a variable number of parameters the type(s) of the last
45  * repeated parameter(s) specified determine(s) the type(s) of all following
46  * parameters.
47  */
48 
50 {
51  // { OpCode, {{ ParamClass, ... }, nRepeatLast, ReturnClass }},
52 
53  // IF() and CHOOSE() are somewhat special, since the ScJumpMatrix is
54  // created inside those functions and ConvertMatrixParameters() is not
55  // called for them.
56  { ocIf, {{ Array, Reference, Reference }, 0, Value }},
57  { ocIfError, {{ Array, Reference }, 0, Value }},
58  { ocIfNA, {{ Array, Reference }, 0, Value }},
59  { ocChoose, {{ Array, Reference }, 1, Value }},
60  // Other specials.
61  { ocArrayClose, {{ Bounds }, 0, Bounds }},
62  { ocArrayColSep, {{ Bounds }, 0, Bounds }},
63  { ocArrayOpen, {{ Bounds }, 0, Bounds }},
64  { ocArrayRowSep, {{ Bounds }, 0, Bounds }},
65  { ocBad, {{ Bounds }, 0, Bounds }},
66  { ocClose, {{ Bounds }, 0, Bounds }},
67  { ocColRowName, {{ Bounds }, 0, Value }}, // or Reference?
68  { ocColRowNameAuto, {{ Bounds }, 0, Value }}, // or Reference?
69  { ocDBArea, {{ Bounds }, 0, Value }}, // or Reference?
70  { ocMatRef, {{ Bounds }, 0, Value }},
71  { ocMissing, {{ Bounds }, 0, Value }},
72  { ocNoName, {{ Bounds }, 0, Bounds }},
73  { ocOpen, {{ Bounds }, 0, Bounds }},
74  { ocSep, {{ Bounds }, 0, Bounds }},
75  { ocSkip, {{ Bounds }, 0, Bounds }},
76  { ocSpaces, {{ Bounds }, 0, Bounds }},
77  { ocStop, {{ Bounds }, 0, Bounds }},
78  { ocStringXML, {{ Bounds }, 0, Bounds }},
79  { ocTableRef, {{ Bounds }, 0, Value }}, // or Reference?
80  { ocTableRefClose, {{ Bounds }, 0, Bounds }},
81  { ocTableRefItemAll, {{ Bounds }, 0, Bounds }},
82  { ocTableRefItemData, {{ Bounds }, 0, Bounds }},
83  { ocTableRefItemHeaders, {{ Bounds }, 0, Bounds }},
84  { ocTableRefItemThisRow, {{ Bounds }, 0, Bounds }},
85  { ocTableRefItemTotals, {{ Bounds }, 0, Bounds }},
86  { ocTableRefOpen, {{ Bounds }, 0, Bounds }},
87  // Error constants.
88  { ocErrDivZero, {{ Bounds }, 0, Bounds }},
89  { ocErrNA, {{ Bounds }, 0, Bounds }},
90  { ocErrName, {{ Bounds }, 0, Bounds }},
91  { ocErrNull, {{ Bounds }, 0, Bounds }},
92  { ocErrNum, {{ Bounds }, 0, Bounds }},
93  { ocErrRef, {{ Bounds }, 0, Bounds }},
94  { ocErrValue, {{ Bounds }, 0, Bounds }},
95  // Functions with Value parameters only but not in resource.
96  { ocBackSolver, {{ Value, Value, Value }, 0, Value }},
97  { ocTableOp, {{ Value, Value, Value, Value, Value }, 0, Value }},
98  // Operators and functions.
99  { ocAdd, {{ Array, Array }, 0, Value }},
101  { ocAmpersand, {{ Array, Array }, 0, Value }},
102  { ocAnd, {{ Reference }, 1, Value }},
103  { ocAreas, {{ Reference }, 0, Value }},
104  { ocAveDev, {{ Reference }, 1, Value }},
105  { ocAverage, {{ ReferenceOrRefArray }, 1, Value }},
106  { ocAverageA, {{ ReferenceOrRefArray }, 1, Value }},
109  { ocCell, {{ Value, Reference }, 0, Value }},
110  { ocColumn, {{ Reference }, 0, Value }},
111  { ocColumns, {{ Reference }, 1, Value }},
112  { ocConcat_MS, {{ Reference }, 1, Value }},
113  { ocCorrel, {{ ForceArray, ForceArray }, 0, Value }},
114  { ocCount, {{ ReferenceOrRefArray }, 1, Value }},
115  { ocCount2, {{ ReferenceOrRefArray }, 1, Value }},
117  { ocCountIf, {{ ReferenceOrRefArray, Value }, 0, Value }},
118  { ocCountIfs, {{ ReferenceOrRefArray, Value }, 2, Value }},
119  { ocCovar, {{ ForceArray, ForceArray }, 0, Value }},
120  { ocCovarianceP, {{ ForceArray, ForceArray }, 0, Value }},
121  { ocCovarianceS, {{ ForceArray, ForceArray }, 0, Value }},
122  { ocCurrent, {{ Bounds }, 0, Value }},
123  { ocDBAverage, {{ Reference, Reference, Reference }, 0, Value }},
124  { ocDBCount, {{ Reference, Reference, Reference }, 0, Value }},
125  { ocDBCount2, {{ Reference, Reference, Reference }, 0, Value }},
126  { ocDBGet, {{ Reference, Reference, Reference }, 0, Value }},
127  { ocDBMax, {{ Reference, Reference, Reference }, 0, Value }},
128  { ocDBMin, {{ Reference, Reference, Reference }, 0, Value }},
129  { ocDBProduct, {{ Reference, Reference, Reference }, 0, Value }},
130  { ocDBStdDev, {{ Reference, Reference, Reference }, 0, Value }},
131  { ocDBStdDevP, {{ Reference, Reference, Reference }, 0, Value }},
132  { ocDBSum, {{ Reference, Reference, Reference }, 0, Value }},
133  { ocDBVar, {{ Reference, Reference, Reference }, 0, Value }},
134  { ocDBVarP, {{ Reference, Reference, Reference }, 0, Value }},
135  { ocDevSq, {{ Reference }, 1, Value }},
136  { ocDiv, {{ Array, Array }, 0, Value }},
137  { ocEqual, {{ Array, Array }, 0, Value }},
138  { ocFTest, {{ ForceArray, ForceArray }, 0, Value }},
139  { ocFalse, {{ Bounds }, 0, Value }},
140  { ocForecast, {{ Value, ForceArray, ForceArray }, 0, Value }},
145  { ocForecast_ETS_SEA, {{ ForceArray, ForceArray, Value, Value }, 0, Value }},
148  { ocFormula, {{ Reference }, 0, Value }},
149  { ocFourier, {{ ForceArray, Value, Value, Value, Value }, 0, Value }},
151  { ocGCD, {{ Reference }, 1, Value }},
152  { ocGeoMean, {{ Reference }, 1, Value }},
153  { ocGetActDate, {{ Bounds }, 0, Value }},
154  { ocGetActTime, {{ Bounds }, 0, Value }},
155  { ocGreater, {{ Array, Array }, 0, Value }},
156  { ocGreaterEqual, {{ Array, Array }, 0, Value }},
157  { ocGrowth, {{ Reference, Reference, Reference, Value }, 0, Value }},
158  { ocHLookup, {{ Value, ReferenceOrForceArray, Value, Value }, 0, Value }},
159  { ocHarMean, {{ Reference }, 1, Value }},
160  { ocIRR, {{ Reference, Value }, 0, Value }},
161  { ocIndex, {{ Reference, Value, Value, Value }, 0, Value }},
162  { ocIndirect, {{ Value, Value }, 0, Reference }},
163  { ocIntercept, {{ ForceArray, ForceArray }, 0, Value }},
164  { ocIntersect, {{ Reference, Reference }, 0, Reference }},
165  { ocIsFormula, {{ Reference }, 0, Value }},
166  { ocIsRef, {{ Reference }, 0, Value }},
167  { ocKurt, {{ Reference }, 1, Value }},
168  { ocLCM, {{ Reference }, 1, Value }},
169  { ocLarge, {{ Reference, Value }, 0, Value }},
170  { ocLess, {{ Array, Array }, 0, Value }},
171  { ocLessEqual, {{ Array, Array }, 0, Value }},
172  { ocLinest, {{ ForceArray, ForceArray, Value, Value }, 0, Value }},
173  { ocLogest, {{ ForceArray, ForceArray, Value, Value }, 0, Value }},
174  { ocLookup, {{ Value, ReferenceOrForceArray, ReferenceOrForceArray }, 0, Value }},
175  { ocMIRR, {{ Reference, Value, Value }, 0, Value }},
176  { ocMatDet, {{ ForceArray }, 0, Value }},
177  { ocMatInv, {{ ForceArray }, 0, Value }},
178  { ocMatMult, {{ ForceArray, ForceArray }, 0, Value }},
179  { ocMatTrans, {{ ForceArray }, 0, ForceArrayReturn }},
180  { ocMatValue, {{ Reference, Value, Value }, 0, Value }},
181  { ocMatch, {{ Value, ReferenceOrForceArray, Value }, 0, Value }},
182  { ocMax, {{ ReferenceOrRefArray }, 1, Value }},
183  { ocMaxA, {{ ReferenceOrRefArray }, 1, Value }},
185  { ocMedian, {{ Reference }, 1, Value }},
186  { ocMin, {{ ReferenceOrRefArray }, 1, Value }},
187  { ocMinA, {{ ReferenceOrRefArray }, 1, Value }},
189  { ocModalValue, {{ ForceArray }, 1, Value }},
190  { ocModalValue_MS, {{ ForceArray }, 1, Value }},
191  { ocModalValue_Multi,{{ ForceArray }, 1, Value }},
192  { ocMul, {{ Array, Array }, 0, Value }},
193  { ocMultiArea, {{ Reference }, 1, Reference }},
194  { ocNPV, {{ Value, Reference }, 1, Value }},
195  { ocNeg, {{ Array }, 0, Value }},
196  { ocNegSub, {{ Array }, 0, Value }},
197  { ocNetWorkdays, {{ Value, Value, Reference, Reference }, 0, Value }},
198  { ocNetWorkdays_MS, {{ Value, Value, Value, Reference }, 0, Value }},
199  { ocNot, {{ Array }, 0, Value }},
200  { ocNotAvail, {{ Bounds }, 0, Value }},
201  { ocNotEqual, {{ Array, Array }, 0, Value }},
202  { ocOffset, {{ Reference, Value, Value, Value, Value }, 0, Reference }},
203  { ocOr, {{ Reference }, 1, Value }},
204  { ocPearson, {{ ForceArray, ForceArray }, 0, Value }},
205  { ocPercentSign, {{ Array }, 0, Value }},
206  { ocPercentile, {{ Reference, Value }, 0, Value }},
207  { ocPercentile_Exc, {{ Reference, Value }, 0, Value }},
208  { ocPercentile_Inc, {{ Reference, Value }, 0, Value }},
209  { ocPercentrank, {{ Reference, Value, Value }, 0, Value }},
210  { ocPercentrank_Exc, {{ Reference, Value, Value }, 0, Value }},
211  { ocPercentrank_Inc, {{ Reference, Value, Value }, 0, Value }},
212  { ocPi, {{ Bounds }, 0, Value }},
213  { ocPow, {{ Array, Array }, 0, Value }},
214  { ocPower, {{ Array, Array }, 0, Value }},
215  { ocProb, {{ ForceArray, ForceArray, Value, Value }, 0, Value }},
216  { ocProduct, {{ ReferenceOrRefArray }, 1, Value }},
217  { ocQuartile, {{ Reference, Value }, 0, Value }},
218  { ocQuartile_Exc, {{ Reference, Value }, 0, Value }},
219  { ocQuartile_Inc, {{ Reference, Value }, 0, Value }},
220  { ocRSQ, {{ ForceArray, ForceArray }, 0, Value }},
221  { ocRandom, {{ Bounds }, 0, Value }},
222  { ocRandomNV, {{ Bounds }, 0, Value }},
223  { ocRange, {{ Reference, Reference }, 0, Reference }},
224  { ocRank, {{ Value, Reference, Value }, 0, Value }},
225  { ocRank_Avg, {{ Value, Reference, Value }, 0, Value }},
226  { ocRank_Eq, {{ Value, Reference, Value }, 0, Value }},
227  { ocRow, {{ Reference }, 0, Value }},
228  { ocRows, {{ Reference }, 1, Value }},
229  { ocSTEYX, {{ ForceArray, ForceArray }, 0, Value }},
230  { ocSheet, {{ Reference }, 0, Value }},
231  { ocSheets, {{ Reference }, 1, Value }},
232  { ocSkew, {{ Reference }, 1, Value }},
233  { ocSkewp, {{ Reference }, 1, Value }},
234  { ocSlope, {{ ForceArray, ForceArray }, 0, Value }},
235  { ocSmall, {{ Reference, Value }, 0, Value }},
236  { ocStDev, {{ Reference }, 1, Value }},
237  { ocStDevA, {{ Reference }, 1, Value }},
238  { ocStDevP, {{ Reference }, 1, Value }},
239  { ocStDevPA, {{ Reference }, 1, Value }},
240  { ocStDevP_MS, {{ Reference }, 1, Value }},
241  { ocStDevS, {{ Reference }, 1, Value }},
242  { ocSub, {{ Array, Array }, 0, Value }},
243  { ocSubTotal, {{ Value, ReferenceOrRefArray }, 1, Value }},
244  { ocSum, {{ ReferenceOrRefArray }, 1, Value }},
247  { ocSumProduct, {{ ForceArray }, 1, Value }},
248  { ocSumSQ, {{ ReferenceOrRefArray }, 1, Value }},
249  { ocSumX2DY2, {{ ForceArray, ForceArray }, 0, Value }},
250  { ocSumX2MY2, {{ ForceArray, ForceArray }, 0, Value }},
251  { ocSumXMY2, {{ ForceArray, ForceArray }, 0, Value }},
252  { ocTTest, {{ ForceArray, ForceArray, Value, Value }, 0, Value }},
253  { ocTextJoin_MS, {{ Reference, Value, Reference }, 1, Value }},
254  { ocTrend, {{ Reference, Reference, Reference, Value }, 0, Value }},
255  { ocTrimMean, {{ Reference, Value }, 0, Value }},
256  { ocTrue, {{ Bounds }, 0, Value }},
257  { ocUnion, {{ Reference, Reference }, 0, Reference }},
258  { ocVLookup, {{ Value, ReferenceOrForceArray, Value, Value }, 0, Value }},
259  { ocVar, {{ ReferenceOrRefArray }, 1, Value }},
260  { ocVarA, {{ ReferenceOrRefArray }, 1, Value }},
261  { ocVarP, {{ ReferenceOrRefArray }, 1, Value }},
262  { ocVarPA, {{ ReferenceOrRefArray }, 1, Value }},
263  { ocVarP_MS, {{ Reference }, 1, Value }},
264  { ocVarS, {{ Reference }, 1, Value }},
265  { ocWorkday_MS, {{ Value, Value, Value, Reference }, 0, Value }},
266  { ocXor, {{ Reference }, 1, Value }},
267  { ocZTest, {{ Reference, Value, Value }, 0, Value }},
268  { ocZTest_MS, {{ Reference, Value, Value }, 0, Value }},
269  // Excel doubts:
270  // ocN, ocT: Excel says (and handles) Reference, error? This means no
271  // position dependent SingleRef if DoubleRef, and no array calculation,
272  // just the upper left corner. We never did that for ocT and now also not
273  // for ocN (position dependent intersection worked before but array
274  // didn't). No specifics in ODFF, so the general rule applies. Gnumeric
275  // does the same.
276  { ocN, {{ Value }, 0, Value }},
277  { ocT, {{ Value }, 0, Value }},
278  // The stopper.
279  { ocNone, {{ Bounds }, 0, Value }}
280 };
281 
283 
285 {
286  if ( pData )
287  return;
289  memset( pData, 0, sizeof(RunData) * (SC_OPCODE_LAST_OPCODE_ID + 1));
290 
291  // init from specified static data above
292  for (const auto & i : pRawData)
293  {
294  const RawData* pRaw = &i;
295  if ( pRaw->eOp > SC_OPCODE_LAST_OPCODE_ID )
296  {
297  OSL_ENSURE( pRaw->eOp == ocNone, "RawData OpCode error");
298  }
299  else
300  {
301  RunData* pRun = &pData[ pRaw->eOp ];
302  SAL_WARN_IF(pRun->aData.nParam[0] != Unknown, "sc.core", "already assigned: " << static_cast<int>(pRaw->eOp));
303  memcpy( &(pRun->aData), &(pRaw->aData), sizeof(CommonData));
304  // fill 0-initialized fields with real values
305  if ( pRun->aData.nRepeatLast )
306  {
307  for ( sal_Int32 j=0; j < CommonData::nMaxParams; ++j )
308  {
309  if ( pRun->aData.nParam[j] )
310  pRun->nMinParams = sal::static_int_cast<sal_uInt8>( j+1 );
311  else if (j >= pRun->aData.nRepeatLast)
312  pRun->aData.nParam[j] = pRun->aData.nParam[j - pRun->aData.nRepeatLast];
313  else
314  {
315  SAL_INFO(
316  "sc.core",
317  "bad classification: eOp " << +pRaw->eOp
318  << ", repeated param " << j
319  << " negative offset");
320  pRun->aData.nParam[j] = Unknown;
321  }
322  }
323  }
324  else
325  {
326  for ( sal_Int32 j=0; j < CommonData::nMaxParams; ++j )
327  {
328  if ( !pRun->aData.nParam[j] )
329  {
330  if ( j == 0 || pRun->aData.nParam[j-1] != Bounds )
331  pRun->nMinParams = sal::static_int_cast<sal_uInt8>( j );
332  pRun->aData.nParam[j] = Bounds;
333  }
334  }
335  if ( !pRun->nMinParams &&
336  pRun->aData.nParam[CommonData::nMaxParams-1] != Bounds)
337  pRun->nMinParams = CommonData::nMaxParams;
338  }
339  for (const formula::ParamClass & j : pRun->aData.nParam)
340  {
341  if ( j == ForceArray || j == ReferenceOrForceArray )
342  {
343  pRun->bHasForceArray = true;
344  break; // for
345  }
346  }
347  }
348  }
349 
350 #if DEBUG_SC_PARCLASSDOC
351  GenerateDocumentation();
352 #endif
353 }
354 
356 {
357  delete [] pData;
358  pData = nullptr;
359 }
360 
362  const formula::FormulaToken* pToken, sal_uInt16 nParameter)
363 {
364  OpCode eOp = pToken->GetOpCode();
365  switch ( eOp )
366  {
367  case ocExternal:
368  return GetExternalParameterType( pToken, nParameter);
369  case ocMacro:
370  return (nParameter == SAL_MAX_UINT16 ? Value : Reference);
371  default:
372  {
373  // added to avoid warnings
374  }
375  }
376  if ( 0 <= static_cast<short>(eOp) && eOp <= SC_OPCODE_LAST_OPCODE_ID )
377  {
378  sal_uInt8 nRepeat;
380  if (nParameter == SAL_MAX_UINT16)
381  eType = pData[eOp].aData.eReturn;
382  else if ( nParameter < CommonData::nMaxParams )
383  eType = pData[eOp].aData.nParam[nParameter];
384  else if ( (nRepeat = pData[eOp].aData.nRepeatLast) > 0 )
385  {
386  // The usual case is 1 repeated parameter, we don't need to
387  // calculate that on each call.
388  sal_uInt16 nParam = (nRepeat > 1 ?
389  (pData[eOp].nMinParams -
390  ((nParameter - pData[eOp].nMinParams) % nRepeat)) :
391  pData[eOp].nMinParams);
392  return pData[eOp].aData.nParam[nParam];
393  }
394  else
395  eType = Bounds;
396  return eType == Unknown ? Value : eType;
397  }
398  return Unknown;
399 }
400 
402  sal_uInt16 nParameter)
403 {
405  if (nParameter == SAL_MAX_UINT16)
406  return eRet;
407 
408  // similar to ScInterpreter::ScExternal()
409  OUString aFuncName = ScGlobal::getCharClassPtr()->uppercase( pToken->GetExternal());
410  {
411  const LegacyFuncData* pLegacyFuncData = ScGlobal::GetLegacyFuncCollection()->findByName(aFuncName);
412  if (pLegacyFuncData)
413  {
414  if ( nParameter >= pLegacyFuncData->GetParamCount() )
415  eRet = Bounds;
416  else
417  {
418  switch ( pLegacyFuncData->GetParamType( nParameter) )
419  {
422  eRet = Value;
423  break;
424  default:
425  eRet = Reference;
426  // also array types are created using an area reference
427  }
428  }
429  return eRet;
430  }
431  }
432 
433  OUString aUnoName =
434  ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false);
435 
436  if (!aUnoName.isEmpty())
437  {
438  // the relevant parts of ScUnoAddInCall without having to create one
439  const ScUnoAddInFuncData* pFuncData =
440  ScGlobal::GetAddInCollection()->GetFuncData( aUnoName, true ); // need fully initialized data
441  if ( pFuncData )
442  {
443  tools::Long nCount = pFuncData->GetArgumentCount();
444  if ( nCount <= 0 )
445  eRet = Bounds;
446  else
447  {
448  const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
449  if ( nParameter >= nCount &&
450  pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
451  eRet = Value;
452  // last arg is sequence, optional "any"s, we simply can't
453  // determine the type
454  if ( eRet == Unknown )
455  {
456  if ( nParameter >= nCount )
457  eRet = Bounds;
458  else
459  {
460  switch ( pArgs[nParameter].eType )
461  {
462  case SC_ADDINARG_INTEGER:
463  case SC_ADDINARG_DOUBLE:
464  case SC_ADDINARG_STRING:
465  eRet = Value;
466  break;
467  default:
468  eRet = Reference;
469  }
470  }
471  }
472  }
473  }
474  }
475  return eRet;
476 }
477 
478 #if DEBUG_SC_PARCLASSDOC
479 
480 // add remaining functions, all Value parameters
481 void ScParameterClassification::MergeArgumentsFromFunctionResource()
482 {
484  for ( const ScFuncDesc* pDesc = pFuncList->First(); pDesc;
485  pDesc = pFuncList->Next() )
486  {
487  if ( pDesc->nFIndex > SC_OPCODE_LAST_OPCODE_ID ||
488  pData[pDesc->nFIndex].aData.nParam[0] != Unknown )
489  continue; // not an internal opcode or already done
490 
491  RunData* pRun = &pData[ pDesc->nFIndex ];
492  sal_uInt16 nArgs = pDesc->GetSuppressedArgCount();
493  if ( nArgs >= PAIRED_VAR_ARGS )
494  {
495  nArgs -= PAIRED_VAR_ARGS - 2;
496  pRun->aData.nRepeatLast = 2;
497  }
498  else if ( nArgs >= VAR_ARGS )
499  {
500  nArgs -= VAR_ARGS - 1;
501  pRun->aData.nRepeatLast = 1;
502  }
503  if ( nArgs > CommonData::nMaxParams )
504  {
505  SAL_WARN( "sc", "ScParameterClassification::Init: too many arguments in listed function: "
506  << *(pDesc->pFuncName)
507  << ": " << nArgs );
508  nArgs = CommonData::nMaxParams - 1;
509  pRun->aData.nRepeatLast = 1;
510  }
511  pRun->nMinParams = static_cast< sal_uInt8 >( nArgs );
512  for ( sal_Int32 j=0; j < nArgs; ++j )
513  {
514  pRun->aData.nParam[j] = Value;
515  }
516  if ( pRun->aData.nRepeatLast )
517  {
518  for ( sal_Int32 j = nArgs; j < CommonData::nMaxParams; ++j )
519  {
520  pRun->aData.nParam[j] = Value;
521  }
522  }
523  else
524  {
525  for ( sal_Int32 j = nArgs; j < CommonData::nMaxParams; ++j )
526  {
527  pRun->aData.nParam[j] = Bounds;
528  }
529  }
530  }
531 }
532 
533 void ScParameterClassification::GenerateDocumentation()
534 {
535  static const char aEnvVarName[] = "OOO_CALC_GENPARCLASSDOC";
536  if ( !getenv( aEnvVarName) )
537  return;
538  MergeArgumentsFromFunctionResource();
539  ScAddress aAddress;
540  ScCompiler aComp(NULL,aAddress);
541  ScCompiler::OpCodeMapPtr xMap( aComp.GetOpCodeMap(css::sheet::FormulaLanguage::ENGLISH));
542  if (!xMap)
543  return;
544  fflush( stderr);
545  size_t nCount = xMap->getSymbolCount();
546  for ( size_t i=0; i<nCount; ++i )
547  {
548  OpCode eOp = OpCode(i);
549  if ( !xMap->getSymbol(eOp).isEmpty() )
550  {
551  OUStringBuffer aStr(xMap->getSymbol(eOp));
552  formula::FormulaByteToken aToken( eOp);
553  sal_uInt8 nParams = GetMinimumParameters( eOp);
554  // preset parameter count according to opcode value, with some
555  // special handling
556  bool bAddParentheses = true;
557  if ( eOp < SC_OPCODE_STOP_DIV )
558  {
559  bAddParentheses = false; // will be overridden below if parameters
560  switch ( eOp )
561  {
562  case ocIf:
563  aToken.SetByte(3);
564  break;
565  case ocIfError:
566  case ocIfNA:
567  case ocChoose:
568  aToken.SetByte(2);
569  break;
570  case ocPercentSign:
571  aToken.SetByte(1);
572  break;
573  default:;
574  }
575  }
576  else if ( eOp < SC_OPCODE_STOP_ERRORS )
577  {
578  bAddParentheses = false;
579  aToken.SetByte(0);
580  }
581  else if ( eOp < SC_OPCODE_STOP_BIN_OP )
582  {
583  switch ( eOp )
584  {
585  case ocAnd:
586  case ocOr:
587  aToken.SetByte(1); // (r1)AND(r2) --> AND( r1, ...)
588  break;
589  default:
590  aToken.SetByte(2);
591  }
592  }
593  else if ( eOp < SC_OPCODE_STOP_UN_OP )
594  aToken.SetByte(1);
595  else if ( eOp < SC_OPCODE_STOP_NO_PAR )
596  aToken.SetByte(0);
597  else if ( eOp < SC_OPCODE_STOP_1_PAR )
598  aToken.SetByte(1);
599  else
600  aToken.SetByte( nParams);
601  // compare (this is a mere test for opcode order Div, BinOp, UnOp,
602  // NoPar, 1Par, ...) and override parameter count with
603  // classification
604  if ( nParams != aToken.GetByte() )
605  SAL_WARN("sc.core", "(parameter count differs, token Byte: " << (int)aToken.GetByte() << " classification: " << (int)nParams << ") ");
606  aToken.SetByte( nParams);
607  if ( nParams != aToken.GetParamCount() )
608  SAL_WARN("sc.core", "(parameter count differs, token ParamCount: " << (int)aToken.GetParamCount() << " classification: " << (int)nParams << ") ");
609  if (aToken.GetByte())
610  bAddParentheses = true;
611  if (bAddParentheses)
612  aStr.append('(');
613  for ( sal_uInt16 j=0; j < nParams; ++j )
614  {
615  if ( j > 0 )
616  aStr.append(',');
617  formula::ParamClass eType = GetParameterType( &aToken, j);
618  switch ( eType )
619  {
620  case Value :
621  aStr.append(" Value");
622  break;
623  case Reference :
624  aStr.append(" Reference");
625  break;
626  case ReferenceOrRefArray :
627  aStr.append(" ReferenceOrRefArray");
628  break;
629  case Array :
630  aStr.append(" Array");
631  break;
632  case ForceArray :
633  aStr.append(" ForceArray");
634  break;
635  case ReferenceOrForceArray :
636  aStr.append(" ReferenceOrForceArray");
637  break;
638  case Bounds :
639  aStr.append(" (Bounds, classification error?)");
640  break;
641  default:
642  aStr.append(" (???, classification error?)");
643  }
644  }
645  if ( HasRepeatParameters( eOp) )
646  aStr.append(", ...");
647  if ( nParams )
648  aStr.append(' ');
649  if (bAddParentheses)
650  aStr.append(')');
651  switch ( eOp )
652  {
653  case ocRRI:
654  aStr.append(" // RRI in English resource, but ZGZ in English-only section");
655  break;
656  case ocMultiArea:
657  aStr.append(" // e.g. combined first parameter of INDEX() function, not a real function");
658  break;
659  case ocBackSolver:
660  aStr.append(" // goal seek via menu, not a real function");
661  break;
662  case ocTableOp:
663  aStr.append(" // MULTIPLE.OPERATIONS in English resource, but TABLE in English-only section");
664  break;
665  case ocNoName:
666  aStr.append(" // error function, not a real function");
667  break;
668  default:;
669  }
670  // Return type.
671  formula::ParamClass eType = GetParameterType( &aToken, SAL_MAX_UINT16);
672  switch ( eType )
673  {
674  case Value :
675  aStr.append(" -> Value");
676  break;
677  case Reference :
678  aStr.append(" -> Reference");
679  break;
680  case ReferenceOrRefArray :
681  aStr.append(" -> ReferenceOrRefArray");
682  break;
683  case Array :
684  aStr.append(" -> Array");
685  break;
686  case ForceArray :
687  aStr.append(" -> ForceArray");
688  break;
689  case ReferenceOrForceArray :
690  aStr.append(" -> ReferenceOrForceArray");
691  break;
692  case Bounds :
693  ; // nothing
694  break;
695  default:
696  aStr.append(" (-> ???, classification error?)");
697  }
698  /* We could add yet another log domain for this, if we wanted... but
699  * as it more seldom than rarely used it's not actually necessary,
700  * just grep output. */
701  SAL_INFO( "sc.core", "CALC_GENPARCLASSDOC: " << aStr.makeStringAndClear());
702  }
703  }
704  fflush( stdout);
705 }
706 
707 #endif // OSL_DEBUG_LEVEL
708 
709 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ocChoose
ocDBCount
ocStop
ocProb
ocStDevP
ocN
List of spreadsheet functions.
Definition: funcdesc.hxx:241
ocVarPA
static const RawData pRawData[]
Definition: parclass.hxx:96
static SC_DLLPUBLIC ScUnoAddInCollection * GetAddInCollection()
Definition: global.cxx:269
static RunData * pData
Definition: parclass.hxx:97
ocTableRefOpen
ocCell
sal_uInt16 GetParamCount() const
Definition: callform.hxx:75
ocSumSQ
#define PAIRED_VAR_ARGS
ocVar
ocNetWorkdays
ocPi
ocForecast_ETS_ADD
ocDevSq
ocRank
std::unique_ptr< ContentProperties > pData
const ScUnoAddInFuncData * GetFuncData(const OUString &rName, bool bComplete=false)
Only if bComplete is set, the function reference and argument types are initialized (component may ha...
Definition: addincol.cxx:1103
ocGrowth
ocCovarianceP
ocSkip
sal_uInt16 char char * pDesc
Definition: callform.cxx:57
ocDBMin
ocWorkday_MS
ocIntercept
ocAmpersand
ocGeoMean
long Long
ocDBAverage
ocCurrent
ocOffset
ocMatch
ocSubTotal
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
ocForecast_ETS_STM
ocOpen
ocGetActTime
ocDBSum
ocIfNA
ocBackSolver
ocPercentSign
ocIntersect
ocTrend
ocArrayColSep
ocProduct
OpCode GetOpCode() const
ocPearson
ocQuartile
ocTableRefItemTotals
ocDBGet
ocSpaces
ocCount
ocMin
ocModalValue_MS
ocUnion
ocLookup
ocTableRefItemThisRow
ocCount2
ocRow
ocSTEYX
ocIf
ocLogest
ocQuartile_Exc
const LegacyFuncData * findByName(const OUString &rName) const
Definition: callform.cxx:383
ocHLookup
ocStDevS
ocIndex
ocForecast_ETS_STA
ocDBProduct
ocNegSub
ocMaxIfs_MS
ocMinIfs_MS
ocRSQ
ocArrayClose
virtual const OUString & GetExternal() const
#define SAL_MAX_UINT16
OpCode
ocSumProduct
ocStDevA
int nCount
ocForecast
const ScFuncDesc * First()
Definition: funcdesc.cxx:994
formula::ParamClass nParam[nMaxParams]
Definition: parclass.hxx:76
ocVarP_MS
ocGreater
ocEqual
ocNot
ocFrequency
ocMedian
ocCorrel
ocMatValue
ocT
ocIfError
ocCovarianceS
ocColumns
ocLinest
ocFourier
ocSep
constexpr OUStringLiteral aData
ocMatRef
DocumentType eType
ocVarP
ocRank_Avg
ocPercentrank_Exc
ocSumIfs
ocPercentile_Inc
ocSumX2MY2
ocDBMax
ocPower
ocAverageA
ocArrayOpen
ocFTest
ocColRowNameAuto
static formula::ParamClass GetParameterType(const formula::FormulaToken *pToken, sal_uInt16 nParameter)
Get one parameter type for function eOp.
Definition: parclass.cxx:361
int i
ocTableRefItemData
ocSkew
ocNPV
ocTableOp
ocMatDet
ocMul
#define VAR_ARGS
ocPercentile
ocQuartile_Inc
ocPercentrank
ocMatInv
ocSheet
ocDBVar
const OUString & FindFunction(const OUString &rUpperName, bool bLocalFirst)
User entered name. rUpperName MUST already be upper case!
Definition: addincol.cxx:1068
ocSub
sal_uInt16 & nParam
Definition: callform.cxx:57
ocMissing
ocTableRefItemHeaders
ocRank_Eq
ocForecast_ETS_PIM
ocMIRR
ocSlope
ocNotAvail
ParamType GetParamType(sal_uInt16 nIndex) const
Definition: callform.hxx:76
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
ocErrName
static void Init()
MUST be called once before any other method.
Definition: parclass.cxx:284
ocExternal
ocAverageIfs
ocMaxA
ocIsFormula
ocBad
ocAreas
ocNone
ocLCM
ocMax
ocForecast_ETS_PIA
ocForecast_ETS_MUL
ocDBStdDevP
ocSkewp
ocRows
ocErrNull
ocVarS
ocVLookup
ocErrNum
ocLess
ocTableRefItemAll
ReferenceOrRefArray
const ScAddInArgDesc * GetArguments() const
Definition: addincol.hxx:119
static ScFunctionList * GetStarCalcFunctionList()
Definition: global.cxx:609
ocCountEmptyCells
ocFalse
ocSumIf
#define SC_OPCODE_LAST_OPCODE_ID
ocErrValue
ocMatMult
ocLarge
ocVarA
ocDBCount2
ocIndirect
ocOr
ocIsRef
ocTrue
ocNetWorkdays_MS
ocRandomNV
ocErrDivZero
ocMultiArea
ocArrayRowSep
ocSheets
ocAdd
static LegacyFuncCollection * GetLegacyFuncCollection()
Definition: global.cxx:264
ocStDevPA
ocPercentrank_Inc
ocNoName
ocSumX2DY2
ocForecast_ETS_SEA
ocAverage
ocHarMean
ocStDevP_MS
#define SAL_WARN_IF(condition, area, stream)
ocAggregate
unsigned char sal_uInt8
ocRandom
ocDBVarP
ocTrimMean
ocAnd
ocConcat_MS
#define SAL_INFO(area, stream)
tools::Long GetArgumentCount() const
Definition: addincol.hxx:118
ocMatTrans
ocPercentile_Exc
ocCountIfs
const ScFuncDesc * Next()
Definition: funcdesc.cxx:1004
ReferenceOrForceArray
ocTableRef
ocColRowName
ocZTest_MS
static SC_DLLPUBLIC const CharClass * getCharClassPtr()
Definition: global.cxx:1009
ocGetActDate
ocSmall
ocModalValue_Multi
ocTableRefClose
ocRRI
ocNeg
static formula::ParamClass GetExternalParameterType(const formula::FormulaToken *pToken, sal_uInt16 nParameter)
Definition: parclass.cxx:401
ocSumXMY2
ocDiv
ocAveDev
ocTextJoin_MS
ocErrNA
ocFormula
ocPow
ocMacro
ocStringXML
ocIRR
#define SAL_WARN(area, stream)
ocNotEqual
ocErrRef
ocLessEqual
std::shared_ptr< const OpCodeMap > OpCodeMapPtr
ocCovar
ocTTest
ocAverageIf
ocCountIf
ocRange
ocGCD
ocKurt
ocXor
Stores and generates human readable descriptions for spreadsheet-functions, e.g. functions used in fo...
Definition: funcdesc.hxx:40
ocZTest
ocModalValue
ocDBStdDev
aStr
ocClose
ocMinA
ocDBArea
ocColumn
ocStDev
ocGreaterEqual
ocSum