xref: /AOO41X/main/basic/source/comp/symtbl.cxx (revision e1f63238eb022c8a12b30d46a012444ff20e0951)
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