1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <basic/sbx.hxx>
26 #include <com/sun/star/script/ModuleType.hpp>
28 // nInc is the increment size of the buffers
30 SbiCodeGen::SbiCodeGen( SbModule
& r
, SbiParser
* p
, short nInc
)
31 : rMod( r
), aCode( p
, nInc
)
40 sal_uInt32
SbiCodeGen::GetPC()
42 return aCode
.GetSize();
45 // memorize the statement
47 void SbiCodeGen::Statement()
51 nLine
= pParser
->GetLine();
52 nCol
= pParser
->GetCol1();
54 // #29955 Store the information of the for-loop-layer
55 // in the uppper Byte of the column
56 nCol
= (nCol
& 0xff) + 0x100 * nForLevel
;
59 // Mark the beginning of a statement
61 void SbiCodeGen::GenStmnt()
66 Gen( _STMNT
, nLine
, nCol
);
70 // The Gen-Routines return the offset of the 1. operand,
71 // so that jumps can sink their backchain there.
73 sal_uInt32
SbiCodeGen::Gen( SbiOpcode eOpcode
)
76 if( eOpcode
< SbOP0_START
|| eOpcode
> SbOP0_END
)
77 pParser
->Error( SbERR_INTERNAL_ERROR
, "OPCODE1" );
80 aCode
+= (sal_uInt8
) eOpcode
;
84 sal_uInt32
SbiCodeGen::Gen( SbiOpcode eOpcode
, sal_uInt32 nOpnd
)
87 if( eOpcode
< SbOP1_START
|| eOpcode
> SbOP1_END
)
88 pParser
->Error( SbERR_INTERNAL_ERROR
, "OPCODE2" );
91 aCode
+= (sal_uInt8
) eOpcode
;
92 sal_uInt32 n
= GetPC();
97 sal_uInt32
SbiCodeGen::Gen( SbiOpcode eOpcode
, sal_uInt32 nOpnd1
, sal_uInt32 nOpnd2
)
100 if( eOpcode
< SbOP2_START
|| eOpcode
> SbOP2_END
)
101 pParser
->Error( SbERR_INTERNAL_ERROR
, "OPCODE3" );
104 aCode
+= (sal_uInt8
) eOpcode
;
105 sal_uInt32 n
= GetPC();
111 // Storing of the created image in the module
113 void SbiCodeGen::Save()
115 SbiImage
* p
= new SbiImage
;
116 rMod
.StartDefinitions();
117 // OPTION BASE-Value:
118 p
->nDimBase
= pParser
->nBase
;
119 // OPTION take over the EXPLICIT-Flag
120 if( pParser
->bExplicit
)
121 p
->SetFlag( SBIMG_EXPLICIT
);
124 if( rMod
.mnType
== com::sun::star::script::ModuleType::CLASS
)
126 OSL_TRACE("COdeGen::save() classmodule processing");
127 rMod
.bIsProxyModule
= true;
128 p
->SetFlag( SBIMG_CLASSMODULE
);
129 GetSbData()->pClassFac
->AddClassModule( &rMod
);
131 nIfaceCount
= pParser
->aIfaceVector
.size();
132 if( !rMod
.pClassData
)
133 rMod
.pClassData
= new SbClassData
;
136 for( int i
= 0 ; i
< nIfaceCount
; i
++ )
138 const OUString
& rIfaceName
= pParser
->aIfaceVector
[i
];
139 SbxVariable
* pIfaceVar
= new SbxVariable( SbxVARIANT
);
140 pIfaceVar
->SetName( rIfaceName
);
141 SbxArray
* pIfaces
= rMod
.pClassData
->mxIfaces
;
142 pIfaces
->Insert( pIfaceVar
, pIfaces
->Count() );
146 rMod
.pClassData
->maRequiredTypes
= pParser
->aRequiredTypes
;
150 GetSbData()->pClassFac
->RemoveClassModule( &rMod
);
151 // Only a ClassModule can revert to Normal
152 if ( rMod
.mnType
== com::sun::star::script::ModuleType::CLASS
)
154 rMod
.mnType
= com::sun::star::script::ModuleType::NORMAL
;
156 rMod
.bIsProxyModule
= false;
160 if( pParser
->HasGlobalCode() )
162 p
->SetFlag( SBIMG_INITCODE
);
165 for( SbiSymDef
* pDef
= pParser
->aPublics
.First(); pDef
;
166 pDef
= pParser
->aPublics
.Next() )
168 SbiProcDef
* pProc
= pDef
->GetProcDef();
169 if( pProc
&& pProc
->IsDefined() )
171 OUString aProcName
= pProc
->GetName();
172 OUString aIfaceProcName
;
174 sal_uInt16 nPassCount
= 1;
177 int nPropPrefixFound
= aProcName
.indexOf(OUString("Property "));
178 OUString aPureProcName
= aProcName
;
179 OUString aPropPrefix
;
180 if( nPropPrefixFound
== 0 )
182 aPropPrefix
= aProcName
.copy( 0, 13 ); // 13 == Len( "Property ?et " )
183 aPureProcName
= aProcName
.copy( 13 );
185 for( int i
= 0 ; i
< nIfaceCount
; i
++ )
187 const OUString
& rIfaceName
= pParser
->aIfaceVector
[i
];
188 int nFound
= aPureProcName
.indexOf( rIfaceName
);
189 if( nFound
== 0 && '_' == aPureProcName
[rIfaceName
.getLength()] )
191 if( nPropPrefixFound
== 0 )
193 aIfaceProcName
+= aPropPrefix
;
195 aIfaceProcName
+= aPureProcName
.copy( rIfaceName
.getLength() + 1 );
196 aIfaceName
= rIfaceName
;
202 SbMethod
* pMeth
= NULL
;
203 for( sal_uInt16 nPass
= 0 ; nPass
< nPassCount
; nPass
++ )
207 aProcName
= aIfaceProcName
;
209 PropertyMode ePropMode
= pProc
->getPropertyMode();
210 if( ePropMode
!= PROPERTY_MODE_NONE
)
212 SbxDataType ePropType
= SbxEMPTY
;
215 case PROPERTY_MODE_GET
:
216 ePropType
= pProc
->GetType();
218 case PROPERTY_MODE_LET
:
220 // type == type of first parameter
221 ePropType
= SbxVARIANT
; // Default
222 SbiSymPool
* pPool
= &pProc
->GetParams();
223 if( pPool
->GetSize() > 1 )
225 SbiSymDef
* pPar
= pPool
->Get( 1 );
228 ePropType
= pPar
->GetType();
233 case PROPERTY_MODE_SET
:
234 ePropType
= SbxOBJECT
;
236 case PROPERTY_MODE_NONE
:
237 OSL_FAIL( "Illegal PropertyMode PROPERTY_MODE_NONE" );
240 OUString aPropName
= pProc
->GetPropName();
243 aPropName
= aPropName
.copy( aIfaceName
.getLength() + 1 );
245 OSL_TRACE("*** getProcedureProperty for thing %s",
246 rtl::OUStringToOString( aPropName
,RTL_TEXTENCODING_UTF8
).getStr() );
247 rMod
.GetProcedureProperty( aPropName
, ePropType
);
251 rMod
.GetIfaceMapperMethod( aProcName
, pMeth
);
255 pMeth
= rMod
.GetMethod( aProcName
, pProc
->GetType() );
257 if( !pProc
->IsPublic() )
259 pMeth
->SetFlag( SBX_PRIVATE
);
261 // Declare? -> Hidden
262 if( !pProc
->GetLib().isEmpty())
264 pMeth
->SetFlag( SBX_HIDDEN
);
266 pMeth
->nStart
= pProc
->GetAddr();
267 pMeth
->nLine1
= pProc
->GetLine1();
268 pMeth
->nLine2
= pProc
->GetLine2();
270 SbxInfo
* pInfo
= pMeth
->GetInfo();
271 OUString aHelpFile
, aComment
;
272 sal_uIntPtr nHelpId
= 0;
275 // Rescue the additional data
276 aHelpFile
= pInfo
->GetHelpFile();
277 aComment
= pInfo
->GetComment();
278 nHelpId
= pInfo
->GetHelpId();
280 // And reestablish the parameter list
281 pInfo
= new SbxInfo( aHelpFile
, nHelpId
);
282 pInfo
->SetComment( aComment
);
283 SbiSymPool
* pPool
= &pProc
->GetParams();
284 // The first element is always the value of the function!
285 for( sal_uInt16 i
= 1; i
< pPool
->GetSize(); i
++ )
287 SbiSymDef
* pPar
= pPool
->Get( i
);
288 SbxDataType t
= pPar
->GetType();
289 if( !pPar
->IsByVal() )
291 t
= (SbxDataType
) ( t
| SbxBYREF
);
293 if( pPar
->GetDims() )
295 t
= (SbxDataType
) ( t
| SbxARRAY
);
297 // #33677 hand-over an Optional-Info
298 sal_uInt16 nFlags
= SBX_READ
;
299 if( pPar
->IsOptional() )
301 nFlags
|= SBX_OPTIONAL
;
303 pInfo
->AddParam( pPar
->GetName(), t
, nFlags
);
305 sal_uInt32 nUserData
= 0;
306 sal_uInt16 nDefaultId
= pPar
->GetDefaultId();
309 nUserData
|= nDefaultId
;
311 if( pPar
->IsParamArray() )
313 nUserData
|= PARAM_INFO_PARAMARRAY
;
315 if( pPar
->IsWithBrackets() )
317 nUserData
|= PARAM_INFO_WITHBRACKETS
;
321 SbxParamInfo
* pParam
= (SbxParamInfo
*)pInfo
->GetParam( i
);
322 pParam
->nUserData
= nUserData
;
325 pMeth
->SetInfo( pInfo
);
331 p
->AddCode( aCode
.GetBuffer(), aCode
.GetSize() );
333 // The global StringPool. 0 is not occupied.
334 SbiStringPool
* pPool
= &pParser
->aGblStrings
;
335 sal_uInt16 nSize
= pPool
->GetSize();
336 p
->MakeStrings( nSize
);
338 for( i
= 1; i
<= nSize
; i
++ )
340 p
->AddString( pPool
->Find( i
) );
343 sal_uInt16 nCount
= pParser
->rTypeArray
->Count();
344 for (i
= 0; i
< nCount
; i
++)
346 p
->AddType((SbxObject
*)pParser
->rTypeArray
->Get(i
));
348 // Insert enum objects
349 nCount
= pParser
->rEnumArray
->Count();
350 for (i
= 0; i
< nCount
; i
++)
352 p
->AddEnum((SbxObject
*)pParser
->rEnumArray
->Get(i
));
362 rMod
.EndDefinitions();
369 virtual ~PCodeVisitor();
371 virtual void start( sal_uInt8
* pStart
) = 0;
372 virtual void processOpCode0( SbiOpcode eOp
) = 0;
373 virtual void processOpCode1( SbiOpcode eOp
, T nOp1
) = 0;
374 virtual void processOpCode2( SbiOpcode eOp
, T nOp1
, T nOp2
) = 0;
375 virtual bool processParams() = 0;
376 virtual void end() = 0;
379 template <class T
> PCodeVisitor
< T
>::~PCodeVisitor()
383 class PCodeBufferWalker
388 T
readParam( sal_uInt8
*& pCode
)
390 short nBytes
= sizeof( T
);
392 for ( int i
=0; i
<nBytes
; ++i
)
393 nOp1
|= *pCode
++ << ( i
* 8);
397 PCodeBufferWalker( sal_uInt8
* pCode
, T nBytes
): m_nBytes( nBytes
), m_pCode( pCode
)
400 void visitBuffer( PCodeVisitor
< T
>& visitor
)
402 sal_uInt8
* pCode
= m_pCode
;
405 sal_uInt8
* pEnd
= pCode
+ m_nBytes
;
406 visitor
.start( m_pCode
);
407 T nOp1
= 0, nOp2
= 0;
408 for( ; pCode
< pEnd
; )
410 SbiOpcode eOp
= (SbiOpcode
)(*pCode
++);
412 if ( eOp
<= SbOP0_END
)
413 visitor
.processOpCode0( eOp
);
414 else if( eOp
>= SbOP1_START
&& eOp
<= SbOP1_END
)
416 if ( visitor
.processParams() )
417 nOp1
= readParam( pCode
);
419 pCode
+= sizeof( T
);
420 visitor
.processOpCode1( eOp
, nOp1
);
422 else if( eOp
>= SbOP2_START
&& eOp
<= SbOP2_END
)
424 if ( visitor
.processParams() )
426 nOp1
= readParam( pCode
);
427 nOp2
= readParam( pCode
);
430 pCode
+= ( sizeof( T
) * 2 );
431 visitor
.processOpCode2( eOp
, nOp1
, nOp2
);
438 template < class T
, class S
>
439 class OffSetAccumulator
: public PCodeVisitor
< T
>
442 T m_nNumSingleParams
;
443 T m_nNumDoubleParams
;
446 OffSetAccumulator() : m_nNumOp0(0), m_nNumSingleParams(0), m_nNumDoubleParams(0){}
447 virtual void start( sal_uInt8
* /*pStart*/ ){}
448 virtual void processOpCode0( SbiOpcode
/*eOp*/ ){ ++m_nNumOp0
; }
449 virtual void processOpCode1( SbiOpcode
/*eOp*/, T
/*nOp1*/ ){ ++m_nNumSingleParams
; }
450 virtual void processOpCode2( SbiOpcode
/*eOp*/, T
/*nOp1*/, T
/*nOp2*/ ) { ++m_nNumDoubleParams
; }
455 static const S max
= std::numeric_limits
< S
>::max();
456 result
= m_nNumOp0
+ ( ( sizeof(S
) + 1 ) * m_nNumSingleParams
) + ( (( sizeof(S
) * 2 )+ 1 ) * m_nNumDoubleParams
);
457 return std::min(static_cast<T
>(max
), result
);
459 virtual bool processParams(){ return false; }
464 template < class T
, class S
>
466 class BufferTransformer
: public PCodeVisitor
< T
>
469 SbiBuffer m_ConvertedBuf
;
471 BufferTransformer():m_pStart(NULL
), m_ConvertedBuf( NULL
, 1024 ) {}
472 virtual void start( sal_uInt8
* pStart
){ m_pStart
= pStart
; }
473 virtual void processOpCode0( SbiOpcode eOp
)
475 m_ConvertedBuf
+= (sal_uInt8
)eOp
;
477 virtual void processOpCode1( SbiOpcode eOp
, T nOp1
)
479 m_ConvertedBuf
+= (sal_uInt8
)eOp
;
490 nOp1
= static_cast<T
>( convertBufferOffSet(m_pStart
, nOp1
) );
494 nOp1
= static_cast<T
>( convertBufferOffSet(m_pStart
, nOp1
) );
500 m_ConvertedBuf
+= (S
)nOp1
;
502 virtual void processOpCode2( SbiOpcode eOp
, T nOp1
, T nOp2
)
504 m_ConvertedBuf
+= (sal_uInt8
)eOp
;
505 if ( eOp
== _CASEIS
)
507 nOp1
= static_cast<T
>( convertBufferOffSet(m_pStart
, nOp1
) );
508 m_ConvertedBuf
+= (S
)nOp1
;
509 m_ConvertedBuf
+= (S
)nOp2
;
512 virtual bool processParams(){ return true; }
513 virtual void end() {}
514 // yeuch, careful here, you can only call
515 // GetBuffer on the returned SbiBuffer once, also
516 // you (as the caller) get to own the memory
519 return m_ConvertedBuf
;
521 static S
convertBufferOffSet( sal_uInt8
* pStart
, T nOp1
)
523 PCodeBufferWalker
< T
> aBuff( pStart
, nOp1
);
524 OffSetAccumulator
< T
, S
> aVisitor
;
525 aBuff
.visitBuffer( aVisitor
);
526 return aVisitor
.offset();
531 SbiCodeGen::calcNewOffSet( sal_uInt8
* pCode
, sal_uInt16 nOffset
)
533 return BufferTransformer
< sal_uInt16
, sal_uInt32
>::convertBufferOffSet( pCode
, nOffset
);
537 SbiCodeGen::calcLegacyOffSet( sal_uInt8
* pCode
, sal_uInt32 nOffset
)
539 return BufferTransformer
< sal_uInt32
, sal_uInt16
>::convertBufferOffSet( pCode
, nOffset
);
542 template <class T
, class S
>
544 PCodeBuffConvertor
<T
,S
>::convert()
546 PCodeBufferWalker
< T
> aBuf( m_pStart
, m_nSize
);
547 BufferTransformer
< T
, S
> aTrnsfrmer
;
548 aBuf
.visitBuffer( aTrnsfrmer
);
549 m_pCnvtdBuf
= (sal_uInt8
*)aTrnsfrmer
.buffer().GetBuffer();
550 m_nCnvtdSize
= static_cast<S
>( aTrnsfrmer
.buffer().GetSize() );
553 template class PCodeBuffConvertor
< sal_uInt16
, sal_uInt32
>;
554 template class PCodeBuffConvertor
< sal_uInt32
, sal_uInt16
>;
556 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */