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
SbiCodeGen(SbModule & r,SbiParser * p,short nInc)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
GetPC()45 sal_uInt32 SbiCodeGen::GetPC()
46 {
47 return aCode.GetSize();
48 }
49
50 // Statement merken
51
Statement()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
GenStmnt()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
Gen(SbiOpcode eOpcode)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
Gen(SbiOpcode eOpcode,sal_uInt32 nOpnd)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
Gen(SbiOpcode eOpcode,sal_uInt32 nOpnd1,sal_uInt32 nOpnd2)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
Save()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
~PCodeVisitor()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;
readParam(sal_uInt8 * & 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:
PCodeBufferWalker(sal_uInt8 * pCode,T nBytes)377 PCodeBufferWalker( sal_uInt8* pCode, T nBytes ): m_nBytes( nBytes ), m_pCode( pCode )
378 {
379 }
visitBuffer(PCodeVisitor<T> & visitor)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
OffSetAccumulator()426 OffSetAccumulator() : m_nNumOp0(0), m_nNumSingleParams(0), m_nNumDoubleParams(0){}
start(sal_uInt8 *)427 virtual void start( sal_uInt8* /*pStart*/ ){}
processOpCode0(SbiOpcode)428 virtual void processOpCode0( SbiOpcode /*eOp*/ ){ ++m_nNumOp0; }
processOpCode1(SbiOpcode,T)429 virtual void processOpCode1( SbiOpcode /*eOp*/, T /*nOp1*/ ){ ++m_nNumSingleParams; }
processOpCode2(SbiOpcode,T,T)430 virtual void processOpCode2( SbiOpcode /*eOp*/, T /*nOp1*/, T /*nOp2*/ ) { ++m_nNumDoubleParams; }
end()431 virtual void end(){}
offset()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 }
processParams()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:
BufferTransformer()454 BufferTransformer():m_pStart(NULL), m_ConvertedBuf( NULL, 1024 ) {}
start(sal_uInt8 * pStart)455 virtual void start( sal_uInt8* pStart ){ m_pStart = pStart; }
processOpCode0(SbiOpcode eOp)456 virtual void processOpCode0( SbiOpcode eOp )
457 {
458 m_ConvertedBuf += (sal_uInt8)eOp;
459 }
processOpCode1(SbiOpcode eOp,T nOp1)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 }
processOpCode2(SbiOpcode eOp,T nOp1,T nOp2)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 }
processParams()495 virtual bool processParams(){ return true; }
end()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
buffer()500 SbiBuffer& buffer()
501 {
502 return m_ConvertedBuf;
503 }
convertBufferOffSet(sal_uInt8 * pStart,T nOp1)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
calcNewOffSet(sal_uInt8 * pCode,sal_uInt16 nOffset)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
calcLegacyOffSet(sal_uInt8 * pCode,sal_uInt32 nOffset)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
convert()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