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