xref: /AOO41X/main/sc/source/core/tool/parclass.cxx (revision 6e86bbc1711eee2d6409c09806e70b9f0929471f)
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