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