merge the formfield patch from ooo-build
[ooovba.git] / basic / source / comp / symtbl.cxx
blob21567561645bb38b198af27d6336d91892be05f2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: symtbl.cxx,v $
10 * $Revision: 1.20 $
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"
34 #include "sbcomp.hxx"
35 #include <stdio.h>
36 #include <string.h>
37 #include <ctype.h>
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 /***************************************************************************
50 |* SbiStringPool
52 ***************************************************************************/
54 SbiStringPool::SbiStringPool( SbiParser* p )
56 pParser = p;
59 SbiStringPool::~SbiStringPool()
62 // Suchen
64 const String& SbiStringPool::Find( USHORT n ) const
66 if( !n || n > aData.Count() )
67 return aEmpty;
68 else
69 return *aData.GetObject( n-1 );
72 // Hinzufuegen eines Strings. Der String wird Case-Insensitiv
73 // verglichen.
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 ) ) )
83 return i+1;
85 const String* pNew = new String( rVal );
86 aData.Insert( pNew, n++ );
87 return (short) n;
90 short SbiStringPool::Add( double n, SbxDataType t )
92 char buf[ 40 ];
93 switch( 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;
99 default: break;
101 return Add( String::CreateFromAscii( buf ) );
104 /***************************************************************************
106 |* SbiSymPool
108 ***************************************************************************/
110 SbiSymPool::SbiSymPool( SbiStringPool& r, SbiSymScope s ) : rStrings( r )
112 pParser = r.GetParser();
113 eScope = s;
114 pParent = NULL;
115 nCur =
116 nProcId = 0;
119 SbiSymPool::~SbiSymPool()
122 // Inhalt loeschen
124 void SbiSymPool::Clear()
126 aData.DeleteAndDestroy( 0, aData.Count() );
129 SbiSymDef* SbiSymPool::First()
131 nCur = (USHORT) -1;
132 return Next();
135 SbiSymDef* SbiSymPool::Next()
137 if( ++nCur >= aData.Count() )
138 return NULL;
139 else
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;
151 p->pIn = this;
152 const SbiSymDef* q = p;
153 aData.Insert( q, q->nPos );
154 return p;
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
163 p->nProcId = 0;
164 p->pIn = this;
165 const SbiSymDef* q = p;
166 aData.Insert( q, q->nPos );
167 return p;
170 // Hinzufuegen einer extern aufgebauten Symboldefinition
172 void SbiSymPool::Add( SbiSymDef* pDef )
174 if( pDef && pDef->pIn != this )
176 if( pDef->pIn )
178 #ifndef PRODUCT
179 // schon in einem anderen Pool drin!
180 pParser->Error( SbERR_INTERNAL_ERROR, "Dbl Pool" );
181 #endif
182 return;
185 pDef->nPos = aData.Count();
186 if( !pDef->nId )
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 );
194 aName += ':';
195 aName += pDef->aName;
197 pDef->nId = rStrings.Add( aName );
199 // Procs sind immer global
200 if( !pDef->GetProcDef() )
201 pDef->nProcId = nProcId;
202 pDef->pIn = this;
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 ) ) )
217 return p;
219 if( pParent )
220 return pParent->Find( rName );
221 else
222 return NULL;
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 ) ) )
233 return p;
235 if( pParent )
236 return pParent->FindId( n );
237 else
238 return NULL;
241 // Suchen ueber Position (ab 0)
243 SbiSymDef* SbiSymPool::Get( USHORT n ) const
245 if( n >= aData.Count() )
246 return NULL;
247 else
248 return aData.GetObject( n );
251 UINT32 SbiSymPool::Define( const String& rName )
253 SbiSymDef* p = Find( rName );
254 if( p )
255 { if( p->IsDefined() )
256 pParser->Error( SbERR_LABEL_DEFINED, rName );
258 else
259 p = AddSym( rName );
260 return p->Define();
263 UINT32 SbiSymPool::Reference( const String& rName )
265 SbiSymDef* p = Find( rName );
266 if( !p )
267 p = AddSym( rName );
268 //Sicherheitshalber
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 )
293 eType = SbxEMPTY;
294 nDims = 0;
295 nTypeId = 0;
296 nProcId = 0;
297 nId = 0;
298 nPos = 0;
299 nLen = 0;
300 nChain = 0;
301 bAs =
302 bNew =
303 bStatic =
304 bOpt =
305 bParamArray =
306 bByVal =
307 bChained =
308 bGlobal = FALSE;
309 pIn =
310 pPool = NULL;
311 nDefaultId = 0;
314 SbiSymDef::~SbiSymDef()
316 delete pPool;
319 SbiProcDef* SbiSymDef::GetProcDef()
321 return NULL;
324 SbiConstDef* SbiSymDef::GetConstDef()
326 return NULL;
329 // Wenn der Name benoetigt wird, den aktuellen Namen
330 // aus dem Stringpool nehmen
332 const String& SbiSymDef::GetName()
334 if( pIn )
335 aName = pIn->rStrings.Find( nId );
336 return aName;
339 // Eintragen eines Datentyps
341 void SbiSymDef::SetType( SbxDataType t )
343 if( t == SbxVARIANT && pIn )
345 sal_Unicode cu = aName.GetBuffer()[0];
346 if( cu < 256 )
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' ];
356 eType = t;
359 // Aufbau einer Backchain, falls noch nicht definiert
360 // Es wird der Wert zurueckgeliefert, der als Operand gespeichert
361 // werden soll.
363 UINT32 SbiSymDef::Reference()
365 if( !bChained )
367 UINT32 n = nChain;
368 nChain = pIn->pParser->aGen.GetOffset();
369 return n;
371 else return nChain;
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 );
382 nChain = n;
383 bChained = TRUE;
384 return nChain;
387 // Eine Symboldefinition kann einen eigenen Pool haben. Dies ist
388 // der Fall bei Objekten und Prozeduren (lokale Variable)
390 SbiSymPool& SbiSymDef::GetPool()
392 if( !pPool )
393 pPool = new SbiSymPool( pIn->pParser->aGblStrings, SbLOCAL ); // wird gedumpt
394 return *pPool;
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,
412 BOOL bProcDecl )
413 : SbiSymDef( 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 );
421 nLine1 =
422 nLine2 = 0;
423 mePropMode = PROPERTY_MODE_NONE;
424 bPublic = TRUE;
425 bCdecl = FALSE;
426 bStatic = FALSE;
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()
437 return this;
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
454 USHORT i;
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
461 // worden?
462 if( !po && !pn->IsOptional() && !pn->IsParamArray() )
463 break;
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;
478 nPos = pOld->nPos;
479 nId = pOld->nId;
480 pIn = pOld->pIn;
482 delete pOld;
485 void SbiProcDef::setPropertyMode( PropertyMode ePropMode )
487 mePropMode = ePropMode;
488 if( mePropMode != PROPERTY_MODE_NONE )
490 // Prop name = original scanned procedure name
491 maPropName = aName;
493 // CompleteProcName includes "Property xxx "
494 // to avoid conflicts with other symbols
495 String aCompleteProcName;
496 aCompleteProcName.AppendAscii( "Property " );
497 switch( mePropMode )
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" );
504 break;
506 aCompleteProcName += aName;
507 aName = aCompleteProcName;
512 //////////////////////////////////////////////////////////////////////////
514 SbiConstDef::SbiConstDef( const String& rName )
515 : SbiSymDef( 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()
535 return this;