1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: compiler.hxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #ifndef SC_COMPILER_HXX
32 #define SC_COMPILER_HXX
34 #include <string.h> // wg. memcpy() und bitte nicht memory.h (WKC)
36 #ifndef _SVMEMPOOL_HXX //autogen
37 #include <tools/mempool.hxx>
45 #ifndef _UNOTOOLS_CHARCLASS_HXX
46 #include <unotools/charclass.hxx>
49 #ifndef _RTL_USTRBUF_HXX_
50 #include <rtl/ustrbuf.hxx>
56 //-----------------------------------------------
58 // Konstanten und Datentypen auch fuer externe Module (Interpreter etc.):
60 #define MAXCODE 512 // Maximale Anzahl Tokens
61 #define MAXSTRLEN 256 // Maximale Laenge fuer Eingabestring
62 // (auch Formeln), "Verlaengerung" durch
63 // Namensvergabe moeglich
64 #define MAXJUMPCOUNT 32
65 #define MAXMATSIZE 100
66 #define SC_DOUBLE_MAXVALUE 1.7e307
68 #define errIllegalChar 501
69 #define errIllegalArgument 502
70 #define errIllegalFPOperation 503
71 #define errIllegalParameter 504
72 #define errIllegalJump 505
73 #define errSeparator 506
75 #define errPairExpected 508
76 #define errOperatorExpected 509
77 #define errVariableExpected 510
78 #define errParameterExpected 511
79 #define errCodeOverflow 512
80 #define errStringOverflow 513
81 #define errStackOverflow 514
82 #define errUnknownState 515
83 #define errUnknownVariable 516
84 #define errUnknownOpCode 517
85 #define errUnknownStackVariable 518
86 #define errNoValue 519
87 #define errUnknownToken 520
89 #define errCircularReference 522
90 #define errNoConvergence 523
93 #define errDoubleRef 526
94 #define errInterpOverflow 527
95 // wird nicht angezeigt, temporaer fuer TrackFormulas
96 // Zelle haengt von einer ab, die errCircularReference ist
97 #define errTrackFromCircRef 528
98 // Interpreter internal: existing cell has no value but value queried
99 #define errCellNoValue 529
100 // Interpreter: needed AddIn not found
101 #define errNoAddin 530
102 // Interpreter: needed Macro not found
103 #define errNoMacro 531
105 #define NOVALUE 0x7fff
108 // flag values of CharTable
109 #define SC_COMPILER_C_ILLEGAL 0x00000000
110 #define SC_COMPILER_C_CHAR 0x00000001
111 #define SC_COMPILER_C_CHAR_BOOL 0x00000002
112 #define SC_COMPILER_C_CHAR_WORD 0x00000004
113 #define SC_COMPILER_C_CHAR_VALUE 0x00000008
114 #define SC_COMPILER_C_CHAR_STRING 0x00000010
115 #define SC_COMPILER_C_CHAR_DONTCARE 0x00000020
116 #define SC_COMPILER_C_BOOL 0x00000040
117 #define SC_COMPILER_C_WORD 0x00000080 // auch in spstring.cxx dekl.
118 #define SC_COMPILER_C_WORD_SEP 0x00000100 // und rangenam.cxx (WORD und CHAR_WORD)
119 #define SC_COMPILER_C_VALUE 0x00000200
120 #define SC_COMPILER_C_VALUE_SEP 0x00000400
121 #define SC_COMPILER_C_VALUE_EXP 0x00000800
122 #define SC_COMPILER_C_VALUE_SIGN 0x00001000
123 #define SC_COMPILER_C_VALUE_VALUE 0x00002000
124 #define SC_COMPILER_C_STRING_SEP 0x00004000
125 #define SC_COMPILER_C_NAME_SEP 0x00008000 // es kann nur einen geben! '\''
126 #define SC_COMPILER_C_CHAR_IDENT 0x00010000 // identifier (built-in function) start
127 #define SC_COMPILER_C_IDENT 0x00020000 // identifier continuation
129 #define SC_COMPILER_FILE_TAB_SEP '#' // 'Doc'#Tab auch in global2.cxx
136 // Konstanten und Datentypen compilerintern:
141 OpCode eOp; // OpCode
142 StackVar eType; // type of data
143 USHORT nRefCnt; // reference count
144 BOOL bRaw; // nicht per Clone auf passende Groesse getrimmt
148 #define SC_TOKEN_FIX_MEMBERS \
154 struct ScDoubleRawToken
160 { // union nur um gleiches Alignment wie ScRawToken sicherzustellen
164 DECL_FIXEDMEMPOOL_NEWDEL( ScDoubleRawToken
);
169 friend class ScCompiler
;
170 // Friends, die temporaere Raw-Tokens auf dem Stack benutzen (und deswegen
171 // den private dtor brauchen) und wissen, was sie tun..
172 friend class ScTokenArray
;
173 friend class ScInterpreter
;
182 USHORT nIndex
; // Index fuer Name-Tabelle
183 sal_Unicode cStr
[ MAXSTRLEN
+1 ]; // String (bis 255 Zeichen + 0)
184 short nJump
[MAXJUMPCOUNT
+1]; // If/Chose-Token
187 ScRawToken() : bRaw( TRUE
) {}
189 ~ScRawToken() {} //! nur via Delete() loeschen
191 DECL_FIXEDMEMPOOL_NEWDEL( ScRawToken
);
192 StackVar
GetType() const { return (StackVar
) eType
; }
193 OpCode
GetOpCode() const { return (OpCode
) eOp
; }
194 void NewOpCode( OpCode e
) { eOp
= e
; }
195 void IncRef() { nRefCnt
++; }
196 void DecRef() { if( !--nRefCnt
) Delete(); }
197 USHORT
GetRef() const { return nRefCnt
; }
200 // Diese Methoden nur auf Tokens, die nicht im TokenArray stehen,
201 // anwenden, da der RefCount auf 0 gesetzt wird!
202 void SetOpCode( OpCode eCode
);
203 void SetString( const sal_Unicode
* pStr
);
204 void SetSingleReference( const SingleRefData
& rRef
);
205 void SetDoubleReference( const ComplRefData
& rRef
);
206 void SetDouble( double fVal
);
207 void SetName( USHORT n
);
208 void SetExternal(const sal_Unicode
* pStr
);
210 ScRawToken
* Clone() const; // real copy!
211 ScToken
* CreateToken() const; // create typified token
212 void Load30( SvStream
& );
213 void Load( SvStream
&, USHORT nVer
);
215 static xub_StrLen
GetStrLen( const sal_Unicode
* pStr
); // as long as a "string" is an array
216 static size_t GetStrLenBytes( xub_StrLen nLen
)
217 { return nLen
* sizeof(sal_Unicode
); }
218 static size_t GetStrLenBytes( const sal_Unicode
* pStr
)
219 { return GetStrLenBytes( GetStrLen( pStr
) ); }
227 inline ScRawTokenRef() { p
= NULL
; }
228 inline ScRawTokenRef( const ScRawTokenRef
& r
) { if( ( p
= r
.p
) != NULL
) p
->IncRef(); }
229 inline ScRawTokenRef( ScRawToken
*t
) { if( ( p
= t
) != NULL
) t
->IncRef(); }
230 inline void Clear() { if( p
) p
->DecRef(); }
231 inline ~ScRawTokenRef() { if( p
) p
->DecRef(); }
232 inline ScRawTokenRef
& operator=( const ScRawTokenRef
& r
) { return *this = r
.p
; }
233 inline ScRawTokenRef
& operator=( ScRawToken
* t
)
234 { if( t
) t
->IncRef(); if( p
) p
->DecRef(); p
= t
; return *this; }
235 inline BOOL
Is() const { return p
!= NULL
; }
236 inline BOOL
operator ! () const { return p
== NULL
; }
237 inline ScRawToken
* operator&() const { return p
; }
238 inline ScRawToken
* operator->() const { return p
; }
239 inline ScRawToken
& operator*() const { return *p
; }
240 inline operator ScRawToken
*() const { return p
; }
245 { // alter RecalcMode bis einschliesslich 4.0
248 RC_ONLOAD
, // immer nach dem Laden
249 RC_ONLOAD_ONCE
, // einmal nach dem Laden
250 RC_FORCED
, // auch wenn Zelle nicht sichtbar
251 RC_ONREFMOVE
// wenn Referenz bewegt wurde (ab SP3, 05.11.97)
254 // neuer (ab 5.0, 14.01.98) RecalcMode Zugriff nur noch noch via TokenArray
255 // SetRecalcMode / IsRecalcMode...
257 typedef BYTE ScRecalcMode
;
258 // von den exklusiven Bits kann nur eins gesetzt sein
259 // wird von TokenArray SetRecalcMode... Methoden gehandelt
260 #define RECALCMODE_NORMAL 0x01 // exklusiv
261 #define RECALCMODE_ALWAYS 0x02 // exklusiv, immer
262 #define RECALCMODE_ONLOAD 0x04 // exklusiv, immer nach dem Laden
263 #define RECALCMODE_ONLOAD_ONCE 0x08 // exklusiv, einmal nach dem Laden
264 #define RECALCMODE_FORCED 0x10 // kombiniert, auch wenn Zelle nicht sichtbar
265 #define RECALCMODE_ONREFMOVE 0x20 // kombiniert, wenn Referenz bewegt wurde
266 #define RECALCMODE_EMASK 0x0F // Maske der exklusiven Bits
267 // werden neue Bits definiert, muessen ExportRecalcMode40 und AddRecalcMode
272 friend class ScCompiler
;
273 friend class ScTokenIterator
;
275 ScToken
** pCode
; // Token code array
276 ScToken
** pRPN
; // RPN array
277 USHORT nLen
; // Length of token array
278 USHORT nRPN
; // Length of RPN array
279 USHORT nIndex
; // Current step index
280 USHORT nError
; // Error code
281 short nRefs
; // Count of cell references
282 ScRecalcMode nMode
; // Flags to indicate when to recalc this code
283 BOOL bReplacedSharedFormula
; // If code was created by replacing
284 // a shared formula, a temporary flag during
285 // UpdateReference() until StartListeningTo()
287 void Assign( const ScTokenArray
& );
289 ScToken
* Add( ScToken
* );
290 void ImportRecalcMode40( ScRecalcMode40
);
291 ScRecalcMode40
ExportRecalcMode40() const;
292 inline void SetCombinedBitsRecalcMode( ScRecalcMode nBits
)
293 { nMode
|= (nBits
& ~RECALCMODE_EMASK
); }
294 inline ScRecalcMode
GetCombinedBitsRecalcMode() const
295 { return nMode
& ~RECALCMODE_EMASK
; }
296 inline void SetMaskedRecalcMode( ScRecalcMode nBits
)
297 { nMode
= GetCombinedBitsRecalcMode() | nBits
; }
298 // in nMode gesetzte exklusive Bits werden genullt,
299 // nVal kann auch kombinierte Bits enthalten,
300 // aber nur ein exklusives Bit darf gesetzt sein!
302 BOOL
ImplGetReference( ScRange
& rRange
, BOOL bValidOnly
) const;
306 ScTokenArray( const ScTokenArray
& ); // Zuweisung mit Referenzen auf Tokens
308 ScTokenArray
* Clone() const; // echte Kopie!
311 ScToken
* First() { nIndex
= 0; return Next(); }
313 ScToken
* GetNextReference();
314 ScToken
* GetNextReferenceRPN();
315 ScToken
* GetNextReferenceOrName();
316 ScToken
* GetNextOpCodeRPN( OpCode
);
318 ScToken
* PeekPrevNoSpaces(); // nur nach First/Next/Last/Prev !
319 ScToken
* PeekNextNoSpaces(); // nur nach First/Next/Last/Prev !
320 ScToken
* FirstRPN() { nIndex
= 0; return NextRPN(); }
323 BOOL
HasOpCodeRPN( OpCode
) const;
324 BOOL
HasNameOrColRowName() const; // token of type svIndex or opcode ocColRowName
325 BOOL
IsReference( ScRange
& rRange
) const; // exactly and only one range (valid or deleted)
327 ScToken
** GetArray() const { return pCode
; }
328 ScToken
** GetCode() const { return pRPN
; }
329 USHORT
GetLen() const { return nLen
; }
330 USHORT
GetCodeLen() const { return nRPN
; }
331 void Reset() { nIndex
= 0; }
332 USHORT
GetError() const { return nError
; }
333 void SetError( USHORT n
) { nError
= n
; }
334 short GetRefs() const { return nRefs
; }
335 void SetReplacedSharedFormula( BOOL bVal
) { bReplacedSharedFormula
= bVal
; }
336 BOOL
IsReplacedSharedFormula() const { return bReplacedSharedFormula
; }
338 inline ScRecalcMode
GetRecalcMode() const { return nMode
; }
339 void AddRecalcMode( ScRecalcMode nBits
);
340 // Bits werden nicht direkt gesetzt sondern
341 // geprueft und evtl. nach Prio behandelt,
342 // wenn mehrere exklusive gesetzt sind!
344 inline void ClearRecalcMode() { nMode
= RECALCMODE_NORMAL
; }
345 inline void SetRecalcModeNormal()
346 { SetMaskedRecalcMode( RECALCMODE_NORMAL
); }
347 inline void SetRecalcModeAlways()
348 { SetMaskedRecalcMode( RECALCMODE_ALWAYS
); }
349 inline void SetRecalcModeOnLoad()
350 { SetMaskedRecalcMode( RECALCMODE_ONLOAD
); }
351 inline void SetRecalcModeOnLoadOnce()
352 { SetMaskedRecalcMode( RECALCMODE_ONLOAD_ONCE
); }
353 inline void SetRecalcModeForced()
354 { nMode
|= RECALCMODE_FORCED
; }
355 inline void ClearRecalcModeForced()
356 { nMode
&= ~RECALCMODE_FORCED
; }
357 inline void SetRecalcModeOnRefMove()
358 { nMode
|= RECALCMODE_ONREFMOVE
; }
359 inline void ClearRecalcModeOnRefMove()
360 { nMode
&= ~RECALCMODE_ONREFMOVE
; }
361 inline BOOL
IsRecalcModeNormal() const
362 { return (nMode
& RECALCMODE_NORMAL
) != 0; }
363 inline BOOL
IsRecalcModeAlways() const
364 { return (nMode
& RECALCMODE_ALWAYS
) != 0; }
365 inline BOOL
IsRecalcModeOnLoad() const
366 { return (nMode
& RECALCMODE_ONLOAD
) != 0; }
367 inline BOOL
IsRecalcModeOnLoadOnce() const
368 { return (nMode
& RECALCMODE_ONLOAD_ONCE
) != 0; }
369 inline BOOL
IsRecalcModeForced() const
370 { return (nMode
& RECALCMODE_FORCED
) != 0; }
371 inline BOOL
IsRecalcModeOnRefMove() const
372 { return (nMode
& RECALCMODE_ONREFMOVE
) != 0; }
374 inline OpCode
GetOuterFuncOpCode(); // OpCode der aeusseren Funktion
375 BOOL
HasMatrixDoubleRefOps();
377 void Load30( SvStream
&, const ScAddress
& );
378 void Load( SvStream
&, USHORT
, const ScAddress
& );
379 void Store( SvStream
&, const ScAddress
& ) const;
381 ScToken
* AddToken( const ScRawToken
& );
382 ScToken
* AddToken( const ScToken
& );
383 ScToken
* AddOpCode( OpCode eCode
);
384 ScToken
* AddString( const sal_Unicode
* pStr
);
385 ScToken
* AddString( const String
& rStr
);
386 ScToken
* AddDouble( double fVal
);
387 ScToken
* AddSingleReference( const SingleRefData
& rRef
);
388 ScToken
* AddDoubleReference( const ComplRefData
& rRef
);
389 ScToken
* AddExternal( const sal_Unicode
* pStr
);
390 ScToken
* AddExternal( const String
& rStr
);
391 ScToken
* AddBad( const String
& rStr
); // ocBad with String
393 // Zuweisung mit Referenzen auf Tokens
394 ScTokenArray
& operator=( const ScTokenArray
& );
397 inline OpCode
ScTokenArray::GetOuterFuncOpCode()
400 return pRPN
[nRPN
-1]->GetOpCode();
404 struct ImpTokenIterator
;
406 class ScTokenIterator
408 friend class ScInterpreter
; // fuer Jump()
409 ImpTokenIterator
* pCur
;
410 void Jump( short nStart
, short nNext
);
411 void Push( ScTokenArray
* );
414 ScTokenIterator( const ScTokenArray
& );
417 const ScToken
* Next();
422 struct ScStringHashCode
424 size_t operator()( const String
& rStr
) const
426 return rtl_ustr_hashCode_WithLength( rStr
.GetBuffer(), rStr
.Len() );
429 typedef ::std::hash_map
< String
, OpCode
, ScStringHashCode
, ::std::equal_to
< String
> > ScOpCodeHashMap
;
434 static String
* pSymbolTableNative
; // array of native symbols, offset==OpCode
435 static String
* pSymbolTableEnglish
; // array of English symbols, offset==OpCode
436 static USHORT nAnzStrings
; // count of symbols
437 static ScOpCodeHashMap
* pSymbolHashMapNative
; // hash map of native symbols
438 static ScOpCodeHashMap
* pSymbolHashMapEnglish
; // hash map of English symbols
440 static ULONG
* pCharTable
; // array of ASCII character flags
443 String cFormula
; // String -> TokenArray
444 String aCorrectedFormula
; // autocorrected Formula
445 String aCorrectedSymbol
; // autocorrected Symbol
446 sal_Unicode cSymbol
[MAXSTRLEN
]; // current Symbol
447 String aFormula
; // formula source code
448 xub_StrLen nSrcPos
; // tokenizer position (source code)
450 ScRawTokenRef pRawToken
;
454 ScArrayStack
* pStack
;
455 String
* pSymbolTable
; // which symbol table is used
456 ScOpCodeHashMap
* pSymbolHashMap
; // which symbol hash map is used
458 short nNumFmt
; // bei CompileTokenArray() gesetzt
459 short nMaxTab
; // letzte Tabelle im Doc
460 short nRecursion
; // GetToken Rekursionen
461 BOOL glSubTotal
; // Merkvariablen fuer Zelle
462 BOOL bAutoCorrect
; // AutoCorrection ausfuehren
463 BOOL bCorrected
; // AutoCorrection ausgefuehrt
464 BOOL bCompileForFAP
; //! kein echtes RPN sondern Namen
465 // werden nicht aufgeloest
466 BOOL bIgnoreErrors
; // bei AutoCorrect und CompileForFAP
467 // trotz Fehler RPN erzeugen
474 void PutCode( ScToken
* );
486 void MakeColStr( ::rtl::OUStringBuffer
& rBuffer
, USHORT nCol
);
487 void MakeRowStr( ::rtl::OUStringBuffer
& rBuffer
, USHORT nRow
);
488 String
MakeTabStr( USHORT nTab
, String
& aDoc
);
489 void MakeRefStr( ::rtl::OUStringBuffer
& rBuffer
, ComplRefData
& rRefData
, BOOL bSingleRef
);
491 void SetError(USHORT nError
);
492 xub_StrLen
NextSymbol();
493 BOOL
IsValue( const String
& );
494 BOOL
IsOpCode( const String
& );
495 BOOL
IsOpCode2( const String
& );
497 BOOL
IsReference( const String
& );
498 BOOL
IsMacro( const String
& );
499 BOOL
IsNamedRange( const String
& );
500 BOOL
IsDBRange( const String
& );
501 BOOL
IsColRowName( const String
& );
502 void AutoCorrectParsedSymbol();
503 void PushTokenArray( ScTokenArray
*, BOOL
= FALSE
);
504 void PopTokenArray();
505 void SetRelNameReference();
507 ScCompiler(ScDocument
* pDocument
, const ScAddress
& );
509 ScCompiler( ScDocument
* pDocument
, const ScAddress
&,
510 const ScTokenArray
& rArr
);
513 static void DeInit();
514 static void CheckTabQuotes( String
& ); // fuer ScAddress::Format()
516 // schliesst String in Quotes ein, wenn nicht-alphanumerische Zeichen
517 // enthalten sind, bestehende Quotes werden escaped
518 static BOOL
EnQuote( String
& );
519 // entfernt Quotes, escaped Quotes werden unescaped
520 static BOOL
DeQuote( String
& );
522 //! _entweder_ CompileForFAP _oder_ AutoCorrection, _nicht_ beides
523 void SetCompileForFAP( BOOL bVal
)
524 { bCompileForFAP
= bVal
; bIgnoreErrors
= bVal
; }
525 void SetAutoCorrection( BOOL bVal
)
526 { bAutoCorrect
= bVal
; bIgnoreErrors
= bVal
; }
527 void SetCompileEnglish( BOOL bVal
); // use English SymbolTable
528 void SetCompileXML( BOOL bVal
)
529 { bCompileXML
= bVal
; }
530 void SetImportXML( BOOL bVal
)
531 { bImportXML
= bVal
; }
532 BOOL
IsCorrected() { return bCorrected
; }
533 const String
& GetCorrectedFormula() { return aCorrectedFormula
; }
534 ScTokenArray
* CompileString( const String
& rFormula
);
535 BOOL
CompileTokenArray();
536 short GetNumFormatType() { return nNumFmt
; }
538 ScToken
* CreateStringFromToken( String
& rFormula
, ScToken
* pToken
,
539 BOOL bAllowArrAdvance
= FALSE
);
540 ScToken
* CreateStringFromToken( ::rtl::OUStringBuffer
& rBuffer
, ScToken
* pToken
,
541 BOOL bAllowArrAdvance
= FALSE
);
542 void CreateStringFromTokenArray( String
& rFormula
);
543 void CreateStringFromTokenArray( ::rtl::OUStringBuffer
& rBuffer
);
547 BOOL
UpdateNameReference( UpdateRefMode eUpdateRefMode
,
549 short nDx
, short nDy
, short nDz
,
552 ScRangeData
* UpdateInsertTab(USHORT nTable
, BOOL bIsName
);
553 ScRangeData
* UpdateDeleteTab(USHORT nTable
, BOOL bIsMove
, BOOL bIsName
, BOOL
& bCompile
);
555 /// Is the CharTable initialized? If not call Init() yourself!
556 static inline BOOL
HasCharTable() { return pCharTable
!= NULL
; }
558 /// Access the CharTable flags
559 static inline ULONG
GetCharTableFlags( sal_Unicode c
)
560 { return c
< 128 ? pCharTable
[ UINT8(c
) ] : 0; }
562 /// If the character is allowed as first character in sheet names or references
563 static inline BOOL
IsCharWordChar( sal_Unicode c
)
566 ((pCharTable
[ UINT8(c
) ] & SC_COMPILER_C_CHAR_WORD
) == SC_COMPILER_C_CHAR_WORD
) :
567 ScGlobal::pCharClass
->isLetterNumeric( c
);
570 /// If the character is allowed in sheet names or references
571 static inline BOOL
IsWordChar( sal_Unicode c
)
574 ((pCharTable
[ UINT8(c
) ] & SC_COMPILER_C_WORD
) == SC_COMPILER_C_WORD
) :
575 ScGlobal::pCharClass
->isLetterNumeric( c
);
579 } //namespace binfilter