Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / tool / parclass.cxx
blob550b116250e3744334131c4af2ffaa0ba99c22ce
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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 <string.h>
31 #if OSL_DEBUG_LEVEL > 1
32 // the documentation thingy
33 #include <stdio.h>
34 #include <com/sun/star/sheet/FormulaLanguage.hpp>
35 #include <rtl/strbuf.hxx>
36 #include "compiler.hxx"
37 #include "sc.hrc"
38 #endif
40 /* Following assumptions are made:
41 * - OpCodes not specified at all will have at least one and only parameters of
42 * type Value, no check is done on the count of parameters => no Bounds type
43 * is returned.
44 * - For OpCodes with a variable number of parameters the type(s) of the last
45 * repeated parameter(s) specified determine(s) the type(s) of all following
46 * parameters.
49 const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
51 // { OpCode, {{ Type, ... }, nRepeatLast }},
53 // IF() and CHOOSE() are somewhat special, since the ScJumpMatrix is
54 // created inside those functions and ConvertMatrixParameters() is not
55 // called for them.
56 { ocIf, {{ Array, Reference, Reference }, 0 }},
57 { ocIfError, {{ Array, Reference }, 0 }},
58 { ocIfNA, {{ Array, Reference }, 0 }},
59 { ocChose, {{ Array, Reference }, 1 }},
60 // Other specials.
61 { ocOpen, {{ Bounds }, 0 }},
62 { ocClose, {{ Bounds }, 0 }},
63 { ocSep, {{ Bounds }, 0 }},
64 { ocNoName, {{ Bounds }, 0 }},
65 { ocErrCell, {{ Bounds }, 0 }},
66 { ocStop, {{ Bounds }, 0 }},
67 { ocUnion, {{ Reference, Reference }, 0 }},
68 { ocRange, {{ Reference, Reference }, 0 }},
69 // Functions with Value parameters only but not in resource.
70 { ocBackSolver, {{ Value, Value, Value }, 0 }},
71 { ocTableOp, {{ Value, Value, Value, Value, Value }, 0 }},
72 // Operators and functions.
73 { ocAdd, {{ Array, Array }, 0 }},
74 { ocAmpersand, {{ Array, Array }, 0 }},
75 { ocAnd, {{ Reference }, 1 }},
76 { ocAreas, {{ Reference }, 0 }},
77 { ocAveDev, {{ Reference }, 1 }},
78 { ocAverage, {{ Reference }, 1 }},
79 { ocAverageA, {{ Reference }, 1 }},
80 { ocAverageIf, {{ Reference, Value, Reference }, 0 }},
81 { ocAverageIfs, {{ Reference, Reference, Value }, 2 }},
82 { ocCell, {{ Value, Reference }, 0 }},
83 { ocColumn, {{ Reference }, 0 }},
84 { ocColumns, {{ Reference }, 1 }},
85 { ocCorrel, {{ ForceArray, ForceArray }, 0 }},
86 { ocCount, {{ Reference }, 1 }},
87 { ocCount2, {{ Reference }, 1 }},
88 { ocCountEmptyCells, {{ Reference }, 0 }},
89 { ocCountIf, {{ Reference, Value }, 0 }},
90 { ocCountIfs, {{ Reference, Value }, 2 }},
91 { ocCovar, {{ ForceArray, ForceArray }, 0 }},
92 { ocCovarianceP, {{ ForceArray, ForceArray }, 0 }},
93 { ocCovarianceS, {{ ForceArray, ForceArray }, 0 }},
94 { ocDBAverage, {{ Reference, Reference, Reference }, 0 }},
95 { ocDBCount, {{ Reference, Reference, Reference }, 0 }},
96 { ocDBCount2, {{ Reference, Reference, Reference }, 0 }},
97 { ocDBGet, {{ Reference, Reference, Reference }, 0 }},
98 { ocDBMax, {{ Reference, Reference, Reference }, 0 }},
99 { ocDBMin, {{ Reference, Reference, Reference }, 0 }},
100 { ocDBProduct, {{ Reference, Reference, Reference }, 0 }},
101 { ocDBStdDev, {{ Reference, Reference, Reference }, 0 }},
102 { ocDBStdDevP, {{ Reference, Reference, Reference }, 0 }},
103 { ocDBSum, {{ Reference, Reference, Reference }, 0 }},
104 { ocDBVar, {{ Reference, Reference, Reference }, 0 }},
105 { ocDBVarP, {{ Reference, Reference, Reference }, 0 }},
106 { ocDevSq, {{ Reference }, 1 }},
107 { ocDiv, {{ Array, Array }, 0 }},
108 { ocEqual, {{ Array, Array }, 0 }},
109 { ocForecast, {{ Value, ForceArray, ForceArray }, 0 }},
110 { ocFrequency, {{ Reference, Reference }, 0 }},
111 { ocFTest, {{ ForceArray, ForceArray }, 0 }},
112 { ocGeoMean, {{ Reference }, 1 }},
113 { ocGCD, {{ Reference }, 1 }},
114 { ocGreater, {{ Array, Array }, 0 }},
115 { ocGreaterEqual, {{ Array, Array }, 0 }},
116 { ocGrowth, {{ Reference, Reference, Reference, Value }, 0 }},
117 { ocHarMean, {{ Reference }, 1 }},
118 { ocHLookup, {{ Value, Reference, Value, Value }, 0 }},
119 { ocIRR, {{ Reference, Value }, 0 }},
120 { ocIndex, {{ Reference, Value, Value, Value }, 0 }},
121 { ocIntercept, {{ ForceArray, ForceArray }, 0 }},
122 { ocIntersect, {{ Reference, Reference }, 0 }},
123 { ocIsRef, {{ Reference }, 0 }},
124 { ocLCM, {{ Reference }, 1 }},
125 { ocKurt, {{ Reference }, 1 }},
126 { ocLarge, {{ Reference, Value }, 0 }},
127 { ocLess, {{ Array, Array }, 0 }},
128 { ocLessEqual, {{ Array, Array }, 0 }},
129 { ocLookup, {{ Value, ReferenceOrForceArray, ReferenceOrForceArray }, 0 }},
130 { ocMatch, {{ Value, Reference, Reference }, 0 }},
131 { ocMatDet, {{ ForceArray }, 0 }},
132 { ocMatInv, {{ ForceArray }, 0 }},
133 { ocMatMult, {{ ForceArray, ForceArray }, 0 }},
134 { ocMatTrans, {{ Array }, 0 }}, // strange, but Xcl doesn't force MatTrans array
135 { ocMatValue, {{ Reference, Value, Value }, 0 }},
136 { ocMax, {{ Reference }, 1 }},
137 { ocMaxA, {{ Reference }, 1 }},
138 { ocMedian, {{ Reference }, 1 }},
139 { ocMin, {{ Reference }, 1 }},
140 { ocMinA, {{ Reference }, 1 }},
141 { ocMIRR, {{ Reference, Value, Value }, 0 }},
142 { ocModalValue, {{ ForceArray }, 1 }},
143 { ocMul, {{ Array, Array }, 0 }},
144 { ocMultiArea, {{ Reference }, 1 }},
145 { ocNPV, {{ Value, Reference }, 1 }},
146 { ocNeg, {{ Array }, 0 }},
147 { ocNegSub, {{ Array }, 0 }},
148 { ocNot, {{ Array }, 0 }},
149 { ocNotEqual, {{ Array, Array }, 0 }},
150 { ocOffset, {{ Reference, Value, Value, Value, Value }, 0 }},
151 { ocOr, {{ Reference }, 1 }},
152 { ocPearson, {{ ForceArray, ForceArray }, 0 }},
153 { ocPercentile, {{ Reference, Value }, 0 }},
154 { ocPercentrank, {{ Reference, Value }, 0 }},
155 { ocPow, {{ Array, Array }, 0 }},
156 { ocPower, {{ Array, Array }, 0 }},
157 { ocProb, {{ ForceArray, ForceArray, Value, Value }, 0 }},
158 { ocProduct, {{ Reference }, 1 }},
159 { ocQuartile, {{ Reference, Value }, 0 }},
160 { ocRank, {{ Value, Reference, Value }, 0 }},
161 { ocRGP, {{ Reference, Reference, Value, Value }, 0 }},
162 { ocRKP, {{ Reference, Reference, Value, Value }, 0 }},
163 { ocRow, {{ Reference }, 0 }},
164 { ocRows, {{ Reference }, 1 }},
165 { ocRSQ, {{ ForceArray, ForceArray }, 0 }},
166 { ocSchiefe, {{ Reference }, 1 }},
167 { ocSkewp, {{ Reference }, 1 }},
168 { ocSlope, {{ ForceArray, ForceArray }, 0 }},
169 { ocSmall, {{ Reference, Value }, 0 }},
170 { ocStDev, {{ Reference }, 1 }},
171 { ocStDevA, {{ Reference }, 1 }},
172 { ocStDevP, {{ Reference }, 1 }},
173 { ocStDevPA, {{ Reference }, 1 }},
174 { ocStDevP_MS, {{ Reference }, 1 }},
175 { ocStDevS, {{ Reference }, 1 }},
176 { ocSTEYX, {{ ForceArray, ForceArray }, 0 }},
177 { ocSub, {{ Array, Array }, 0 }},
178 { ocSubTotal, {{ Value, Reference }, 1 }},
179 { ocSum, {{ Reference }, 1 }},
180 { ocSumIf, {{ Reference, Value, Reference }, 0 }},
181 { ocSumIfs, {{ Reference, Reference, Value }, 2 }},
182 { ocSumProduct, {{ ForceArray }, 1 }},
183 { ocSumSQ, {{ Reference }, 1 }},
184 { ocSumX2MY2, {{ ForceArray, ForceArray }, 0 }},
185 { ocSumX2DY2, {{ ForceArray, ForceArray }, 0 }},
186 { ocSumXMY2, {{ ForceArray, ForceArray }, 0 }},
187 { ocTable, {{ Reference }, 0 }},
188 { ocTables, {{ Reference }, 1 }},
189 { ocTrend, {{ Reference, Reference, Reference, Value }, 0 }},
190 { ocTrimMean, {{ Reference, Value }, 0 }},
191 { ocTTest, {{ ForceArray, ForceArray, Value, Value }, 0 }},
192 { ocVar, {{ Reference }, 1 }},
193 { ocVarA, {{ Reference }, 1 }},
194 { ocVarP, {{ Reference }, 1 }},
195 { ocVarPA, {{ Reference }, 1 }},
196 { ocVarP_MS, {{ Reference }, 1 }},
197 { ocVarS, {{ Reference }, 1 }},
198 { ocVLookup, {{ Value, Reference, Value, Value }, 0 }},
199 { ocXor, {{ Reference }, 1 }},
200 { ocZTest, {{ Reference, Value, Value }, 0 }},
201 // Excel doubts:
202 // ocN, ocT: Excel says (and handles) Reference, error? This means no
203 // position dependent SingleRef if DoubleRef, and no array calculation,
204 // just the upper left corner. We never did that for ocT and now also not
205 // for ocN (position dependent intersection worked before but array
206 // didn't). No specifics in ODFF, so the general rule applies. Gnumeric
207 // does the same.
208 { ocN, {{ Value }, 0 }},
209 { ocT, {{ Value }, 0 }},
210 // The stopper.
211 { ocNone, {{ Bounds }, 0 } }
214 ScParameterClassification::RunData * ScParameterClassification::pData = NULL;
216 void ScParameterClassification::Init()
218 if ( pData )
219 return;
220 pData = new RunData[ SC_OPCODE_LAST_OPCODE_ID + 1 ];
221 memset( pData, 0, sizeof(RunData) * (SC_OPCODE_LAST_OPCODE_ID + 1));
223 // init from specified static data above
224 for ( size_t i=0; i < SAL_N_ELEMENTS(pRawData); ++i )
226 const RawData* pRaw = &pRawData[i];
227 if ( pRaw->eOp > SC_OPCODE_LAST_OPCODE_ID )
229 OSL_ENSURE( pRaw->eOp == ocNone, "RawData OpCode error");
231 else
233 RunData* pRun = &pData[ pRaw->eOp ];
234 #if OSL_DEBUG_LEVEL > 1
235 if ( pRun->aData.nParam[0] != Unknown )
237 OSL_TRACE( "already assigned: %d", pRaw->eOp);
239 #endif
240 memcpy( &(pRun->aData), &(pRaw->aData), sizeof(CommonData));
241 // fill 0-initialized fields with real values
242 if ( pRun->aData.nRepeatLast )
244 for ( sal_Int32 j=0; j < CommonData::nMaxParams; ++j )
246 if ( pRun->aData.nParam[j] )
247 pRun->nMinParams = sal::static_int_cast<sal_uInt8>( j+1 );
248 else if (j >= pRun->aData.nRepeatLast)
249 pRun->aData.nParam[j] = pRun->aData.nParam[j - pRun->aData.nRepeatLast];
250 else
252 OSL_TRACE( "bad classification: eOp %d, repeated param %d negative offset", pRaw->eOp, j);
253 pRun->aData.nParam[j] = Unknown;
257 else
259 for ( sal_Int32 j=0; j < CommonData::nMaxParams; ++j )
261 if ( !pRun->aData.nParam[j] )
263 if ( j == 0 || pRun->aData.nParam[j-1] != Bounds )
264 pRun->nMinParams = sal::static_int_cast<sal_uInt8>( j );
265 pRun->aData.nParam[j] = Bounds;
268 if ( !pRun->nMinParams &&
269 pRun->aData.nParam[CommonData::nMaxParams-1] != Bounds)
270 pRun->nMinParams = CommonData::nMaxParams;
272 for ( sal_Int32 j=0; j < CommonData::nMaxParams; ++j )
274 if ( pRun->aData.nParam[j] == ForceArray || pRun->aData.nParam[j] == ReferenceOrForceArray )
276 pRun->bHasForceArray = true;
277 break; // for
283 #if OSL_DEBUG_LEVEL > 1
284 GenerateDocumentation();
285 #endif
288 void ScParameterClassification::Exit()
290 delete [] pData;
291 pData = NULL;
294 ScParameterClassification::Type ScParameterClassification::GetParameterType(
295 const formula::FormulaToken* pToken, sal_uInt16 nParameter)
297 OpCode eOp = pToken->GetOpCode();
298 switch ( eOp )
300 case ocExternal:
301 return GetExternalParameterType( pToken, nParameter);
302 //break;
303 case ocMacro:
304 return Reference;
305 //break;
306 default:
308 // added to avoid warnings
311 if ( 0 <= (short)eOp && eOp <= SC_OPCODE_LAST_OPCODE_ID )
313 sal_uInt8 nRepeat;
314 Type eType;
315 if ( nParameter < CommonData::nMaxParams )
316 eType = pData[eOp].aData.nParam[nParameter];
317 else if ( (nRepeat = pData[eOp].aData.nRepeatLast) > 0 )
319 // The usual case is 1 repeated parameter, we don't need to
320 // calculate that on each call.
321 sal_uInt16 nParam = (nRepeat > 1 ?
322 (pData[eOp].nMinParams -
323 ((nParameter - pData[eOp].nMinParams) % nRepeat)) :
324 pData[eOp].nMinParams);
325 return pData[eOp].aData.nParam[nParam];
327 else
328 eType = Bounds;
329 return eType == Unknown ? Value : eType;
331 return Unknown;
334 ScParameterClassification::Type
335 ScParameterClassification::GetExternalParameterType( const formula::FormulaToken* pToken,
336 sal_uInt16 nParameter)
338 Type eRet = Unknown;
339 // similar to ScInterpreter::ScExternal()
340 OUString aFuncName = ScGlobal::pCharClass->uppercase( pToken->GetExternal());
342 const FuncData* pFuncData = ScGlobal::GetFuncCollection()->findByName(aFuncName);
343 if (pFuncData)
345 if ( nParameter >= pFuncData->GetParamCount() )
346 eRet = Bounds;
347 else
349 switch ( pFuncData->GetParamType( nParameter) )
351 case PTR_DOUBLE:
352 case PTR_STRING:
353 eRet = Value;
354 break;
355 default:
356 eRet = Reference;
357 // also array types are created using an area reference
360 return eRet;
364 OUString aUnoName =
365 ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false);
367 if (!aUnoName.isEmpty())
369 // the relevant parts of ScUnoAddInCall without having to create one
370 const ScUnoAddInFuncData* pFuncData =
371 ScGlobal::GetAddInCollection()->GetFuncData( aUnoName, true ); // need fully initialized data
372 if ( pFuncData )
374 long nCount = pFuncData->GetArgumentCount();
375 if ( nCount <= 0 )
376 eRet = Bounds;
377 else
379 const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
380 if ( nParameter >= nCount &&
381 pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
382 eRet = Value;
383 // last arg is sequence, optional "any"s, we simply can't
384 // determine the type
385 if ( eRet == Unknown )
387 if ( nParameter >= nCount )
388 eRet = Bounds;
389 else
391 switch ( pArgs[nParameter].eType )
393 case SC_ADDINARG_INTEGER:
394 case SC_ADDINARG_DOUBLE:
395 case SC_ADDINARG_STRING:
396 eRet = Value;
397 break;
398 default:
399 eRet = Reference;
406 return eRet;
409 #if OSL_DEBUG_LEVEL > 1
411 // add remaining functions, all Value parameters
412 void ScParameterClassification::MergeArgumentsFromFunctionResource()
414 ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
415 for ( const ScFuncDesc* pDesc = pFuncList->First(); pDesc;
416 pDesc = pFuncList->Next() )
418 if ( pDesc->nFIndex > SC_OPCODE_LAST_OPCODE_ID ||
419 pData[pDesc->nFIndex].aData.nParam[0] != Unknown )
420 continue; // not an internal opcode or already done
422 RunData* pRun = &pData[ pDesc->nFIndex ];
423 sal_uInt16 nArgs = pDesc->GetSuppressedArgCount();
424 if ( nArgs >= PAIRED_VAR_ARGS )
426 nArgs -= PAIRED_VAR_ARGS - 2;
427 pRun->aData.nRepeatLast = 2;
429 else if ( nArgs >= VAR_ARGS )
431 nArgs -= VAR_ARGS - 1;
432 pRun->aData.nRepeatLast = 1;
434 if ( nArgs > CommonData::nMaxParams )
436 OStringBuffer aBuf;
437 aBuf.append("ScParameterClassification::Init: too many arguments in listed function: ");
438 aBuf.append(OUStringToOString(*(pDesc->pFuncName), RTL_TEXTENCODING_UTF8));
439 aBuf.append(": ");
440 aBuf.append(sal_Int32(nArgs));
441 OSL_FAIL( aBuf.getStr());
442 nArgs = CommonData::nMaxParams - 1;
443 pRun->aData.nRepeatLast = 1;
445 pRun->nMinParams = static_cast< sal_uInt8 >( nArgs );
446 for ( sal_Int32 j=0; j < nArgs; ++j )
448 pRun->aData.nParam[j] = Value;
450 if ( pRun->aData.nRepeatLast )
452 for ( sal_Int32 j = nArgs; j < CommonData::nMaxParams; ++j )
454 pRun->aData.nParam[j] = Value;
457 else
459 for ( sal_Int32 j = nArgs; j < CommonData::nMaxParams; ++j )
461 pRun->aData.nParam[j] = Bounds;
467 void ScParameterClassification::GenerateDocumentation()
469 static const sal_Char aEnvVarName[] = "OOO_CALC_GENPARCLASSDOC";
470 if ( !getenv( aEnvVarName) )
471 return;
472 MergeArgumentsFromFunctionResource();
473 ScAddress aAddress;
474 ScCompiler aComp(NULL,aAddress);
475 ScCompiler::OpCodeMapPtr xMap( aComp.GetOpCodeMap(::com::sun::star::sheet::FormulaLanguage::ENGLISH));
476 if (!xMap)
477 return;
478 fflush( stderr);
479 size_t nCount = xMap->getSymbolCount();
480 for ( size_t i=0; i<nCount; ++i )
482 OpCode eOp = OpCode(i);
483 if ( !xMap->getSymbol(eOp).isEmpty() )
485 fprintf( stdout, "%s: ", aEnvVarName);
486 OStringBuffer aStr(OUStringToOString(xMap->getSymbol(eOp), RTL_TEXTENCODING_UTF8));
487 aStr.append('(');
488 formula::FormulaByteToken aToken( eOp);
489 sal_uInt8 nParams = GetMinimumParameters( eOp);
490 // preset parameter count according to opcode value, with some
491 // special handling
492 if ( eOp < SC_OPCODE_STOP_DIV )
494 switch ( eOp )
496 case ocIf:
497 aToken.SetByte(3);
498 break;
499 case ocIfError:
500 case ocIfNA:
501 case ocChose:
502 aToken.SetByte(2);
503 break;
504 case ocPercentSign:
505 aToken.SetByte(1);
506 break;
507 default:;
510 else if ( eOp < SC_OPCODE_STOP_ERRORS )
511 aToken.SetByte(0);
512 else if ( eOp < SC_OPCODE_STOP_BIN_OP )
514 switch ( eOp )
516 case ocAnd:
517 case ocOr:
518 aToken.SetByte(1); // (r1)AND(r2) --> AND( r1, ...)
519 break;
520 default:
521 aToken.SetByte(2);
524 else if ( eOp < SC_OPCODE_STOP_UN_OP )
525 aToken.SetByte(1);
526 else if ( eOp < SC_OPCODE_STOP_NO_PAR )
527 aToken.SetByte(0);
528 else if ( eOp < SC_OPCODE_STOP_1_PAR )
529 aToken.SetByte(1);
530 else
531 aToken.SetByte( nParams);
532 // compare (this is a mere test for opcode order Div, BinOp, UnOp,
533 // NoPar, 1Par, ...) and override parameter count with
534 // classification
535 if ( nParams != aToken.GetByte() )
536 fprintf( stdout, "(parameter count differs, token Byte: %d classification: %d) ",
537 aToken.GetByte(), nParams);
538 aToken.SetByte( nParams);
539 if ( nParams != aToken.GetParamCount() )
540 fprintf( stdout, "(parameter count differs, token ParamCount: %d classification: %d) ",
541 aToken.GetParamCount(), nParams);
542 for ( sal_uInt16 j=0; j < nParams; ++j )
544 if ( j > 0 )
545 aStr.append(',');
546 Type eType = GetParameterType( &aToken, j);
547 switch ( eType )
549 case Value :
550 aStr.append(" Value");
551 break;
552 case Reference :
553 aStr.append(" Reference");
554 break;
555 case Array :
556 aStr.append(" Array");
557 break;
558 case ForceArray :
559 aStr.append(" ForceArray");
560 break;
561 case ReferenceOrForceArray :
562 aStr.append(" ReferenceOrForceArray");
563 break;
564 case Bounds :
565 aStr.append(" (Bounds, classification error?)");
566 break;
567 default:
568 aStr.append(" (???, classification error?)");
571 if ( HasRepeatParameters( eOp) )
572 aStr.append(", ...");
573 if ( nParams )
574 aStr.append(' ');
575 aStr.append(')');
576 switch ( eOp )
578 case ocZGZ:
579 aStr.append(" // RRI in English resource, but ZGZ in English-only section");
580 break;
581 case ocMultiArea:
582 aStr.append(" // e.g. combined first parameter of INDEX() function, not a real function");
583 break;
584 case ocBackSolver:
585 aStr.append(" // goal seek via menu, not a real function");
586 break;
587 case ocTableOp:
588 aStr.append(" // MULTIPLE.OPERATIONS in English resource, but TABLE in English-only section");
589 break;
590 case ocNoName:
591 aStr.append(" // error function, not a real function");
592 break;
593 default:;
595 fprintf( stdout, "%s\n", aStr.getStr());
598 fflush( stdout);
601 #endif // OSL_DEBUG_LEVEL
603 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */