1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3b3f79822SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist * or more contributor license agreements. See the NOTICE file
5b3f79822SAndrew Rist * distributed with this work for additional information
6b3f79822SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7b3f79822SAndrew Rist * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11b3f79822SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13b3f79822SAndrew Rist * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist * software distributed under the License is distributed on an
15b3f79822SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist * KIND, either express or implied. See the License for the
17b3f79822SAndrew Rist * specific language governing permissions and limitations
18b3f79822SAndrew Rist * under the License.
19cdf0e10cSrcweir *
20b3f79822SAndrew Rist *************************************************************/
21b3f79822SAndrew Rist
22b3f79822SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir
28cdf0e10cSrcweir #include "parclass.hxx"
29cdf0e10cSrcweir #include "token.hxx"
30cdf0e10cSrcweir #include "global.hxx"
31cdf0e10cSrcweir #include "callform.hxx"
32cdf0e10cSrcweir #include "addincol.hxx"
33cdf0e10cSrcweir #include "funcdesc.hxx"
34cdf0e10cSrcweir #include <unotools/charclass.hxx>
35cdf0e10cSrcweir #include <tools/debug.hxx>
36cdf0e10cSrcweir #include <string.h>
37cdf0e10cSrcweir
38cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
39cdf0e10cSrcweir // the documentation thingy
40cdf0e10cSrcweir #include <stdio.h>
41cdf0e10cSrcweir #include <com/sun/star/sheet/FormulaLanguage.hpp>
42cdf0e10cSrcweir #include "compiler.hxx"
43cdf0e10cSrcweir #include "sc.hrc" // VAR_ARGS
44cdf0e10cSrcweir #endif
45cdf0e10cSrcweir
46cdf0e10cSrcweir
47cdf0e10cSrcweir /* Following assumptions are made:
48cdf0e10cSrcweir * - OpCodes not specified at all will have at least one and only parameters of
49cdf0e10cSrcweir * type Value, no check is done on the count of parameters => no Bounds type
50cdf0e10cSrcweir * is returned.
51*6e86bbc1SAndrew Rist * - For OpCodes with a variable number of parameters the type(s) of the last
52*6e86bbc1SAndrew Rist * repeated parameter(s) specified determine(s) the type(s) of all following
53*6e86bbc1SAndrew Rist * parameters.
54cdf0e10cSrcweir */
55cdf0e10cSrcweir
56cdf0e10cSrcweir const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
57cdf0e10cSrcweir {
58*6e86bbc1SAndrew Rist // { OpCode, {{ Type, ... }, nRepeatLast }},
59*6e86bbc1SAndrew Rist
60cdf0e10cSrcweir // IF() and CHOOSE() are somewhat special, since the ScJumpMatrix is
61cdf0e10cSrcweir // created inside those functions and ConvertMatrixParameters() is not
62cdf0e10cSrcweir // called for them.
63*6e86bbc1SAndrew Rist { ocIf, {{ Array, Reference, Reference }, 0 }},
64*6e86bbc1SAndrew Rist { ocChose, {{ Array, Reference }, 1 }},
65cdf0e10cSrcweir // Other specials.
66*6e86bbc1SAndrew Rist { ocOpen, {{ Bounds }, 0 }},
67*6e86bbc1SAndrew Rist { ocClose, {{ Bounds }, 0 }},
68*6e86bbc1SAndrew Rist { ocSep, {{ Bounds }, 0 }},
69*6e86bbc1SAndrew Rist { ocNoName, {{ Bounds }, 0 }},
70*6e86bbc1SAndrew Rist { ocErrCell, {{ Bounds }, 0 }},
71*6e86bbc1SAndrew Rist { ocStop, {{ Bounds }, 0 }},
72*6e86bbc1SAndrew Rist { ocUnion, {{ Reference, Reference }, 0 }},
73*6e86bbc1SAndrew Rist { ocRange, {{ Reference, Reference }, 0 }},
74cdf0e10cSrcweir // Functions with Value parameters only but not in resource.
75*6e86bbc1SAndrew Rist { ocBackSolver, {{ Value, Value, Value }, 0 }},
76*6e86bbc1SAndrew Rist { ocTableOp, {{ Value, Value, Value, Value, Value }, 0 }},
77cdf0e10cSrcweir // Operators and functions.
78*6e86bbc1SAndrew Rist { ocAdd, {{ Array, Array }, 0 }},
79*6e86bbc1SAndrew Rist { ocAmpersand, {{ Array, Array }, 0 }},
80*6e86bbc1SAndrew Rist { ocAnd, {{ Reference }, 1 }},
81*6e86bbc1SAndrew Rist { ocAreas, {{ Reference }, 0 }},
82*6e86bbc1SAndrew Rist { ocAveDev, {{ Reference }, 1 }},
83*6e86bbc1SAndrew Rist { ocAverage, {{ Reference }, 1 }},
84*6e86bbc1SAndrew Rist { ocAverageA, {{ Reference }, 1 }},
85*6e86bbc1SAndrew Rist { ocAverageIf, {{ Reference, Value, Reference }, 0 }},
86*6e86bbc1SAndrew Rist { ocAverageIfs, {{ Reference, Reference, Value }, 2 }},
87*6e86bbc1SAndrew Rist { ocCell, {{ Value, Reference }, 0 }},
88*6e86bbc1SAndrew Rist { ocColumn, {{ Reference }, 0 }},
89*6e86bbc1SAndrew Rist { ocColumns, {{ Reference }, 1 }},
90*6e86bbc1SAndrew Rist { ocCorrel, {{ ForceArray, ForceArray }, 0 }},
91*6e86bbc1SAndrew Rist { ocCount, {{ Reference }, 1 }},
92*6e86bbc1SAndrew Rist { ocCount2, {{ Reference }, 1 }},
93*6e86bbc1SAndrew Rist { ocCountEmptyCells, {{ Reference }, 0 }},
94*6e86bbc1SAndrew Rist { ocCountIf, {{ Reference, Value }, 0 }},
95*6e86bbc1SAndrew Rist { ocCountIfs, {{ Reference, Value }, 2 }},
96*6e86bbc1SAndrew Rist { ocCovar, {{ ForceArray, ForceArray }, 0 }},
97*6e86bbc1SAndrew Rist { ocDBAverage, {{ Reference, Reference, Reference }, 0 }},
98*6e86bbc1SAndrew Rist { ocDBCount, {{ Reference, Reference, Reference }, 0 }},
99*6e86bbc1SAndrew Rist { ocDBCount2, {{ Reference, Reference, Reference }, 0 }},
100*6e86bbc1SAndrew Rist { ocDBGet, {{ Reference, Reference, Reference }, 0 }},
101*6e86bbc1SAndrew Rist { ocDBMax, {{ Reference, Reference, Reference }, 0 }},
102*6e86bbc1SAndrew Rist { ocDBMin, {{ Reference, Reference, Reference }, 0 }},
103*6e86bbc1SAndrew Rist { ocDBProduct, {{ Reference, Reference, Reference }, 0 }},
104*6e86bbc1SAndrew Rist { ocDBStdDev, {{ Reference, Reference, Reference }, 0 }},
105*6e86bbc1SAndrew Rist { ocDBStdDevP, {{ Reference, Reference, Reference }, 0 }},
106*6e86bbc1SAndrew Rist { ocDBSum, {{ Reference, Reference, Reference }, 0 }},
107*6e86bbc1SAndrew Rist { ocDBVar, {{ Reference, Reference, Reference }, 0 }},
108*6e86bbc1SAndrew Rist { ocDBVarP, {{ Reference, Reference, Reference }, 0 }},
109*6e86bbc1SAndrew Rist { ocDevSq, {{ Reference }, 1 }},
110*6e86bbc1SAndrew Rist { ocDiv, {{ Array, Array }, 0 }},
111*6e86bbc1SAndrew Rist { ocEqual, {{ Array, Array }, 0 }},
112*6e86bbc1SAndrew Rist { ocForecast, {{ Value, ForceArray, ForceArray }, 0 }},
113*6e86bbc1SAndrew Rist { ocFrequency, {{ Reference, Reference }, 0 }},
114*6e86bbc1SAndrew Rist { ocFTest, {{ ForceArray, ForceArray }, 0 }},
115*6e86bbc1SAndrew Rist { ocGeoMean, {{ Reference }, 1 }},
116*6e86bbc1SAndrew Rist { ocGCD, {{ Reference }, 1 }},
117*6e86bbc1SAndrew Rist { ocGreater, {{ Array, Array }, 0 }},
118*6e86bbc1SAndrew Rist { ocGreaterEqual, {{ Array, Array }, 0 }},
119*6e86bbc1SAndrew Rist { ocGrowth, {{ Reference, Reference, Reference, Value }, 0 }},
120*6e86bbc1SAndrew Rist { ocHarMean, {{ Reference }, 1 }},
121*6e86bbc1SAndrew Rist { ocHLookup, {{ Value, Reference, Value, Value }, 0 }},
122*6e86bbc1SAndrew Rist { ocIRR, {{ Reference, Value }, 0 }},
123*6e86bbc1SAndrew Rist { ocIndex, {{ Reference, Value, Value, Value }, 0 }},
124*6e86bbc1SAndrew Rist { ocIntercept, {{ ForceArray, ForceArray }, 0 }},
125*6e86bbc1SAndrew Rist { ocIntersect, {{ Reference, Reference }, 0 }},
126*6e86bbc1SAndrew Rist { ocIsRef, {{ Reference }, 0 }},
127*6e86bbc1SAndrew Rist { ocLCM, {{ Reference }, 1 }},
128*6e86bbc1SAndrew Rist { ocKurt, {{ Reference }, 1 }},
129*6e86bbc1SAndrew Rist { ocLarge, {{ Reference, Value }, 0 }},
130*6e86bbc1SAndrew Rist { ocLess, {{ Array, Array }, 0 }},
131*6e86bbc1SAndrew Rist { ocLessEqual, {{ Array, Array }, 0 }},
132*6e86bbc1SAndrew Rist { ocLookup, {{ Value, ReferenceOrForceArray, ReferenceOrForceArray }, 0 }},
133*6e86bbc1SAndrew Rist { ocMatch, {{ Value, Reference, Reference }, 0 }},
134*6e86bbc1SAndrew Rist { ocMatDet, {{ ForceArray }, 0 }},
135*6e86bbc1SAndrew Rist { ocMatInv, {{ ForceArray }, 0 }},
136*6e86bbc1SAndrew Rist { ocMatMult, {{ ForceArray, ForceArray }, 0 }},
137*6e86bbc1SAndrew Rist { ocMatTrans, {{ Array }, 0 }}, // strange, but Xcl doesn't force MatTrans array
138*6e86bbc1SAndrew Rist { ocMatValue, {{ Reference, Value, Value }, 0 }},
139*6e86bbc1SAndrew Rist { ocMax, {{ Reference }, 1 }},
140*6e86bbc1SAndrew Rist { ocMaxA, {{ Reference }, 1 }},
141*6e86bbc1SAndrew Rist { ocMedian, {{ Reference }, 1 }},
142*6e86bbc1SAndrew Rist { ocMin, {{ Reference }, 1 }},
143*6e86bbc1SAndrew Rist { ocMinA, {{ Reference }, 1 }},
144*6e86bbc1SAndrew Rist { ocMIRR, {{ Reference, Value, Value }, 0 }},
145*6e86bbc1SAndrew Rist { ocModalValue, {{ ForceArray }, 1 }},
146*6e86bbc1SAndrew Rist { ocMul, {{ Array, Array }, 0 }},
147*6e86bbc1SAndrew Rist { ocMultiArea, {{ Reference }, 1 }},
148*6e86bbc1SAndrew Rist { ocN, {{ Reference }, 0 }},
149*6e86bbc1SAndrew Rist { ocNPV, {{ Value, Reference }, 1 }},
150*6e86bbc1SAndrew Rist { ocNeg, {{ Array }, 0 }},
151*6e86bbc1SAndrew Rist { ocNegSub, {{ Array }, 0 }},
152*6e86bbc1SAndrew Rist { ocNot, {{ Array }, 0 }},
153*6e86bbc1SAndrew Rist { ocNotEqual, {{ Array, Array }, 0 }},
154*6e86bbc1SAndrew Rist { ocOffset, {{ Reference, Value, Value, Value, Value }, 0 }},
155*6e86bbc1SAndrew Rist { ocOr, {{ Reference }, 1 }},
156*6e86bbc1SAndrew Rist { ocPearson, {{ ForceArray, ForceArray }, 0 }},
157*6e86bbc1SAndrew Rist { ocPercentile, {{ Reference, Value }, 0 }},
158*6e86bbc1SAndrew Rist { ocPercentrank, {{ Reference, Value }, 0 }},
159*6e86bbc1SAndrew Rist { ocPow, {{ Array, Array }, 0 }},
160*6e86bbc1SAndrew Rist { ocPower, {{ Array, Array }, 0 }},
161*6e86bbc1SAndrew Rist { ocProb, {{ ForceArray, ForceArray, Value, Value }, 0 }},
162*6e86bbc1SAndrew Rist { ocProduct, {{ Reference }, 1 }},
163*6e86bbc1SAndrew Rist { ocQuartile, {{ Reference, Value }, 0 }},
164*6e86bbc1SAndrew Rist { ocRank, {{ Value, Reference, Value }, 0 }},
165*6e86bbc1SAndrew Rist { ocRGP, {{ Reference, Reference, Value, Value }, 0 }},
166*6e86bbc1SAndrew Rist { ocRKP, {{ Reference, Reference, Value, Value }, 0 }},
167*6e86bbc1SAndrew Rist { ocRow, {{ Reference }, 0 }},
168*6e86bbc1SAndrew Rist { ocRows, {{ Reference }, 1 }},
169*6e86bbc1SAndrew Rist { ocRSQ, {{ ForceArray, ForceArray }, 0 }},
170*6e86bbc1SAndrew Rist { ocSchiefe, {{ Reference }, 1 }},
171*6e86bbc1SAndrew Rist { ocSlope, {{ ForceArray, ForceArray }, 0 }},
172*6e86bbc1SAndrew Rist { ocSmall, {{ Reference, Value }, 0 }},
173*6e86bbc1SAndrew Rist { ocStDev, {{ Reference }, 1 }},
174*6e86bbc1SAndrew Rist { ocStDevA, {{ Reference }, 1 }},
175*6e86bbc1SAndrew Rist { ocStDevP, {{ Reference }, 1 }},
176*6e86bbc1SAndrew Rist { ocStDevPA, {{ Reference }, 1 }},
177*6e86bbc1SAndrew Rist { ocSTEYX, {{ ForceArray, ForceArray }, 0 }},
178*6e86bbc1SAndrew Rist { ocSub, {{ Array, Array }, 0 }},
179*6e86bbc1SAndrew Rist { ocSubTotal, {{ Value, Reference }, 1 }},
180*6e86bbc1SAndrew Rist { ocSum, {{ Reference }, 1 }},
181*6e86bbc1SAndrew Rist { ocSumIf, {{ Reference, Value, Reference }, 0 }},
182*6e86bbc1SAndrew Rist { ocSumIfs, {{ Reference, Reference, Value }, 2 }},
183*6e86bbc1SAndrew Rist { ocSumProduct, {{ ForceArray }, 1 }},
184*6e86bbc1SAndrew Rist { ocSumSQ, {{ Reference }, 1 }},
185*6e86bbc1SAndrew Rist { ocSumX2MY2, {{ ForceArray, ForceArray }, 0 }},
186*6e86bbc1SAndrew Rist { ocSumX2DY2, {{ ForceArray, ForceArray }, 0 }},
187*6e86bbc1SAndrew Rist { ocSumXMY2, {{ ForceArray, ForceArray }, 0 }},
188*6e86bbc1SAndrew Rist { ocTable, {{ Reference }, 0 }},
189*6e86bbc1SAndrew Rist { ocTables, {{ Reference }, 1 }},
190*6e86bbc1SAndrew Rist { ocTrend, {{ Reference, Reference, Reference, Value }, 0 }},
191*6e86bbc1SAndrew Rist { ocTrimMean, {{ Reference, Value }, 0 }},
192*6e86bbc1SAndrew Rist { ocTTest, {{ ForceArray, ForceArray, Value, Value }, 0 }},
193*6e86bbc1SAndrew Rist { ocVar, {{ Reference }, 1 }},
194*6e86bbc1SAndrew Rist { ocVarA, {{ Reference }, 1 }},
195*6e86bbc1SAndrew Rist { ocVarP, {{ Reference }, 1 }},
196*6e86bbc1SAndrew Rist { ocVarPA, {{ Reference }, 1 }},
197*6e86bbc1SAndrew Rist { ocVLookup, {{ Value, Reference, Value, Value }, 0 }},
198*6e86bbc1SAndrew Rist { ocXor, {{ Reference }, 1 }},
199*6e86bbc1SAndrew Rist { ocZTest, {{ Reference, Value, Value }, 0 }},
200cdf0e10cSrcweir // Excel doubts:
201cdf0e10cSrcweir // ocT: Excel says (and handles) Reference, error? This means no position
202cdf0e10cSrcweir // dependent SingleRef if DoubleRef, and no array calculation, just the
203cdf0e10cSrcweir // upper left corner. We never did that.
204*6e86bbc1SAndrew Rist { ocT, {{ Value }, 0 }},
205cdf0e10cSrcweir // The stopper.
206*6e86bbc1SAndrew Rist { ocNone, {{ Bounds }, 0 } }
207cdf0e10cSrcweir };
208cdf0e10cSrcweir
209cdf0e10cSrcweir ScParameterClassification::RunData * ScParameterClassification::pData = NULL;
210cdf0e10cSrcweir
211cdf0e10cSrcweir
Init()212cdf0e10cSrcweir void ScParameterClassification::Init()
213cdf0e10cSrcweir {
214cdf0e10cSrcweir if ( pData )
215cdf0e10cSrcweir return;
216cdf0e10cSrcweir pData = new RunData[ SC_OPCODE_LAST_OPCODE_ID + 1 ];
217cdf0e10cSrcweir memset( pData, 0, sizeof(RunData) * (SC_OPCODE_LAST_OPCODE_ID + 1));
218cdf0e10cSrcweir
219cdf0e10cSrcweir // init from specified static data above
220cdf0e10cSrcweir for ( size_t i=0; i < sizeof(pRawData) / sizeof(RawData); ++i )
221cdf0e10cSrcweir {
222cdf0e10cSrcweir const RawData* pRaw = &pRawData[i];
223cdf0e10cSrcweir if ( pRaw->eOp > SC_OPCODE_LAST_OPCODE_ID )
224cdf0e10cSrcweir {
225cdf0e10cSrcweir DBG_ASSERT( pRaw->eOp == ocNone, "RawData OpCode error");
226cdf0e10cSrcweir }
227cdf0e10cSrcweir else
228cdf0e10cSrcweir {
229cdf0e10cSrcweir RunData* pRun = &pData[ pRaw->eOp ];
230cdf0e10cSrcweir #ifdef DBG_UTIL
231cdf0e10cSrcweir if ( pRun->aData.nParam[0] != Unknown )
232cdf0e10cSrcweir {
233cdf0e10cSrcweir DBG_ERROR1( "already assigned: %d", pRaw->eOp);
234cdf0e10cSrcweir }
235cdf0e10cSrcweir #endif
236cdf0e10cSrcweir memcpy( &(pRun->aData), &(pRaw->aData), sizeof(CommonData));
237cdf0e10cSrcweir // fill 0-initialized fields with real values
238*6e86bbc1SAndrew Rist if ( pRun->aData.nRepeatLast )
239cdf0e10cSrcweir {
240cdf0e10cSrcweir for ( size_t j=0; j < CommonData::nMaxParams; ++j )
241cdf0e10cSrcweir {
242cdf0e10cSrcweir if ( pRun->aData.nParam[j] )
243cdf0e10cSrcweir pRun->nMinParams = sal::static_int_cast<sal_uInt8>( j+1 );
244*6e86bbc1SAndrew Rist else if (j >= pRun->aData.nRepeatLast)
245*6e86bbc1SAndrew Rist pRun->aData.nParam[j] = pRun->aData.nParam[j - pRun->aData.nRepeatLast];
246cdf0e10cSrcweir else
247*6e86bbc1SAndrew Rist {
248*6e86bbc1SAndrew Rist DBG_ERROR2( "bad classification: eOp %d, repeated param %d negative offset", pRaw->eOp, j);
249*6e86bbc1SAndrew Rist pRun->aData.nParam[j] = Unknown;
250*6e86bbc1SAndrew Rist }
251cdf0e10cSrcweir }
252cdf0e10cSrcweir }
253cdf0e10cSrcweir else
254cdf0e10cSrcweir {
255cdf0e10cSrcweir for ( size_t j=0; j < CommonData::nMaxParams; ++j )
256cdf0e10cSrcweir {
257cdf0e10cSrcweir if ( !pRun->aData.nParam[j] )
258cdf0e10cSrcweir {
259cdf0e10cSrcweir if ( j == 0 || pRun->aData.nParam[j-1] != Bounds )
260cdf0e10cSrcweir pRun->nMinParams = sal::static_int_cast<sal_uInt8>( j );
261cdf0e10cSrcweir pRun->aData.nParam[j] = Bounds;
262cdf0e10cSrcweir }
263cdf0e10cSrcweir }
264cdf0e10cSrcweir if ( !pRun->nMinParams &&
265cdf0e10cSrcweir pRun->aData.nParam[CommonData::nMaxParams-1] != Bounds)
266cdf0e10cSrcweir pRun->nMinParams = CommonData::nMaxParams;
267cdf0e10cSrcweir }
268cdf0e10cSrcweir for ( size_t j=0; j < CommonData::nMaxParams; ++j )
269cdf0e10cSrcweir {
270cdf0e10cSrcweir if ( pRun->aData.nParam[j] == ForceArray || pRun->aData.nParam[j] == ReferenceOrForceArray )
271cdf0e10cSrcweir {
272cdf0e10cSrcweir pRun->bHasForceArray = true;
273cdf0e10cSrcweir break; // for
274cdf0e10cSrcweir }
275cdf0e10cSrcweir }
276cdf0e10cSrcweir }
277cdf0e10cSrcweir }
278cdf0e10cSrcweir
279cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
280cdf0e10cSrcweir GenerateDocumentation();
281cdf0e10cSrcweir #endif
282cdf0e10cSrcweir }
283cdf0e10cSrcweir
284cdf0e10cSrcweir
Exit()285cdf0e10cSrcweir void ScParameterClassification::Exit()
286cdf0e10cSrcweir {
287cdf0e10cSrcweir delete [] pData;
288cdf0e10cSrcweir pData = NULL;
289cdf0e10cSrcweir }
290cdf0e10cSrcweir
291cdf0e10cSrcweir
GetParameterType(const formula::FormulaToken * pToken,sal_uInt16 nParameter)292cdf0e10cSrcweir ScParameterClassification::Type ScParameterClassification::GetParameterType(
293cdf0e10cSrcweir const formula::FormulaToken* pToken, sal_uInt16 nParameter)
294cdf0e10cSrcweir {
295cdf0e10cSrcweir OpCode eOp = pToken->GetOpCode();
296cdf0e10cSrcweir switch ( eOp )
297cdf0e10cSrcweir {
298cdf0e10cSrcweir case ocExternal:
299cdf0e10cSrcweir return GetExternalParameterType( pToken, nParameter);
300cdf0e10cSrcweir //break;
301cdf0e10cSrcweir case ocMacro:
302cdf0e10cSrcweir return Reference;
303cdf0e10cSrcweir //break;
304cdf0e10cSrcweir default:
305cdf0e10cSrcweir {
306cdf0e10cSrcweir // added to avoid warnings
307cdf0e10cSrcweir }
308cdf0e10cSrcweir }
309cdf0e10cSrcweir if ( 0 <= (short)eOp && eOp <= SC_OPCODE_LAST_OPCODE_ID )
310cdf0e10cSrcweir {
311*6e86bbc1SAndrew Rist sal_uInt8 nRepeat;
312*6e86bbc1SAndrew Rist Type eType;
313cdf0e10cSrcweir if ( nParameter < CommonData::nMaxParams )
314*6e86bbc1SAndrew Rist eType = pData[eOp].aData.nParam[nParameter];
315*6e86bbc1SAndrew Rist else if ( (nRepeat = pData[eOp].aData.nRepeatLast) > 0 )
316cdf0e10cSrcweir {
317*6e86bbc1SAndrew Rist // The usual case is 1 repeated parameter, we don't need to
318*6e86bbc1SAndrew Rist // calculate that on each call.
319*6e86bbc1SAndrew Rist sal_uInt16 nParam = (nRepeat > 1 ?
320*6e86bbc1SAndrew Rist (pData[eOp].nMinParams -
321*6e86bbc1SAndrew Rist ((nParameter - pData[eOp].nMinParams) % nRepeat)) :
322*6e86bbc1SAndrew Rist pData[eOp].nMinParams);
323*6e86bbc1SAndrew Rist return pData[eOp].aData.nParam[nParam];
324cdf0e10cSrcweir }
325cdf0e10cSrcweir else
326*6e86bbc1SAndrew Rist eType = Bounds;
327*6e86bbc1SAndrew Rist return eType == Unknown ? Value : eType;
328cdf0e10cSrcweir }
329cdf0e10cSrcweir return Unknown;
330cdf0e10cSrcweir }
331cdf0e10cSrcweir
332cdf0e10cSrcweir
333cdf0e10cSrcweir ScParameterClassification::Type
GetExternalParameterType(const formula::FormulaToken * pToken,sal_uInt16 nParameter)334cdf0e10cSrcweir ScParameterClassification::GetExternalParameterType( const formula::FormulaToken* pToken,
335cdf0e10cSrcweir sal_uInt16 nParameter)
336cdf0e10cSrcweir {
337cdf0e10cSrcweir Type eRet = Unknown;
338cdf0e10cSrcweir // similar to ScInterpreter::ScExternal()
339cdf0e10cSrcweir sal_uInt16 nIndex;
340cdf0e10cSrcweir String aUnoName;
341cdf0e10cSrcweir String aFuncName( ScGlobal::pCharClass->upper( pToken->GetExternal()));
342cdf0e10cSrcweir if ( ScGlobal::GetFuncCollection()->SearchFunc( aFuncName, nIndex) )
343cdf0e10cSrcweir {
344cdf0e10cSrcweir FuncData* pFuncData = (FuncData*)ScGlobal::GetFuncCollection()->At(
345cdf0e10cSrcweir nIndex);
346cdf0e10cSrcweir if ( nParameter >= pFuncData->GetParamCount() )
347cdf0e10cSrcweir eRet = Bounds;
348cdf0e10cSrcweir else
349cdf0e10cSrcweir {
350cdf0e10cSrcweir switch ( pFuncData->GetParamType( nParameter) )
351cdf0e10cSrcweir {
352cdf0e10cSrcweir case PTR_DOUBLE:
353cdf0e10cSrcweir case PTR_STRING:
354cdf0e10cSrcweir eRet = Value;
355cdf0e10cSrcweir break;
356cdf0e10cSrcweir default:
357cdf0e10cSrcweir eRet = Reference;
358cdf0e10cSrcweir // also array types are created using an area reference
359cdf0e10cSrcweir }
360cdf0e10cSrcweir }
361cdf0e10cSrcweir }
362cdf0e10cSrcweir else if ( (aUnoName = ScGlobal::GetAddInCollection()->FindFunction(
363cdf0e10cSrcweir aFuncName, sal_False)).Len() )
364cdf0e10cSrcweir {
365cdf0e10cSrcweir // the relevant parts of ScUnoAddInCall without having to create one
366cdf0e10cSrcweir const ScUnoAddInFuncData* pFuncData =
367cdf0e10cSrcweir ScGlobal::GetAddInCollection()->GetFuncData( aUnoName, true ); // need fully initialized data
368cdf0e10cSrcweir if ( pFuncData )
369cdf0e10cSrcweir {
370cdf0e10cSrcweir long nCount = pFuncData->GetArgumentCount();
371cdf0e10cSrcweir if ( nCount <= 0 )
372cdf0e10cSrcweir eRet = Bounds;
373cdf0e10cSrcweir else
374cdf0e10cSrcweir {
375cdf0e10cSrcweir const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
376cdf0e10cSrcweir if ( nParameter >= nCount &&
377cdf0e10cSrcweir pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
378cdf0e10cSrcweir eRet = Value;
379cdf0e10cSrcweir // last arg is sequence, optional "any"s, we simply can't
380cdf0e10cSrcweir // determine the type
381cdf0e10cSrcweir if ( eRet == Unknown )
382cdf0e10cSrcweir {
383cdf0e10cSrcweir if ( nParameter >= nCount )
384cdf0e10cSrcweir eRet = Bounds;
385cdf0e10cSrcweir else
386cdf0e10cSrcweir {
387cdf0e10cSrcweir switch ( pArgs[nParameter].eType )
388cdf0e10cSrcweir {
389cdf0e10cSrcweir case SC_ADDINARG_INTEGER:
390cdf0e10cSrcweir case SC_ADDINARG_DOUBLE:
391cdf0e10cSrcweir case SC_ADDINARG_STRING:
392cdf0e10cSrcweir eRet = Value;
393cdf0e10cSrcweir break;
394cdf0e10cSrcweir default:
395cdf0e10cSrcweir eRet = Reference;
396cdf0e10cSrcweir }
397cdf0e10cSrcweir }
398cdf0e10cSrcweir }
399cdf0e10cSrcweir }
400cdf0e10cSrcweir }
401cdf0e10cSrcweir }
402cdf0e10cSrcweir return eRet;
403cdf0e10cSrcweir }
404cdf0e10cSrcweir
405cdf0e10cSrcweir //-----------------------------------------------------------------------------
406cdf0e10cSrcweir
407cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
408cdf0e10cSrcweir
409cdf0e10cSrcweir // add remaining functions, all Value parameters
MergeArgumentsFromFunctionResource()410cdf0e10cSrcweir void ScParameterClassification::MergeArgumentsFromFunctionResource()
411cdf0e10cSrcweir {
412cdf0e10cSrcweir ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
413cdf0e10cSrcweir for ( const ScFuncDesc* pDesc = pFuncList->First(); pDesc;
414cdf0e10cSrcweir pDesc = pFuncList->Next() )
415cdf0e10cSrcweir {
416cdf0e10cSrcweir if ( pDesc->nFIndex > SC_OPCODE_LAST_OPCODE_ID ||
417cdf0e10cSrcweir pData[pDesc->nFIndex].aData.nParam[0] != Unknown )
418cdf0e10cSrcweir continue; // not an internal opcode or already done
419cdf0e10cSrcweir
420cdf0e10cSrcweir RunData* pRun = &pData[ pDesc->nFIndex ];
421cdf0e10cSrcweir sal_uInt16 nArgs = pDesc->GetSuppressedArgCount();
4221b1b70fbSAndrew Rist if ( nArgs >= PAIRED_VAR_ARGS )
4231b1b70fbSAndrew Rist {
4241b1b70fbSAndrew Rist nArgs -= PAIRED_VAR_ARGS - 2;
425*6e86bbc1SAndrew Rist pRun->aData.nRepeatLast = 2;
4261b1b70fbSAndrew Rist }
4271b1b70fbSAndrew Rist else if ( nArgs >= VAR_ARGS )
428cdf0e10cSrcweir {
429cdf0e10cSrcweir nArgs -= VAR_ARGS - 1;
430*6e86bbc1SAndrew Rist pRun->aData.nRepeatLast = 1;
431cdf0e10cSrcweir }
432cdf0e10cSrcweir if ( nArgs > CommonData::nMaxParams )
433cdf0e10cSrcweir {
434cdf0e10cSrcweir DBG_ERROR2( "ScParameterClassification::Init: too many arguments in listed function: %s: %d",
435cdf0e10cSrcweir ByteString( *(pDesc->pFuncName),
436cdf0e10cSrcweir RTL_TEXTENCODING_UTF8).GetBuffer(), nArgs);
437*6e86bbc1SAndrew Rist nArgs = CommonData::nMaxParams - 1;
438*6e86bbc1SAndrew Rist pRun->aData.nRepeatLast = 1;
439cdf0e10cSrcweir }
440cdf0e10cSrcweir pRun->nMinParams = static_cast< sal_uInt8 >( nArgs );
441cdf0e10cSrcweir for ( size_t j=0; j < nArgs; ++j )
442cdf0e10cSrcweir {
443cdf0e10cSrcweir pRun->aData.nParam[j] = Value;
444cdf0e10cSrcweir }
445*6e86bbc1SAndrew Rist if ( pRun->aData.nRepeatLast )
446cdf0e10cSrcweir {
447cdf0e10cSrcweir for ( size_t j = nArgs; j < CommonData::nMaxParams; ++j )
448cdf0e10cSrcweir {
449cdf0e10cSrcweir pRun->aData.nParam[j] = Value;
450cdf0e10cSrcweir }
451cdf0e10cSrcweir }
452cdf0e10cSrcweir else
453cdf0e10cSrcweir {
454cdf0e10cSrcweir for ( size_t j = nArgs; j < CommonData::nMaxParams; ++j )
455cdf0e10cSrcweir {
456cdf0e10cSrcweir pRun->aData.nParam[j] = Bounds;
457cdf0e10cSrcweir }
458cdf0e10cSrcweir }
459cdf0e10cSrcweir }
460cdf0e10cSrcweir }
461cdf0e10cSrcweir
462cdf0e10cSrcweir
GenerateDocumentation()463cdf0e10cSrcweir void ScParameterClassification::GenerateDocumentation()
464cdf0e10cSrcweir {
465cdf0e10cSrcweir static const sal_Char aEnvVarName[] = "OOO_CALC_GENPARCLASSDOC";
466cdf0e10cSrcweir if ( !getenv( aEnvVarName) )
467cdf0e10cSrcweir return;
468cdf0e10cSrcweir MergeArgumentsFromFunctionResource();
469cdf0e10cSrcweir ScAddress aAddress;
470cdf0e10cSrcweir ScCompiler aComp(NULL,aAddress);
471cdf0e10cSrcweir ScCompiler::OpCodeMapPtr xMap( aComp.GetOpCodeMap(::com::sun::star::sheet::FormulaLanguage::ENGLISH));
472cdf0e10cSrcweir if (!xMap)
473cdf0e10cSrcweir return;
474cdf0e10cSrcweir fflush( stderr);
475cdf0e10cSrcweir size_t nCount = xMap->getSymbolCount();
476cdf0e10cSrcweir for ( size_t i=0; i<nCount; ++i )
477cdf0e10cSrcweir {
478cdf0e10cSrcweir OpCode eOp = OpCode(i);
479cdf0e10cSrcweir if ( xMap->getSymbol(eOp).Len() )
480cdf0e10cSrcweir {
481cdf0e10cSrcweir fprintf( stdout, "%s: ", aEnvVarName);
482cdf0e10cSrcweir ByteString aStr( xMap->getSymbol(eOp), RTL_TEXTENCODING_UTF8);
483cdf0e10cSrcweir aStr += "(";
484cdf0e10cSrcweir formula::FormulaByteToken aToken( eOp);
485cdf0e10cSrcweir sal_uInt8 nParams = GetMinimumParameters( eOp);
486cdf0e10cSrcweir // preset parameter count according to opcode value, with some
487cdf0e10cSrcweir // special handling
488cdf0e10cSrcweir if ( eOp < SC_OPCODE_STOP_DIV )
489cdf0e10cSrcweir {
490cdf0e10cSrcweir switch ( eOp )
491cdf0e10cSrcweir {
492cdf0e10cSrcweir case ocIf:
493cdf0e10cSrcweir aToken.SetByte(3);
494cdf0e10cSrcweir break;
495cdf0e10cSrcweir case ocChose:
496cdf0e10cSrcweir aToken.SetByte(2);
497cdf0e10cSrcweir break;
498cdf0e10cSrcweir case ocPercentSign:
499cdf0e10cSrcweir aToken.SetByte(1);
500cdf0e10cSrcweir break;
501cdf0e10cSrcweir default:;
502cdf0e10cSrcweir }
503cdf0e10cSrcweir }
504cdf0e10cSrcweir else if ( eOp < SC_OPCODE_STOP_ERRORS )
505cdf0e10cSrcweir aToken.SetByte(0);
506cdf0e10cSrcweir else if ( eOp < SC_OPCODE_STOP_BIN_OP )
507cdf0e10cSrcweir {
508cdf0e10cSrcweir switch ( eOp )
509cdf0e10cSrcweir {
510cdf0e10cSrcweir case ocAnd:
511cdf0e10cSrcweir case ocOr:
512cdf0e10cSrcweir aToken.SetByte(1); // (r1)AND(r2) --> AND( r1, ...)
513cdf0e10cSrcweir break;
514cdf0e10cSrcweir default:
515cdf0e10cSrcweir aToken.SetByte(2);
516cdf0e10cSrcweir }
517cdf0e10cSrcweir }
518cdf0e10cSrcweir else if ( eOp < SC_OPCODE_STOP_UN_OP )
519cdf0e10cSrcweir aToken.SetByte(1);
520cdf0e10cSrcweir else if ( eOp < SC_OPCODE_STOP_NO_PAR )
521cdf0e10cSrcweir aToken.SetByte(0);
522cdf0e10cSrcweir else if ( eOp < SC_OPCODE_STOP_1_PAR )
523cdf0e10cSrcweir aToken.SetByte(1);
524cdf0e10cSrcweir else
525cdf0e10cSrcweir aToken.SetByte( nParams);
526cdf0e10cSrcweir // compare (this is a mere test for opcode order Div, BinOp, UnOp,
527cdf0e10cSrcweir // NoPar, 1Par, ...) and override parameter count with
528cdf0e10cSrcweir // classification
529cdf0e10cSrcweir if ( nParams != aToken.GetByte() )
530cdf0e10cSrcweir fprintf( stdout, "(parameter count differs, token Byte: %d classification: %d) ",
531cdf0e10cSrcweir aToken.GetByte(), nParams);
532cdf0e10cSrcweir aToken.SetByte( nParams);
533cdf0e10cSrcweir if ( nParams != aToken.GetParamCount() )
534cdf0e10cSrcweir fprintf( stdout, "(parameter count differs, token ParamCount: %d classification: %d) ",
535cdf0e10cSrcweir aToken.GetParamCount(), nParams);
536cdf0e10cSrcweir for ( sal_uInt16 j=0; j < nParams; ++j )
537cdf0e10cSrcweir {
538cdf0e10cSrcweir if ( j > 0 )
539cdf0e10cSrcweir aStr += ",";
540cdf0e10cSrcweir Type eType = GetParameterType( &aToken, j);
541cdf0e10cSrcweir switch ( eType )
542cdf0e10cSrcweir {
543cdf0e10cSrcweir case Value :
544cdf0e10cSrcweir aStr += " Value";
545cdf0e10cSrcweir break;
546cdf0e10cSrcweir case Reference :
547cdf0e10cSrcweir aStr += " Reference";
548cdf0e10cSrcweir break;
549cdf0e10cSrcweir case Array :
550cdf0e10cSrcweir aStr += " Array";
551cdf0e10cSrcweir break;
552cdf0e10cSrcweir case ForceArray :
553cdf0e10cSrcweir aStr += " ForceArray";
554cdf0e10cSrcweir break;
555cdf0e10cSrcweir case ReferenceOrForceArray :
556cdf0e10cSrcweir aStr += " ReferenceOrForceArray";
557cdf0e10cSrcweir break;
558cdf0e10cSrcweir case Bounds :
559cdf0e10cSrcweir aStr += " (Bounds, classification error?)";
560cdf0e10cSrcweir break;
561cdf0e10cSrcweir default:
562cdf0e10cSrcweir aStr += " (???, classification error?)";
563cdf0e10cSrcweir }
564cdf0e10cSrcweir }
565cdf0e10cSrcweir if ( HasRepeatParameters( eOp) )
566cdf0e10cSrcweir aStr += ", ...";
567cdf0e10cSrcweir if ( nParams )
568cdf0e10cSrcweir aStr += " ";
569cdf0e10cSrcweir aStr += ")";
570cdf0e10cSrcweir switch ( eOp )
571cdf0e10cSrcweir {
572cdf0e10cSrcweir case ocZGZ:
573cdf0e10cSrcweir aStr += " // RRI in English resource, but ZGZ in English-only section";
574cdf0e10cSrcweir break;
575cdf0e10cSrcweir case ocMultiArea:
576cdf0e10cSrcweir aStr += " // e.g. combined first parameter of INDEX() function, not a real function";
577cdf0e10cSrcweir break;
578cdf0e10cSrcweir case ocBackSolver:
579cdf0e10cSrcweir aStr += " // goal seek via menu, not a real function";
580cdf0e10cSrcweir break;
581cdf0e10cSrcweir case ocTableOp:
582cdf0e10cSrcweir aStr += " // MULTIPLE.OPERATIONS in English resource, but TABLE in English-only section";
583cdf0e10cSrcweir break;
584cdf0e10cSrcweir case ocNoName:
585cdf0e10cSrcweir aStr += " // error function, not a real function";
586cdf0e10cSrcweir break;
587cdf0e10cSrcweir default:;
588cdf0e10cSrcweir }
589cdf0e10cSrcweir fprintf( stdout, "%s\n", aStr.GetBuffer());
590cdf0e10cSrcweir }
591cdf0e10cSrcweir }
592cdf0e10cSrcweir fflush( stdout);
593cdf0e10cSrcweir }
594cdf0e10cSrcweir
595cdf0e10cSrcweir #endif // OSL_DEBUG_LEVEL
596cdf0e10cSrcweir
597