1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_basic.hxx" 30 31 #include <basic/sbx.hxx> 32 #include "sbcomp.hxx" 33 #include "image.hxx" 34 #include <limits> 35 #include <com/sun/star/script/ModuleType.hpp> 36 37 // nInc ist die Inkrementgroesse der Puffer 38 39 SbiCodeGen::SbiCodeGen( SbModule& r, SbiParser* p, short nInc ) 40 : rMod( r ), aCode( p, nInc ) 41 { 42 pParser = p; 43 bStmnt = sal_False; 44 nLine = 0; 45 nCol = 0; 46 nForLevel = 0; 47 } 48 49 sal_uInt32 SbiCodeGen::GetPC() 50 { 51 return aCode.GetSize(); 52 } 53 54 // Statement merken 55 56 void SbiCodeGen::Statement() 57 { 58 bStmnt = sal_True; 59 60 nLine = pParser->GetLine(); 61 nCol = pParser->GetCol1(); 62 63 // #29955 Information der for-Schleifen-Ebene 64 // in oberen Byte der Spalte speichern 65 nCol = (nCol & 0xff) + 0x100 * nForLevel; 66 } 67 68 // Anfang eines Statements markieren 69 70 void SbiCodeGen::GenStmnt() 71 { 72 if( bStmnt ) 73 { 74 bStmnt = sal_False; 75 Gen( _STMNT, nLine, nCol ); 76 } 77 } 78 79 // Die Gen-Routinen returnen den Offset des 1. Operanden, 80 // damit Jumps dort ihr Backchain versenken koennen 81 82 sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode ) 83 { 84 #ifdef DBG_UTIL 85 if( eOpcode < SbOP0_START || eOpcode > SbOP0_END ) 86 pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE1" ); 87 #endif 88 GenStmnt(); 89 aCode += (sal_uInt8) eOpcode; 90 return GetPC(); 91 } 92 93 sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode, sal_uInt32 nOpnd ) 94 { 95 #ifdef DBG_UTIL 96 if( eOpcode < SbOP1_START || eOpcode > SbOP1_END ) 97 pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE2" ); 98 #endif 99 GenStmnt(); 100 aCode += (sal_uInt8) eOpcode; 101 sal_uInt32 n = GetPC(); 102 aCode += nOpnd; 103 return n; 104 } 105 106 sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode, sal_uInt32 nOpnd1, sal_uInt32 nOpnd2 ) 107 { 108 #ifdef DBG_UTIL 109 if( eOpcode < SbOP2_START || eOpcode > SbOP2_END ) 110 pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE3" ); 111 #endif 112 GenStmnt(); 113 aCode += (sal_uInt8) eOpcode; 114 sal_uInt32 n = GetPC(); 115 aCode += nOpnd1; 116 aCode += nOpnd2; 117 return n; 118 } 119 120 // Abspeichern des erzeugten Images im Modul 121 122 void SbiCodeGen::Save() 123 { 124 SbiImage* p = new SbiImage; 125 rMod.StartDefinitions(); 126 // OPTION BASE-Wert: 127 p->nDimBase = pParser->nBase; 128 // OPTION EXPLICIT-Flag uebernehmen 129 if( pParser->bExplicit ) 130 p->SetFlag( SBIMG_EXPLICIT ); 131 132 int nIfaceCount = 0; 133 if( rMod.mnType == com::sun::star::script::ModuleType::CLASS ) 134 { 135 OSL_TRACE("COdeGen::save() classmodule processing"); 136 rMod.bIsProxyModule = true; 137 p->SetFlag( SBIMG_CLASSMODULE ); 138 pCLASSFAC->AddClassModule( &rMod ); 139 140 nIfaceCount = pParser->aIfaceVector.size(); 141 if( !rMod.pClassData ) 142 rMod.pClassData = new SbClassData; 143 if( nIfaceCount ) 144 { 145 for( int i = 0 ; i < nIfaceCount ; i++ ) 146 { 147 const String& rIfaceName = pParser->aIfaceVector[i]; 148 SbxVariable* pIfaceVar = new SbxVariable( SbxVARIANT ); 149 pIfaceVar->SetName( rIfaceName ); 150 SbxArray* pIfaces = rMod.pClassData->mxIfaces; 151 pIfaces->Insert( pIfaceVar, pIfaces->Count() ); 152 } 153 } 154 155 rMod.pClassData->maRequiredTypes = pParser->aRequiredTypes; 156 } 157 else 158 { 159 pCLASSFAC->RemoveClassModule( &rMod ); 160 // Only a ClassModule can revert to Normal 161 if ( rMod.mnType == com::sun::star::script::ModuleType::CLASS ) 162 rMod.mnType = com::sun::star::script::ModuleType::NORMAL; 163 rMod.bIsProxyModule = false; 164 } 165 166 if( pParser->bText ) 167 p->SetFlag( SBIMG_COMPARETEXT ); 168 // GlobalCode-Flag 169 if( pParser->HasGlobalCode() ) 170 p->SetFlag( SBIMG_INITCODE ); 171 // Die Entrypoints: 172 for( SbiSymDef* pDef = pParser->aPublics.First(); pDef; 173 pDef = pParser->aPublics.Next() ) 174 { 175 SbiProcDef* pProc = pDef->GetProcDef(); 176 if( pProc && pProc->IsDefined() ) 177 { 178 String aProcName = pProc->GetName(); 179 String aIfaceProcName; 180 String aIfaceName; 181 sal_uInt16 nPassCount = 1; 182 if( nIfaceCount ) 183 { 184 int nPropPrefixFound = 185 aProcName.Search( String( RTL_CONSTASCII_USTRINGPARAM("Property ") ) ); 186 String aPureProcName = aProcName; 187 String aPropPrefix; 188 if( nPropPrefixFound == 0 ) 189 { 190 aPropPrefix = aProcName.Copy( 0, 13 ); // 13 == Len( "Property ?et " ) 191 aPureProcName = aProcName.Copy( 13 ); 192 } 193 for( int i = 0 ; i < nIfaceCount ; i++ ) 194 { 195 const String& rIfaceName = pParser->aIfaceVector[i]; 196 int nFound = aPureProcName.Search( rIfaceName ); 197 if( nFound == 0 && '_' == aPureProcName.GetChar( rIfaceName.Len() ) ) 198 { 199 if( nPropPrefixFound == 0 ) 200 aIfaceProcName += aPropPrefix; 201 aIfaceProcName += aPureProcName.Copy( rIfaceName.Len() + 1 ); 202 aIfaceName = rIfaceName; 203 nPassCount = 2; 204 break; 205 } 206 } 207 } 208 SbMethod* pMeth = NULL; 209 for( sal_uInt16 nPass = 0 ; nPass < nPassCount ; nPass++ ) 210 { 211 if( nPass == 1 ) 212 aProcName = aIfaceProcName; 213 214 PropertyMode ePropMode = pProc->getPropertyMode(); 215 if( ePropMode != PROPERTY_MODE_NONE ) 216 { 217 SbxDataType ePropType = SbxEMPTY; 218 switch( ePropMode ) 219 { 220 case PROPERTY_MODE_GET: 221 ePropType = pProc->GetType(); 222 break; 223 case PROPERTY_MODE_LET: 224 { 225 // type == type of first parameter 226 ePropType = SbxVARIANT; // Default 227 SbiSymPool* pPool = &pProc->GetParams(); 228 if( pPool->GetSize() > 1 ) 229 { 230 SbiSymDef* pPar = pPool->Get( 1 ); 231 if( pPar ) 232 ePropType = pPar->GetType(); 233 } 234 break; 235 } 236 case PROPERTY_MODE_SET: 237 ePropType = SbxOBJECT; 238 break; 239 case PROPERTY_MODE_NONE: 240 DBG_ERROR( "Illegal PropertyMode PROPERTY_MODE_NONE" ); 241 break; 242 } 243 String aPropName = pProc->GetPropName(); 244 if( nPass == 1 ) 245 aPropName = aPropName.Copy( aIfaceName.Len() + 1 ); 246 SbProcedureProperty* pProcedureProperty = NULL; 247 pProcedureProperty = rMod.GetProcedureProperty( aPropName, ePropType ); 248 } 249 if( nPass == 1 ) 250 { 251 SbIfaceMapperMethod* pMapperMeth = NULL; 252 pMapperMeth = rMod.GetIfaceMapperMethod( aProcName, pMeth ); 253 } 254 else 255 { 256 pMeth = rMod.GetMethod( aProcName, pProc->GetType() ); 257 258 // #110004 259 if( !pProc->IsPublic() ) 260 pMeth->SetFlag( SBX_PRIVATE ); 261 262 // Declare? -> Hidden 263 if( pProc->GetLib().Len() > 0 ) 264 pMeth->SetFlag( SBX_HIDDEN ); 265 266 pMeth->nStart = pProc->GetAddr(); 267 pMeth->nLine1 = pProc->GetLine1(); 268 pMeth->nLine2 = pProc->GetLine2(); 269 // Die Parameter: 270 SbxInfo* pInfo = pMeth->GetInfo(); 271 String aHelpFile, aComment; 272 sal_uIntPtr nHelpId = 0; 273 if( pInfo ) 274 { 275 // Die Zusatzdaten retten 276 aHelpFile = pInfo->GetHelpFile(); 277 aComment = pInfo->GetComment(); 278 nHelpId = pInfo->GetHelpId(); 279 } 280 // Und die Parameterliste neu aufbauen 281 pInfo = new SbxInfo( aHelpFile, nHelpId ); 282 pInfo->SetComment( aComment ); 283 SbiSymPool* pPool = &pProc->GetParams(); 284 // Das erste Element ist immer der Funktionswert! 285 for( sal_uInt16 i = 1; i < pPool->GetSize(); i++ ) 286 { 287 SbiSymDef* pPar = pPool->Get( i ); 288 SbxDataType t = pPar->GetType(); 289 if( !pPar->IsByVal() ) 290 t = (SbxDataType) ( t | SbxBYREF ); 291 if( pPar->GetDims() ) 292 t = (SbxDataType) ( t | SbxARRAY ); 293 // #33677 Optional-Info durchreichen 294 sal_uInt16 nFlags = SBX_READ; 295 if( pPar->IsOptional() ) 296 nFlags |= SBX_OPTIONAL; 297 298 pInfo->AddParam( pPar->GetName(), t, nFlags ); 299 300 sal_uInt32 nUserData = 0; 301 sal_uInt16 nDefaultId = pPar->GetDefaultId(); 302 if( nDefaultId ) 303 nUserData |= nDefaultId; 304 if( pPar->IsParamArray() ) 305 nUserData |= PARAM_INFO_PARAMARRAY; 306 if( pPar->IsWithBrackets() ) 307 nUserData |= PARAM_INFO_WITHBRACKETS; 308 if( nUserData ) 309 { 310 SbxParamInfo* pParam = (SbxParamInfo*)pInfo->GetParam( i ); 311 pParam->nUserData = nUserData; 312 } 313 } 314 pMeth->SetInfo( pInfo ); 315 } 316 317 } // for( iPass... 318 } 319 } 320 // Der Code 321 p->AddCode( aCode.GetBuffer(), aCode.GetSize() ); 322 323 // Der globale StringPool. 0 ist nicht belegt. 324 SbiStringPool* pPool = &pParser->aGblStrings; 325 sal_uInt16 nSize = pPool->GetSize(); 326 p->MakeStrings( nSize ); 327 sal_uInt16 i; 328 for( i = 1; i <= nSize; i++ ) 329 p->AddString( pPool->Find( i ) ); 330 331 // Typen einfuegen 332 sal_uInt16 nCount = pParser->rTypeArray->Count(); 333 for (i = 0; i < nCount; i++) 334 p->AddType((SbxObject *)pParser->rTypeArray->Get(i)); 335 336 // Insert enum objects 337 nCount = pParser->rEnumArray->Count(); 338 for (i = 0; i < nCount; i++) 339 p->AddEnum((SbxObject *)pParser->rEnumArray->Get(i)); 340 341 if( !p->IsError() ) 342 rMod.pImage = p; 343 else 344 delete p; 345 346 rMod.EndDefinitions(); 347 } 348 349 template < class T > 350 class PCodeVisitor 351 { 352 public: 353 virtual ~PCodeVisitor(); 354 355 virtual void start( sal_uInt8* pStart ) = 0; 356 virtual void processOpCode0( SbiOpcode eOp ) = 0; 357 virtual void processOpCode1( SbiOpcode eOp, T nOp1 ) = 0; 358 virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 ) = 0; 359 virtual bool processParams() = 0; 360 virtual void end() = 0; 361 }; 362 363 template <class T> PCodeVisitor< T >::~PCodeVisitor() 364 {} 365 366 template <class T> 367 class PCodeBufferWalker 368 { 369 private: 370 T m_nBytes; 371 sal_uInt8* m_pCode; 372 T readParam( sal_uInt8*& pCode ) 373 { 374 short nBytes = sizeof( T ); 375 T nOp1=0; 376 for ( int i=0; i<nBytes; ++i ) 377 nOp1 |= *pCode++ << ( i * 8); 378 return nOp1; 379 } 380 public: 381 PCodeBufferWalker( sal_uInt8* pCode, T nBytes ): m_nBytes( nBytes ), m_pCode( pCode ) 382 { 383 } 384 void visitBuffer( PCodeVisitor< T >& visitor ) 385 { 386 sal_uInt8* pCode = m_pCode; 387 if ( !pCode ) 388 return; 389 sal_uInt8* pEnd = pCode + m_nBytes; 390 visitor.start( m_pCode ); 391 T nOp1 = 0, nOp2 = 0; 392 for( ; pCode < pEnd; ) 393 { 394 SbiOpcode eOp = (SbiOpcode)(*pCode++); 395 396 if ( eOp <= SbOP0_END ) 397 visitor.processOpCode0( eOp ); 398 else if( eOp >= SbOP1_START && eOp <= SbOP1_END ) 399 { 400 if ( visitor.processParams() ) 401 nOp1 = readParam( pCode ); 402 else 403 pCode += sizeof( T ); 404 visitor.processOpCode1( eOp, nOp1 ); 405 } 406 else if( eOp >= SbOP2_START && eOp <= SbOP2_END ) 407 { 408 if ( visitor.processParams() ) 409 { 410 nOp1 = readParam( pCode ); 411 nOp2 = readParam( pCode ); 412 } 413 else 414 pCode += ( sizeof( T ) * 2 ); 415 visitor.processOpCode2( eOp, nOp1, nOp2 ); 416 } 417 } 418 visitor.end(); 419 } 420 }; 421 422 template < class T, class S > 423 class OffSetAccumulator : public PCodeVisitor< T > 424 { 425 T m_nNumOp0; 426 T m_nNumSingleParams; 427 T m_nNumDoubleParams; 428 public: 429 430 OffSetAccumulator() : m_nNumOp0(0), m_nNumSingleParams(0), m_nNumDoubleParams(0){} 431 virtual void start( sal_uInt8* /*pStart*/ ){} 432 virtual void processOpCode0( SbiOpcode /*eOp*/ ){ ++m_nNumOp0; } 433 virtual void processOpCode1( SbiOpcode /*eOp*/, T /*nOp1*/ ){ ++m_nNumSingleParams; } 434 virtual void processOpCode2( SbiOpcode /*eOp*/, T /*nOp1*/, T /*nOp2*/ ) { ++m_nNumDoubleParams; } 435 virtual void end(){} 436 S offset() 437 { 438 T result = 0 ; 439 static const S max = std::numeric_limits< S >::max(); 440 result = m_nNumOp0 + ( ( sizeof(S) + 1 ) * m_nNumSingleParams ) + ( (( sizeof(S) * 2 )+ 1 ) * m_nNumDoubleParams ); 441 if ( result > max ) 442 return max; 443 444 return static_cast<S>(result); 445 } 446 virtual bool processParams(){ return false; } 447 }; 448 449 450 451 template < class T, class S > 452 453 class BufferTransformer : public PCodeVisitor< T > 454 { 455 sal_uInt8* m_pStart; 456 SbiBuffer m_ConvertedBuf; 457 public: 458 BufferTransformer():m_pStart(NULL), m_ConvertedBuf( NULL, 1024 ) {} 459 virtual void start( sal_uInt8* pStart ){ m_pStart = pStart; } 460 virtual void processOpCode0( SbiOpcode eOp ) 461 { 462 m_ConvertedBuf += (sal_uInt8)eOp; 463 } 464 virtual void processOpCode1( SbiOpcode eOp, T nOp1 ) 465 { 466 m_ConvertedBuf += (sal_uInt8)eOp; 467 switch( eOp ) 468 { 469 case _JUMP: 470 case _JUMPT: 471 case _JUMPF: 472 case _GOSUB: 473 case _CASEIS: 474 case _RETURN: 475 case _ERRHDL: 476 case _TESTFOR: 477 nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) ); 478 break; 479 case _RESUME: 480 if ( nOp1 > 1 ) 481 nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) ); 482 break; 483 default: 484 break; // 485 486 } 487 m_ConvertedBuf += (S)nOp1; 488 } 489 virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 ) 490 { 491 m_ConvertedBuf += (sal_uInt8)eOp; 492 if ( eOp == _CASEIS ) 493 if ( nOp1 ) 494 nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) ); 495 m_ConvertedBuf += (S)nOp1; 496 m_ConvertedBuf += (S)nOp2; 497 498 } 499 virtual bool processParams(){ return true; } 500 virtual void end() {} 501 // yeuch, careful here, you can only call 502 // GetBuffer on the returned SbiBuffer once, also 503 // you (as the caller) get to own the memory 504 SbiBuffer& buffer() 505 { 506 return m_ConvertedBuf; 507 } 508 static S convertBufferOffSet( sal_uInt8* pStart, T nOp1 ) 509 { 510 PCodeBufferWalker< T > aBuff( pStart, nOp1); 511 OffSetAccumulator< T, S > aVisitor; 512 aBuff.visitBuffer( aVisitor ); 513 return aVisitor.offset(); 514 } 515 }; 516 517 sal_uInt32 518 SbiCodeGen::calcNewOffSet( sal_uInt8* pCode, sal_uInt16 nOffset ) 519 { 520 return BufferTransformer< sal_uInt16, sal_uInt32 >::convertBufferOffSet( pCode, nOffset ); 521 } 522 523 sal_uInt16 524 SbiCodeGen::calcLegacyOffSet( sal_uInt8* pCode, sal_uInt32 nOffset ) 525 { 526 return BufferTransformer< sal_uInt32, sal_uInt16 >::convertBufferOffSet( pCode, nOffset ); 527 } 528 529 template <class T, class S> 530 void 531 PCodeBuffConvertor<T,S>::convert() 532 { 533 PCodeBufferWalker< T > aBuf( m_pStart, m_nSize ); 534 BufferTransformer< T, S > aTrnsfrmer; 535 aBuf.visitBuffer( aTrnsfrmer ); 536 m_pCnvtdBuf = (sal_uInt8*)aTrnsfrmer.buffer().GetBuffer(); 537 m_nCnvtdSize = static_cast<S>( aTrnsfrmer.buffer().GetSize() ); 538 } 539 540 template class PCodeBuffConvertor< sal_uInt16, sal_uInt32 >; 541 template class PCodeBuffConvertor< sal_uInt32, sal_uInt16 >; 542