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