xref: /trunk/main/basic/source/comp/symtbl.cxx (revision e1f63238)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basic.hxx"
26 
27 #include "sbcomp.hxx"
28 #include <stdio.h>
29 #include <string.h>
30 #include <ctype.h>
31 
SV_IMPL_PTRARR(SbiStrings,String *)32 SV_IMPL_PTRARR(SbiStrings,String*)
33 SV_IMPL_PTRARR(SbiSymbols,SbiSymDef*)
34 
35 // Alle Symbolnamen werden im Stringpool des Symbol-Pools abgelegt, damit
36 // alle Symbole im gleichen Case verarbeitet werden. Beim Speichern des
37 // Code-Images wird der globale Stringpool mit den entsprechenden Sympools
38 // gespeichert. Der lokale Stringpool nimmt alle Symbole auf, die nicht
39 // ins Image wandern (Labels, Konstantennamen etc).
40 
41 /***************************************************************************
42 |*
43 |*	SbiStringPool
44 |*
45 ***************************************************************************/
46 
47 SbiStringPool::SbiStringPool( SbiParser* p )
48 {
49 	pParser = p;
50 }
51 
~SbiStringPool()52 SbiStringPool::~SbiStringPool()
53 {}
54 
55 // Suchen
56 
Find(sal_uInt16 n) const57 const String& SbiStringPool::Find( sal_uInt16 n ) const
58 {
59 	if( !n || n > aData.Count() )
60 		return aEmpty;
61 	else
62 		return *aData.GetObject( n-1 );
63 }
64 
65 // Hinzufuegen eines Strings. Der String wird Case-Insensitiv
66 // verglichen.
67 
Add(const String & rVal,sal_Bool bNoCase)68 short SbiStringPool::Add( const String& rVal, sal_Bool bNoCase )
69 {
70 	sal_uInt16 n = aData.Count();
71 	for( sal_uInt16 i = 0; i < n; i++ )
72 	{
73 		String* p = aData.GetObject( i );
74 		if( (  bNoCase && p->Equals( rVal ) )
75 		 || ( !bNoCase && p->EqualsIgnoreCaseAscii( rVal ) ) )
76 			return i+1;
77 	}
78 	const String* pNew = new String( rVal );
79 	aData.Insert( pNew, n++ );
80 	return (short) n;
81 }
82 
Add(double n,SbxDataType t)83 short SbiStringPool::Add( double n, SbxDataType t )
84 {
85 	char buf[ 40 ];
86 	switch( t )
87 	{
88         case SbxINTEGER: snprintf( buf, sizeof(buf), "%d", (short) n ); break;
89         case SbxLONG:    snprintf( buf, sizeof(buf), "%ld", (long) n ); break;
90         case SbxSINGLE:  snprintf( buf, sizeof(buf), "%.6g", (float) n ); break;
91         case SbxDOUBLE:  snprintf( buf, sizeof(buf), "%.16g", n ); break;
92 		default: break;
93 	}
94 	return Add( String::CreateFromAscii( buf ) );
95 }
96 
97 /***************************************************************************
98 |*
99 |*	SbiSymPool
100 |*
101 ***************************************************************************/
102 
SbiSymPool(SbiStringPool & r,SbiSymScope s)103 SbiSymPool::SbiSymPool( SbiStringPool& r, SbiSymScope s ) : rStrings( r )
104 {
105 	pParser	 = r.GetParser();
106 	eScope   = s;
107 	pParent  = NULL;
108 	nCur	 =
109 	nProcId  = 0;
110 }
111 
~SbiSymPool()112 SbiSymPool::~SbiSymPool()
113 {}
114 
115 // Inhalt loeschen
116 
Clear()117 void SbiSymPool::Clear()
118 {
119 	aData.DeleteAndDestroy( 0, aData.Count() );
120 }
121 
First()122 SbiSymDef* SbiSymPool::First()
123 {
124 	nCur = (sal_uInt16) -1;
125 	return Next();
126 }
127 
Next()128 SbiSymDef* SbiSymPool::Next()
129 {
130 	if( ++nCur >= aData.Count() )
131 		return NULL;
132 	else
133 		return aData.GetObject( nCur );
134 }
135 
136 // Hinzufuegen eines Symbols
137 
AddSym(const String & rName)138 SbiSymDef* SbiSymPool::AddSym( const String& rName )
139 {
140 	SbiSymDef* p = new SbiSymDef( rName );
141 	p->nPos    = aData.Count();
142 	p->nId	   = rStrings.Add( rName );
143 	p->nProcId = nProcId;
144 	p->pIn	   = this;
145 	const SbiSymDef* q = p;
146 	aData.Insert( q, q->nPos );
147 	return p;
148 }
149 
AddProc(const String & rName)150 SbiProcDef* SbiSymPool::AddProc( const String& rName )
151 {
152 	SbiProcDef* p = new SbiProcDef( pParser, rName );
153 	p->nPos    = aData.Count();
154 	p->nId	   = rStrings.Add( rName );
155 	// Procs sind immer global
156 	p->nProcId = 0;
157 	p->pIn	   = this;
158 	const SbiSymDef* q = p;
159 	aData.Insert( q, q->nPos );
160 	return p;
161 }
162 
163 // Hinzufuegen einer extern aufgebauten Symboldefinition
164 
Add(SbiSymDef * pDef)165 void SbiSymPool::Add( SbiSymDef* pDef )
166 {
167 	if( pDef && pDef->pIn != this )
168 	{
169 		if( pDef->pIn )
170 		{
171 #ifdef DBG_UTIL
172 			// schon in einem anderen Pool drin!
173 			pParser->Error( SbERR_INTERNAL_ERROR, "Dbl Pool" );
174 #endif
175 			return;
176 		}
177 
178 		pDef->nPos = aData.Count();
179 		if( !pDef->nId )
180 		{
181 			// Bei statischen Variablen muss ein eindeutiger Name
182 			// im Stringpool erzeugt werden (Form ProcName:VarName)
183 			String aName( pDef->aName );
184 			if( pDef->IsStatic() )
185 			{
186 				aName = pParser->aGblStrings.Find( nProcId );
187 				aName += ':';
188 				aName += pDef->aName;
189 			}
190 			pDef->nId = rStrings.Add( aName );
191 		}
192 		// Procs sind immer global
193 		if( !pDef->GetProcDef() )
194 			pDef->nProcId = nProcId;
195 		pDef->pIn = this;
196 		const SbiSymDef* q = pDef;
197 		aData.Insert( q, q->nPos );
198 	}
199 }
200 
201 // Suchen eines Eintrags ueber den Namen. Es wird auch im Parent gesucht.
202 
Find(const String & rName) const203 SbiSymDef* SbiSymPool::Find( const String& rName ) const
204 {
205 	sal_uInt16 nCount = aData.Count();
206 	for( sal_uInt16 i = 0; i < nCount; i++ )
207 	{
208 		SbiSymDef* p = aData.GetObject( nCount - i - 1 );
209 		if( ( !p->nProcId || ( p->nProcId == nProcId ) )
210 		 && ( p->aName.EqualsIgnoreCaseAscii( rName ) ) )
211 			return p;
212 	}
213 	if( pParent )
214 		return pParent->Find( rName );
215 	else
216 		return NULL;
217 }
218 
219 // Suchen ueber ID-Nummer
220 
FindId(sal_uInt16 n) const221 SbiSymDef* SbiSymPool::FindId( sal_uInt16 n ) const
222 {
223 	for( sal_uInt16 i = 0; i < aData.Count(); i++ )
224 	{
225 		SbiSymDef* p = aData.GetObject( i );
226 		if( p->nId == n && ( !p->nProcId || ( p->nProcId == nProcId ) ) )
227 			return p;
228 	}
229 	if( pParent )
230 		return pParent->FindId( n );
231 	else
232 		return NULL;
233 }
234 
235 // Suchen ueber Position (ab 0)
236 
Get(sal_uInt16 n) const237 SbiSymDef* SbiSymPool::Get( sal_uInt16 n ) const
238 {
239 	if( n >= aData.Count() )
240 		return NULL;
241 	else
242 		return aData.GetObject( n );
243 }
244 
Define(const String & rName)245 sal_uInt32 SbiSymPool::Define( const String& rName )
246 {
247 	SbiSymDef* p = Find( rName );
248 	if( p )
249 	{	if( p->IsDefined() )
250 			pParser->Error( SbERR_LABEL_DEFINED, rName );
251 	}
252 	else
253 		p = AddSym( rName );
254 	return p->Define();
255 }
256 
Reference(const String & rName)257 sal_uInt32 SbiSymPool::Reference( const String& rName )
258 {
259 	SbiSymDef* p = Find( rName );
260 	if( !p )
261 		p = AddSym( rName );
262 	//Sicherheitshalber
263 	pParser->aGen.GenStmnt();
264 	return p->Reference();
265 }
266 
267 // Alle offenen Referenzen anmaulen
268 
CheckRefs()269 void SbiSymPool::CheckRefs()
270 {
271 	for( sal_uInt16 i = 0; i < aData.Count(); i++ )
272 	{
273 		SbiSymDef* p = aData.GetObject( i );
274 		if( !p->IsDefined() )
275 			pParser->Error( SbERR_UNDEF_LABEL, p->GetName() );
276 	}
277 }
278 
279 /***************************************************************************
280 |*
281 |*	Symbol-Definitionen
282 |*
283 ***************************************************************************/
284 
SbiSymDef(const String & rName)285 SbiSymDef::SbiSymDef( const String& rName ) : aName( rName )
286 {
287 	eType	 = SbxEMPTY;
288 	nDims	 = 0;
289 	nTypeId  = 0;
290 	nProcId  = 0;
291 	nId 	 = 0;
292 	nPos	 = 0;
293 	nLen	 = 0;
294 	nChain	 = 0;
295 	bAs		 =
296 	bNew	 =
297 	bStatic	 =
298 	bOpt	 =
299 	bParamArray =
300 	bWithEvents =
301 	bWithBrackets =
302 	bByVal	 =
303 	bChained =
304     bGlobal  = sal_False;
305 	pIn		 =
306 	pPool	 = NULL;
307 	nDefaultId = 0;
308 	nFixedStringLength = -1;
309 }
310 
~SbiSymDef()311 SbiSymDef::~SbiSymDef()
312 {
313 	delete pPool;
314 }
315 
GetProcDef()316 SbiProcDef* SbiSymDef::GetProcDef()
317 {
318 	return NULL;
319 }
320 
GetConstDef()321 SbiConstDef* SbiSymDef::GetConstDef()
322 {
323 	return NULL;
324 }
325 
326 // Wenn der Name benoetigt wird, den aktuellen Namen
327 // aus dem Stringpool nehmen
328 
GetName()329 const String& SbiSymDef::GetName()
330 {
331 	if( pIn )
332 		aName = pIn->rStrings.Find( nId );
333 	return aName;
334 }
335 
336 // Eintragen eines Datentyps
337 
SetType(SbxDataType t)338 void SbiSymDef::SetType( SbxDataType t )
339 {
340 	if( t == SbxVARIANT && pIn )
341 	{
342 		sal_Unicode cu = aName.GetBuffer()[0];
343 		if( cu < 256 )
344 		{
345 			char ch = (char)aName.GetBuffer()[0];
346 			if( ch == '_' ) ch = 'Z';
347 			int ch2 = toupper( ch );
348 			unsigned char c = (unsigned char)ch2;
349 			if( c > 0 && c < 128 )
350 				t = pIn->pParser->eDefTypes[ ch2 - 'A' ];
351 		}
352 	}
353 	eType = t;
354 }
355 
356 // Aufbau einer Backchain, falls noch nicht definiert
357 // Es wird der Wert zurueckgeliefert, der als Operand gespeichert
358 // werden soll.
359 
Reference()360 sal_uInt32 SbiSymDef::Reference()
361 {
362 	if( !bChained )
363 	{
364 		sal_uInt32 n = nChain;
365 		nChain = pIn->pParser->aGen.GetOffset();
366 		return n;
367 	}
368 	else return nChain;
369 }
370 
371 // Definition eines Symbols.
372 // Hier wird der Backchain aufgeloest, falls vorhanden
373 
Define()374 sal_uInt32 SbiSymDef::Define()
375 {
376 	sal_uInt32 n = pIn->pParser->aGen.GetPC();
377 	pIn->pParser->aGen.GenStmnt();
378 	if( nChain ) pIn->pParser->aGen.BackChain( nChain );
379 	nChain = n;
380 	bChained = sal_True;
381 	return nChain;
382 }
383 
384 // Eine Symboldefinition kann einen eigenen Pool haben. Dies ist
385 // der Fall bei Objekten und Prozeduren (lokale Variable)
386 
GetPool()387 SbiSymPool& SbiSymDef::GetPool()
388 {
389 	if( !pPool )
390 		pPool = new SbiSymPool( pIn->pParser->aGblStrings, SbLOCAL );	// wird gedumpt
391 	return *pPool;
392 }
393 
GetScope() const394 SbiSymScope SbiSymDef::GetScope() const
395 {
396 	return pIn ? pIn->GetScope() : SbLOCAL;
397 }
398 
399 ////////////////////////////////////////////////////////////////////////////
400 
401 // Die Prozedur-Definition hat drei Pools:
402 // 1) aParams: wird durch die Definition gefuellt. Enthaelt die Namen
403 //	  der Parameter, wie sie innerhalb des Rumpfes verwendet werden.
404 //	  Das erste Element ist der Returnwert.
405 // 2) pPool: saemtliche lokale Variable
406 // 3) aLabels: Labels
407 
SbiProcDef(SbiParser * pParser,const String & rName,sal_Bool bProcDecl)408 SbiProcDef::SbiProcDef( SbiParser* pParser, const String& rName,
409 					    sal_Bool bProcDecl )
410 		 : SbiSymDef( rName )
411 		 , aParams( pParser->aGblStrings, SbPARAM )  // wird gedumpt
412 		 , aLabels( pParser->aLclStrings, SbLOCAL )	 // wird nicht gedumpt
413 		 , mbProcDecl( bProcDecl )
414 {
415 	aParams.SetParent( &pParser->aPublics );
416 	pPool = new SbiSymPool( pParser->aGblStrings, SbLOCAL ); // Locals
417 	pPool->SetParent( &aParams );
418 	nLine1	=
419 	nLine2	= 0;
420 	mePropMode = PROPERTY_MODE_NONE;
421 	bPublic = sal_True;
422 	bCdecl	= sal_False;
423 	bStatic = sal_False;
424 	// Fuer Returnwerte ist das erste Element der Parameterliste
425 	// immer mit dem Namen und dem Typ der Proc definiert
426 	aParams.AddSym( aName );
427 }
428 
~SbiProcDef()429 SbiProcDef::~SbiProcDef()
430 {}
431 
GetProcDef()432 SbiProcDef* SbiProcDef::GetProcDef()
433 {
434 	return this;
435 }
436 
SetType(SbxDataType t)437 void SbiProcDef::SetType( SbxDataType t )
438 {
439 	SbiSymDef::SetType( t );
440 	aParams.Get( 0 )->SetType( eType );
441 }
442 
443 // Match mit einer Forward-Deklaration
444 // Falls der Match OK ist, wird pOld durch this im Pool ersetzt
445 // pOld wird immer geloescht!
446 
Match(SbiProcDef * pOld)447 void SbiProcDef::Match( SbiProcDef* pOld )
448 {
449 	SbiSymDef* po, *pn=NULL;
450 	// Parameter 0 ist der Funktionsname
451 	sal_uInt16 i;
452 	for( i = 1; i < aParams.GetSize(); i++ )
453 	{
454 		po = pOld->aParams.Get( i );
455 		pn = aParams.Get( i );
456 		// Kein Typabgleich; das wird beim Laufen erledigt
457 		// aber ist sie evtl. mit zu wenigen Parametern aufgerufen
458 		// worden?
459 		if( !po && !pn->IsOptional() && !pn->IsParamArray() )
460 			break;
461 		po = pOld->aParams.Next();
462 	}
463 	// Wurden zu viele Parameter angegeben?
464 	if( pn && i < aParams.GetSize() && pOld->pIn )
465 	{
466 		// Die ganze Zeile markieren
467 		pOld->pIn->GetParser()->SetCol1( 0 );
468 		pOld->pIn->GetParser()->Error( SbERR_BAD_DECLARATION, aName );
469 	}
470 	if( !pIn && pOld->pIn )
471 	{
472 		// Alten Eintrag durch neuen ersetzen
473 		SbiSymDef** pData = (SbiSymDef**) pOld->pIn->aData.GetData();
474 		pData[ pOld->nPos ] = this;
475 		nPos = pOld->nPos;
476 		nId  = pOld->nId;
477 		pIn  = pOld->pIn;
478 	}
479 	delete pOld;
480 }
481 
setPropertyMode(PropertyMode ePropMode)482 void SbiProcDef::setPropertyMode( PropertyMode ePropMode )
483 {
484 	mePropMode = ePropMode;
485 	if( mePropMode != PROPERTY_MODE_NONE )
486 	{
487 		// Prop name = original scanned procedure name
488 		maPropName = aName;
489 
490 		// CompleteProcName includes "Property xxx "
491 		// to avoid conflicts with other symbols
492 		String aCompleteProcName;
493 		aCompleteProcName.AppendAscii( "Property " );
494 		switch( mePropMode )
495 		{
496 			case PROPERTY_MODE_GET:		aCompleteProcName.AppendAscii( "Get " ); break;
497 			case PROPERTY_MODE_LET:		aCompleteProcName.AppendAscii( "Let " ); break;
498 			case PROPERTY_MODE_SET:		aCompleteProcName.AppendAscii( "Set " ); break;
499 			case PROPERTY_MODE_NONE:
500 				DBG_ERROR( "Illegal PropertyMode PROPERTY_MODE_NONE" );
501 				break;
502 		}
503 		aCompleteProcName += aName;
504 		aName = aCompleteProcName;
505 	}
506 }
507 
508 
509 //////////////////////////////////////////////////////////////////////////
510 
SbiConstDef(const String & rName)511 SbiConstDef::SbiConstDef( const String& rName )
512 		   : SbiSymDef( rName )
513 {
514 	nVal = 0; eType = SbxINTEGER;
515 }
516 
Set(double n,SbxDataType t)517 void SbiConstDef::Set( double n, SbxDataType t )
518 {
519 	aVal.Erase(); nVal = n; eType = t;
520 }
521 
Set(const String & n)522 void SbiConstDef::Set( const String& n )
523 {
524 	aVal = n; nVal = 0; eType = SbxSTRING;
525 }
526 
~SbiConstDef()527 SbiConstDef::~SbiConstDef()
528 {}
529 
GetConstDef()530 SbiConstDef* SbiConstDef::GetConstDef()
531 {
532 	return this;
533 }
534 
535