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: symtbl.cxx,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 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
39 SV_IMPL_PTRARR(SbiStrings
,String
*)
40 SV_IMPL_PTRARR(SbiSymbols
,SbiSymDef
*)
42 // Alle Symbolnamen werden im Stringpool des Symbol-Pools abgelegt, damit
43 // alle Symbole im gleichen Case verarbeitet werden. Beim Speichern des
44 // Code-Images wird der globale Stringpool mit den entsprechenden Sympools
45 // gespeichert. Der lokale Stringpool nimmt alle Symbole auf, die nicht
46 // ins Image wandern (Labels, Konstantennamen etc).
48 /***************************************************************************
52 ***************************************************************************/
54 SbiStringPool::SbiStringPool( SbiParser
* p
)
59 SbiStringPool::~SbiStringPool()
64 const String
& SbiStringPool::Find( USHORT n
) const
66 if( !n
|| n
> aData
.Count() )
69 return *aData
.GetObject( n
-1 );
72 // Hinzufuegen eines Strings. Der String wird Case-Insensitiv
75 short SbiStringPool::Add( const String
& rVal
, BOOL bNoCase
)
77 USHORT n
= aData
.Count();
78 for( USHORT i
= 0; i
< n
; i
++ )
80 String
* p
= aData
.GetObject( i
);
81 if( ( bNoCase
&& p
->Equals( rVal
) )
82 || ( !bNoCase
&& p
->EqualsIgnoreCaseAscii( rVal
) ) )
85 const String
* pNew
= new String( rVal
);
86 aData
.Insert( pNew
, n
++ );
90 short SbiStringPool::Add( double n
, SbxDataType t
)
95 case SbxINTEGER
: snprintf( buf
, sizeof(buf
), "%d", (short) n
); break;
96 case SbxLONG
: snprintf( buf
, sizeof(buf
), "%ld", (long) n
); break;
97 case SbxSINGLE
: snprintf( buf
, sizeof(buf
), "%.6g", (float) n
); break;
98 case SbxDOUBLE
: snprintf( buf
, sizeof(buf
), "%.16g", n
); break;
101 return Add( String::CreateFromAscii( buf
) );
104 /***************************************************************************
108 ***************************************************************************/
110 SbiSymPool::SbiSymPool( SbiStringPool
& r
, SbiSymScope s
) : rStrings( r
)
112 pParser
= r
.GetParser();
119 SbiSymPool::~SbiSymPool()
124 void SbiSymPool::Clear()
126 aData
.DeleteAndDestroy( 0, aData
.Count() );
129 SbiSymDef
* SbiSymPool::First()
135 SbiSymDef
* SbiSymPool::Next()
137 if( ++nCur
>= aData
.Count() )
140 return aData
.GetObject( nCur
);
143 // Hinzufuegen eines Symbols
145 SbiSymDef
* SbiSymPool::AddSym( const String
& rName
)
147 SbiSymDef
* p
= new SbiSymDef( rName
);
148 p
->nPos
= aData
.Count();
149 p
->nId
= rStrings
.Add( rName
);
150 p
->nProcId
= nProcId
;
152 const SbiSymDef
* q
= p
;
153 aData
.Insert( q
, q
->nPos
);
157 SbiProcDef
* SbiSymPool::AddProc( const String
& rName
)
159 SbiProcDef
* p
= new SbiProcDef( pParser
, rName
);
160 p
->nPos
= aData
.Count();
161 p
->nId
= rStrings
.Add( rName
);
162 // Procs sind immer global
165 const SbiSymDef
* q
= p
;
166 aData
.Insert( q
, q
->nPos
);
170 // Hinzufuegen einer extern aufgebauten Symboldefinition
172 void SbiSymPool::Add( SbiSymDef
* pDef
)
174 if( pDef
&& pDef
->pIn
!= this )
179 // schon in einem anderen Pool drin!
180 pParser
->Error( SbERR_INTERNAL_ERROR
, "Dbl Pool" );
185 pDef
->nPos
= aData
.Count();
188 // Bei statischen Variablen muss ein eindeutiger Name
189 // im Stringpool erzeugt werden (Form ProcName:VarName)
190 String
aName( pDef
->aName
);
191 if( pDef
->IsStatic() )
193 aName
= pParser
->aGblStrings
.Find( nProcId
);
195 aName
+= pDef
->aName
;
197 pDef
->nId
= rStrings
.Add( aName
);
199 // Procs sind immer global
200 if( !pDef
->GetProcDef() )
201 pDef
->nProcId
= nProcId
;
203 const SbiSymDef
* q
= pDef
;
204 aData
.Insert( q
, q
->nPos
);
208 // Suchen eines Eintrags ueber den Namen. Es wird auch im Parent gesucht.
210 SbiSymDef
* SbiSymPool::Find( const String
& rName
) const
212 for( USHORT i
= 0; i
< aData
.Count(); i
++ )
214 SbiSymDef
* p
= aData
.GetObject( i
);
215 if( ( !p
->nProcId
|| ( p
->nProcId
== nProcId
) )
216 && ( p
->aName
.EqualsIgnoreCaseAscii( rName
) ) )
220 return pParent
->Find( rName
);
225 // Suchen ueber ID-Nummer
227 SbiSymDef
* SbiSymPool::FindId( USHORT n
) const
229 for( USHORT i
= 0; i
< aData
.Count(); i
++ )
231 SbiSymDef
* p
= aData
.GetObject( i
);
232 if( p
->nId
== n
&& ( !p
->nProcId
|| ( p
->nProcId
== nProcId
) ) )
236 return pParent
->FindId( n
);
241 // Suchen ueber Position (ab 0)
243 SbiSymDef
* SbiSymPool::Get( USHORT n
) const
245 if( n
>= aData
.Count() )
248 return aData
.GetObject( n
);
251 UINT32
SbiSymPool::Define( const String
& rName
)
253 SbiSymDef
* p
= Find( rName
);
255 { if( p
->IsDefined() )
256 pParser
->Error( SbERR_LABEL_DEFINED
, rName
);
263 UINT32
SbiSymPool::Reference( const String
& rName
)
265 SbiSymDef
* p
= Find( rName
);
269 pParser
->aGen
.GenStmnt();
270 return p
->Reference();
273 // Alle offenen Referenzen anmaulen
275 void SbiSymPool::CheckRefs()
277 for( USHORT i
= 0; i
< aData
.Count(); i
++ )
279 SbiSymDef
* p
= aData
.GetObject( i
);
280 if( !p
->IsDefined() )
281 pParser
->Error( SbERR_UNDEF_LABEL
, p
->GetName() );
285 /***************************************************************************
287 |* Symbol-Definitionen
289 ***************************************************************************/
291 SbiSymDef::SbiSymDef( const String
& rName
) : aName( rName
)
314 SbiSymDef::~SbiSymDef()
319 SbiProcDef
* SbiSymDef::GetProcDef()
324 SbiConstDef
* SbiSymDef::GetConstDef()
329 // Wenn der Name benoetigt wird, den aktuellen Namen
330 // aus dem Stringpool nehmen
332 const String
& SbiSymDef::GetName()
335 aName
= pIn
->rStrings
.Find( nId
);
339 // Eintragen eines Datentyps
341 void SbiSymDef::SetType( SbxDataType t
)
343 if( t
== SbxVARIANT
&& pIn
)
345 sal_Unicode cu
= aName
.GetBuffer()[0];
348 char ch
= (char)aName
.GetBuffer()[0];
349 if( ch
== '_' ) ch
= 'Z';
350 int ch2
= toupper( ch
);
351 unsigned char c
= (unsigned char)ch2
;
352 if( c
> 0 && c
< 128 )
353 t
= pIn
->pParser
->eDefTypes
[ ch2
- 'A' ];
359 // Aufbau einer Backchain, falls noch nicht definiert
360 // Es wird der Wert zurueckgeliefert, der als Operand gespeichert
363 UINT32
SbiSymDef::Reference()
368 nChain
= pIn
->pParser
->aGen
.GetOffset();
374 // Definition eines Symbols.
375 // Hier wird der Backchain aufgeloest, falls vorhanden
377 UINT32
SbiSymDef::Define()
379 UINT32 n
= pIn
->pParser
->aGen
.GetPC();
380 pIn
->pParser
->aGen
.GenStmnt();
381 if( nChain
) pIn
->pParser
->aGen
.BackChain( nChain
);
387 // Eine Symboldefinition kann einen eigenen Pool haben. Dies ist
388 // der Fall bei Objekten und Prozeduren (lokale Variable)
390 SbiSymPool
& SbiSymDef::GetPool()
393 pPool
= new SbiSymPool( pIn
->pParser
->aGblStrings
, SbLOCAL
); // wird gedumpt
397 SbiSymScope
SbiSymDef::GetScope() const
399 return pIn
? pIn
->GetScope() : SbLOCAL
;
402 ////////////////////////////////////////////////////////////////////////////
404 // Die Prozedur-Definition hat drei Pools:
405 // 1) aParams: wird durch die Definition gefuellt. Enthaelt die Namen
406 // der Parameter, wie sie innerhalb des Rumpfes verwendet werden.
407 // Das erste Element ist der Returnwert.
408 // 2) pPool: saemtliche lokale Variable
409 // 3) aLabels: Labels
411 SbiProcDef::SbiProcDef( SbiParser
* pParser
, const String
& rName
,
414 , aParams( pParser
->aGblStrings
, SbPARAM
) // wird gedumpt
415 , aLabels( pParser
->aLclStrings
, SbLOCAL
) // wird nicht gedumpt
416 , mbProcDecl( bProcDecl
)
418 aParams
.SetParent( &pParser
->aPublics
);
419 pPool
= new SbiSymPool( pParser
->aGblStrings
, SbLOCAL
); // Locals
420 pPool
->SetParent( &aParams
);
423 mePropMode
= PROPERTY_MODE_NONE
;
427 // Fuer Returnwerte ist das erste Element der Parameterliste
428 // immer mit dem Namen und dem Typ der Proc definiert
429 aParams
.AddSym( aName
);
432 SbiProcDef::~SbiProcDef()
435 SbiProcDef
* SbiProcDef::GetProcDef()
440 void SbiProcDef::SetType( SbxDataType t
)
442 SbiSymDef::SetType( t
);
443 aParams
.Get( 0 )->SetType( eType
);
446 // Match mit einer Forward-Deklaration
447 // Falls der Match OK ist, wird pOld durch this im Pool ersetzt
448 // pOld wird immer geloescht!
450 void SbiProcDef::Match( SbiProcDef
* pOld
)
452 SbiSymDef
* po
, *pn
=NULL
;
453 // Parameter 0 ist der Funktionsname
455 for( i
= 1; i
< aParams
.GetSize(); i
++ )
457 po
= pOld
->aParams
.Get( i
);
458 pn
= aParams
.Get( i
);
459 // Kein Typabgleich; das wird beim Laufen erledigt
460 // aber ist sie evtl. mit zu wenigen Parametern aufgerufen
462 if( !po
&& !pn
->IsOptional() && !pn
->IsParamArray() )
464 po
= pOld
->aParams
.Next();
466 // Wurden zu viele Parameter angegeben?
467 if( pn
&& i
< aParams
.GetSize() && pOld
->pIn
)
469 // Die ganze Zeile markieren
470 pOld
->pIn
->GetParser()->SetCol1( 0 );
471 pOld
->pIn
->GetParser()->Error( SbERR_BAD_DECLARATION
, aName
);
473 if( !pIn
&& pOld
->pIn
)
475 // Alten Eintrag durch neuen ersetzen
476 SbiSymDef
** pData
= (SbiSymDef
**) pOld
->pIn
->aData
.GetData();
477 pData
[ pOld
->nPos
] = this;
485 void SbiProcDef::setPropertyMode( PropertyMode ePropMode
)
487 mePropMode
= ePropMode
;
488 if( mePropMode
!= PROPERTY_MODE_NONE
)
490 // Prop name = original scanned procedure name
493 // CompleteProcName includes "Property xxx "
494 // to avoid conflicts with other symbols
495 String aCompleteProcName
;
496 aCompleteProcName
.AppendAscii( "Property " );
499 case PROPERTY_MODE_GET
: aCompleteProcName
.AppendAscii( "Get " ); break;
500 case PROPERTY_MODE_LET
: aCompleteProcName
.AppendAscii( "Let " ); break;
501 case PROPERTY_MODE_SET
: aCompleteProcName
.AppendAscii( "Set " ); break;
502 case PROPERTY_MODE_NONE
:
503 DBG_ERROR( "Illegal PropertyMode PROPERTY_MODE_NONE" );
506 aCompleteProcName
+= aName
;
507 aName
= aCompleteProcName
;
512 //////////////////////////////////////////////////////////////////////////
514 SbiConstDef::SbiConstDef( const String
& rName
)
517 nVal
= 0; eType
= SbxINTEGER
;
520 void SbiConstDef::Set( double n
, SbxDataType t
)
522 aVal
.Erase(); nVal
= n
; eType
= t
;
525 void SbiConstDef::Set( const String
& n
)
527 aVal
= n
; nVal
= 0; eType
= SbxSTRING
;
530 SbiConstDef::~SbiConstDef()
533 SbiConstDef
* SbiConstDef::GetConstDef()