1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: codegen.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
34 #include <basic/sbx.hxx>
39 // nInc ist die Inkrementgroesse der Puffer
41 SbiCodeGen::SbiCodeGen( SbModule
& r
, SbiParser
* p
, short nInc
)
42 : rMod( r
), aCode( p
, nInc
)
51 UINT32
SbiCodeGen::GetPC()
53 return aCode
.GetSize();
58 void SbiCodeGen::Statement()
62 nLine
= pParser
->GetLine();
63 nCol
= pParser
->GetCol1();
65 // #29955 Information der for-Schleifen-Ebene
66 // in oberen Byte der Spalte speichern
67 nCol
= (nCol
& 0xff) + 0x100 * nForLevel
;
70 // Anfang eines Statements markieren
72 void SbiCodeGen::GenStmnt()
77 Gen( _STMNT
, nLine
, nCol
);
81 // Die Gen-Routinen returnen den Offset des 1. Operanden,
82 // damit Jumps dort ihr Backchain versenken koennen
84 UINT32
SbiCodeGen::Gen( SbiOpcode eOpcode
)
87 if( eOpcode
< SbOP0_START
|| eOpcode
> SbOP0_END
)
88 pParser
->Error( SbERR_INTERNAL_ERROR
, "OPCODE1" );
91 aCode
+= (UINT8
) eOpcode
;
95 UINT32
SbiCodeGen::Gen( SbiOpcode eOpcode
, UINT32 nOpnd
)
98 if( eOpcode
< SbOP1_START
|| eOpcode
> SbOP1_END
)
99 pParser
->Error( SbERR_INTERNAL_ERROR
, "OPCODE2" );
102 aCode
+= (UINT8
) eOpcode
;
108 UINT32
SbiCodeGen::Gen( SbiOpcode eOpcode
, UINT32 nOpnd1
, UINT32 nOpnd2
)
111 if( eOpcode
< SbOP2_START
|| eOpcode
> SbOP2_END
)
112 pParser
->Error( SbERR_INTERNAL_ERROR
, "OPCODE3" );
115 aCode
+= (UINT8
) eOpcode
;
122 // Abspeichern des erzeugten Images im Modul
124 void SbiCodeGen::Save()
126 SbiImage
* p
= new SbiImage
;
127 rMod
.StartDefinitions();
129 p
->nDimBase
= pParser
->nBase
;
130 // OPTION EXPLICIT-Flag uebernehmen
131 if( pParser
->bExplicit
)
132 p
->SetFlag( SBIMG_EXPLICIT
);
135 if( rMod
.mnType
== com::sun::star::script::ModuleType::Class
)
137 OSL_TRACE("COdeGen::save() classmodule processing");
138 rMod
.bIsProxyModule
= true;
139 p
->SetFlag( SBIMG_CLASSMODULE
);
140 pCLASSFAC
->AddClassModule( &rMod
);
142 nIfaceCount
= pParser
->aIfaceVector
.size();
145 if( !rMod
.pClassData
)
146 rMod
.pClassData
= new SbClassData
;
148 for( int i
= 0 ; i
< nIfaceCount
; i
++ )
150 const String
& rIfaceName
= pParser
->aIfaceVector
[i
];
151 SbxVariable
* pIfaceVar
= new SbxVariable( SbxVARIANT
);
152 pIfaceVar
->SetName( rIfaceName
);
153 SbxArray
* pIfaces
= rMod
.pClassData
->mxIfaces
;
154 pIfaces
->Insert( pIfaceVar
, pIfaces
->Count() );
160 pCLASSFAC
->RemoveClassModule( &rMod
);
161 // Only a ClassModule can revert to Normal
162 if ( rMod
.mnType
== com::sun::star::script::ModuleType::Class
)
163 rMod
.mnType
= com::sun::star::script::ModuleType::Normal
;
164 rMod
.bIsProxyModule
= false;
167 p
->SetFlag( SBIMG_COMPARETEXT
);
169 if( pParser
->HasGlobalCode() )
170 p
->SetFlag( SBIMG_INITCODE
);
172 for( SbiSymDef
* pDef
= pParser
->aPublics
.First(); pDef
;
173 pDef
= pParser
->aPublics
.Next() )
175 SbiProcDef
* pProc
= pDef
->GetProcDef();
176 if( pProc
&& pProc
->IsDefined() )
178 String aProcName
= pProc
->GetName();
179 String aIfaceProcName
;
181 USHORT nPassCount
= 1;
184 int nPropPrefixFound
=
185 aProcName
.Search( String( RTL_CONSTASCII_USTRINGPARAM("Property ") ) );
186 String aPureProcName
= aProcName
;
188 if( nPropPrefixFound
== 0 )
190 aPropPrefix
= aProcName
.Copy( 0, 13 ); // 13 == Len( "Property ?et " )
191 aPureProcName
= aProcName
.Copy( 13 );
193 for( int i
= 0 ; i
< nIfaceCount
; i
++ )
195 const String
& rIfaceName
= pParser
->aIfaceVector
[i
];
196 int nFound
= aPureProcName
.Search( rIfaceName
);
197 if( nFound
== 0 && '_' == aPureProcName
.GetChar( rIfaceName
.Len() ) )
199 if( nPropPrefixFound
== 0 )
200 aIfaceProcName
+= aPropPrefix
;
201 aIfaceProcName
+= aPureProcName
.Copy( rIfaceName
.Len() + 1 );
202 aIfaceName
= rIfaceName
;
208 SbMethod
* pMeth
= NULL
;
209 for( USHORT nPass
= 0 ; nPass
< nPassCount
; nPass
++ )
212 aProcName
= aIfaceProcName
;
214 PropertyMode ePropMode
= pProc
->getPropertyMode();
215 if( ePropMode
!= PROPERTY_MODE_NONE
)
217 SbxDataType ePropType
= SbxEMPTY
;
220 case PROPERTY_MODE_GET
:
221 ePropType
= pProc
->GetType();
223 case PROPERTY_MODE_LET
:
225 // type == type of first parameter
226 ePropType
= SbxVARIANT
; // Default
227 SbiSymPool
* pPool
= &pProc
->GetParams();
228 if( pPool
->GetSize() > 1 )
230 SbiSymDef
* pPar
= pPool
->Get( 1 );
232 ePropType
= pPar
->GetType();
236 case PROPERTY_MODE_SET
:
237 ePropType
= SbxOBJECT
;
239 case PROPERTY_MODE_NONE
:
240 DBG_ERROR( "Illegal PropertyMode PROPERTY_MODE_NONE" );
243 String aPropName
= pProc
->GetPropName();
245 aPropName
= aPropName
.Copy( aIfaceName
.Len() + 1 );
246 SbProcedureProperty
* pProcedureProperty
= NULL
;
247 OSL_TRACE("*** getProcedureProperty for thing %s",
248 rtl::OUStringToOString( aPropName
,RTL_TEXTENCODING_UTF8
).getStr() );
249 pProcedureProperty
= rMod
.GetProcedureProperty( aPropName
, ePropType
);
253 SbIfaceMapperMethod
* pMapperMeth
= NULL
;
254 pMapperMeth
= rMod
.GetIfaceMapperMethod( aProcName
, pMeth
);
258 pMeth
= rMod
.GetMethod( aProcName
, pProc
->GetType() );
261 if( !pProc
->IsPublic() )
262 pMeth
->SetFlag( SBX_PRIVATE
);
264 pMeth
->nStart
= pProc
->GetAddr();
265 pMeth
->nLine1
= pProc
->GetLine1();
266 pMeth
->nLine2
= pProc
->GetLine2();
268 SbxInfo
* pInfo
= pMeth
->GetInfo();
269 String aHelpFile
, aComment
;
273 // Die Zusatzdaten retten
274 aHelpFile
= pInfo
->GetHelpFile();
275 aComment
= pInfo
->GetComment();
276 nHelpId
= pInfo
->GetHelpId();
278 // Und die Parameterliste neu aufbauen
279 pInfo
= new SbxInfo( aHelpFile
, nHelpId
);
280 pInfo
->SetComment( aComment
);
281 SbiSymPool
* pPool
= &pProc
->GetParams();
282 // Das erste Element ist immer der Funktionswert!
283 for( USHORT i
= 1; i
< pPool
->GetSize(); i
++ )
285 SbiSymDef
* pPar
= pPool
->Get( i
);
286 SbxDataType t
= pPar
->GetType();
287 if( !pPar
->IsByVal() )
288 t
= (SbxDataType
) ( t
| SbxBYREF
);
289 if( pPar
->GetDims() )
290 t
= (SbxDataType
) ( t
| SbxARRAY
);
291 // #33677 Optional-Info durchreichen
292 USHORT nFlags
= SBX_READ
;
293 if( pPar
->IsOptional() )
294 nFlags
|= SBX_OPTIONAL
;
296 pInfo
->AddParam( pPar
->GetName(), t
, nFlags
);
298 UINT32 nUserData
= 0;
299 USHORT nDefaultId
= pPar
->GetDefaultId();
301 nUserData
|= nDefaultId
;
302 if( pPar
->IsParamArray() )
303 nUserData
|= PARAM_INFO_PARAMARRAY
;
306 SbxParamInfo
* pParam
= (SbxParamInfo
*)pInfo
->GetParam( i
);
307 pParam
->nUserData
= nUserData
;
310 pMeth
->SetInfo( pInfo
);
317 p
->AddCode( aCode
.GetBuffer(), aCode
.GetSize() );
319 // Der globale StringPool. 0 ist nicht belegt.
320 SbiStringPool
* pPool
= &pParser
->aGblStrings
;
321 USHORT nSize
= pPool
->GetSize();
322 p
->MakeStrings( nSize
);
324 for( i
= 1; i
<= nSize
; i
++ )
325 p
->AddString( pPool
->Find( i
) );
328 USHORT nCount
= pParser
->rTypeArray
->Count();
329 for (i
= 0; i
< nCount
; i
++)
330 p
->AddType((SbxObject
*)pParser
->rTypeArray
->Get(i
));
332 // Insert enum objects
333 nCount
= pParser
->rEnumArray
->Count();
334 for (i
= 0; i
< nCount
; i
++)
335 p
->AddEnum((SbxObject
*)pParser
->rEnumArray
->Get(i
));
342 rMod
.EndDefinitions();
349 virtual ~PCodeVisitor();
351 virtual void start( BYTE
* 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;
359 template <class T
> PCodeVisitor
< T
>::~PCodeVisitor()
363 class PCodeBufferWalker
368 T
readParam( BYTE
*& pCode
)
370 short nBytes
= sizeof( T
);
372 for ( int i
=0; i
<nBytes
; ++i
)
373 nOp1
|= *pCode
++ << ( i
* 8);
377 PCodeBufferWalker( BYTE
* pCode
, T nBytes
): m_nBytes( nBytes
), m_pCode( pCode
)
380 void visitBuffer( PCodeVisitor
< T
>& visitor
)
382 BYTE
* pCode
= m_pCode
;
385 BYTE
* pEnd
= pCode
+ m_nBytes
;
386 visitor
.start( m_pCode
);
387 T nOp1
= 0, nOp2
= 0;
388 for( ; pCode
< pEnd
; )
390 SbiOpcode eOp
= (SbiOpcode
)(*pCode
++);
392 if ( eOp
<= SbOP0_END
)
393 visitor
.processOpCode0( eOp
);
394 else if( eOp
>= SbOP1_START
&& eOp
<= SbOP1_END
)
396 if ( visitor
.processParams() )
397 nOp1
= readParam( pCode
);
399 pCode
+= sizeof( T
);
400 visitor
.processOpCode1( eOp
, nOp1
);
402 else if( eOp
>= SbOP2_START
&& eOp
<= SbOP2_END
)
404 if ( visitor
.processParams() )
406 nOp1
= readParam( pCode
);
407 nOp2
= readParam( pCode
);
410 pCode
+= ( sizeof( T
) * 2 );
411 visitor
.processOpCode2( eOp
, nOp1
, nOp2
);
418 template < class T
, class S
>
419 class OffSetAccumulator
: public PCodeVisitor
< T
>
422 T m_nNumSingleParams
;
423 T m_nNumDoubleParams
;
426 OffSetAccumulator() : m_nNumOp0(0), m_nNumSingleParams(0), m_nNumDoubleParams(0){}
427 virtual void start( BYTE
* /*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
; }
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
);
440 return static_cast<S
>(result
);
442 virtual bool processParams(){ return false; }
447 template < class T
, class S
>
449 class BufferTransformer
: public PCodeVisitor
< T
>
452 SbiBuffer m_ConvertedBuf
;
454 BufferTransformer():m_pStart(NULL
), m_ConvertedBuf( NULL
, 1024 ) {}
455 virtual void start( BYTE
* pStart
){ m_pStart
= pStart
; }
456 virtual void processOpCode0( SbiOpcode eOp
)
458 m_ConvertedBuf
+= (UINT8
)eOp
;
460 virtual void processOpCode1( SbiOpcode eOp
, T nOp1
)
462 m_ConvertedBuf
+= (UINT8
)eOp
;
473 nOp1
= static_cast<T
>( convertBufferOffSet(m_pStart
, nOp1
) );
477 nOp1
= static_cast<T
>( convertBufferOffSet(m_pStart
, nOp1
) );
483 m_ConvertedBuf
+= (S
)nOp1
;
485 virtual void processOpCode2( SbiOpcode eOp
, T nOp1
, T nOp2
)
487 m_ConvertedBuf
+= (UINT8
)eOp
;
488 if ( eOp
== _CASEIS
)
490 nOp1
= static_cast<T
>( convertBufferOffSet(m_pStart
, nOp1
) );
491 m_ConvertedBuf
+= (S
)nOp1
;
492 m_ConvertedBuf
+= (S
)nOp2
;
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
502 return m_ConvertedBuf
;
504 static S
convertBufferOffSet( BYTE
* pStart
, T nOp1
)
506 PCodeBufferWalker
< T
> aBuff( pStart
, nOp1
);
507 OffSetAccumulator
< T
, S
> aVisitor
;
508 aBuff
.visitBuffer( aVisitor
);
509 return aVisitor
.offset();
514 SbiCodeGen::calcNewOffSet( BYTE
* pCode
, UINT16 nOffset
)
516 return BufferTransformer
< UINT16
, UINT32
>::convertBufferOffSet( pCode
, nOffset
);
520 SbiCodeGen::calcLegacyOffSet( BYTE
* pCode
, UINT32 nOffset
)
522 return BufferTransformer
< UINT32
, UINT16
>::convertBufferOffSet( pCode
, nOffset
);
525 template <class T
, class S
>
527 PCodeBuffConvertor
<T
,S
>::convert()
529 PCodeBufferWalker
< T
> aBuf( m_pStart
, m_nSize
);
530 BufferTransformer
< T
, S
> aTrnsfrmer
;
531 aBuf
.visitBuffer( aTrnsfrmer
);
532 m_pCnvtdBuf
= (BYTE
*)aTrnsfrmer
.buffer().GetBuffer();
533 m_nCnvtdSize
= static_cast<S
>( aTrnsfrmer
.buffer().GetSize() );
536 template class PCodeBuffConvertor
< UINT16
, UINT32
>;
537 template class PCodeBuffConvertor
< UINT32
, UINT16
>;