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 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 52 SbiStringPool::~SbiStringPool() 53 {} 54 55 // Suchen 56 57 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 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 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 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 112 SbiSymPool::~SbiSymPool() 113 {} 114 115 // Inhalt loeschen 116 117 void SbiSymPool::Clear() 118 { 119 aData.DeleteAndDestroy( 0, aData.Count() ); 120 } 121 122 SbiSymDef* SbiSymPool::First() 123 { 124 nCur = (sal_uInt16) -1; 125 return Next(); 126 } 127 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 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 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 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 203 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 221 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 237 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 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 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 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 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 311 SbiSymDef::~SbiSymDef() 312 { 313 delete pPool; 314 } 315 316 SbiProcDef* SbiSymDef::GetProcDef() 317 { 318 return NULL; 319 } 320 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 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 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 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 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 387 SbiSymPool& SbiSymDef::GetPool() 388 { 389 if( !pPool ) 390 pPool = new SbiSymPool( pIn->pParser->aGblStrings, SbLOCAL ); // wird gedumpt 391 return *pPool; 392 } 393 394 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 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 429 SbiProcDef::~SbiProcDef() 430 {} 431 432 SbiProcDef* SbiProcDef::GetProcDef() 433 { 434 return this; 435 } 436 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 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 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 511 SbiConstDef::SbiConstDef( const String& rName ) 512 : SbiSymDef( rName ) 513 { 514 nVal = 0; eType = SbxINTEGER; 515 } 516 517 void SbiConstDef::Set( double n, SbxDataType t ) 518 { 519 aVal.Erase(); nVal = n; eType = t; 520 } 521 522 void SbiConstDef::Set( const String& n ) 523 { 524 aVal = n; nVal = 0; eType = SbxSTRING; 525 } 526 527 SbiConstDef::~SbiConstDef() 528 {} 529 530 SbiConstDef* SbiConstDef::GetConstDef() 531 { 532 return this; 533 } 534 535