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>
23 #include "codegen.hxx"
27 #include <osl/diagnose.h>
28 #include <com/sun/star/script/ModuleType.hpp>
30 // nInc is the increment size of the buffers
32 SbiCodeGen::SbiCodeGen( SbModule
& r
, SbiParser
* p
, short nInc
)
33 : rMod( r
), aCode( p
, nInc
)
42 sal_uInt32
SbiCodeGen::GetPC()
44 return aCode
.GetSize();
47 // memorize the statement
49 void SbiCodeGen::Statement()
51 if( pParser
->IsCodeCompleting() )
56 nLine
= pParser
->GetLine();
57 nCol
= pParser
->GetCol1();
59 // #29955 Store the information of the for-loop-layer
60 // in the uppper Byte of the column
61 nCol
= (nCol
& 0xff) + 0x100 * nForLevel
;
64 // Mark the beginning of a statement
66 void SbiCodeGen::GenStmnt()
68 if( pParser
->IsCodeCompleting() )
74 Gen( _STMNT
, nLine
, nCol
);
78 // The Gen-Routines return the offset of the 1. operand,
79 // so that jumps can sink their backchain there.
81 sal_uInt32
SbiCodeGen::Gen( SbiOpcode eOpcode
)
83 if( pParser
->IsCodeCompleting() )
87 if( eOpcode
< SbOP0_START
|| eOpcode
> SbOP0_END
)
88 pParser
->Error( SbERR_INTERNAL_ERROR
, "OPCODE1" );
91 aCode
+= (sal_uInt8
) eOpcode
;
95 sal_uInt32
SbiCodeGen::Gen( SbiOpcode eOpcode
, sal_uInt32 nOpnd
)
97 if( pParser
->IsCodeCompleting() )
101 if( eOpcode
< SbOP1_START
|| eOpcode
> SbOP1_END
)
102 pParser
->Error( SbERR_INTERNAL_ERROR
, "OPCODE2" );
105 aCode
+= (sal_uInt8
) eOpcode
;
106 sal_uInt32 n
= GetPC();
111 sal_uInt32
SbiCodeGen::Gen( SbiOpcode eOpcode
, sal_uInt32 nOpnd1
, sal_uInt32 nOpnd2
)
113 if( pParser
->IsCodeCompleting() )
117 if( eOpcode
< SbOP2_START
|| eOpcode
> SbOP2_END
)
118 pParser
->Error( SbERR_INTERNAL_ERROR
, "OPCODE3" );
121 aCode
+= (sal_uInt8
) eOpcode
;
122 sal_uInt32 n
= GetPC();
128 // Storing of the created image in the module
130 void SbiCodeGen::Save()
132 if( pParser
->IsCodeCompleting() )
135 SbiImage
* p
= new SbiImage
;
136 rMod
.StartDefinitions();
137 // OPTION BASE-Value:
138 p
->nDimBase
= pParser
->nBase
;
139 // OPTION take over the EXPLICIT-Flag
140 if( pParser
->bExplicit
)
141 p
->SetFlag( SbiImageFlags::EXPLICIT
);
144 if( rMod
.mnType
== com::sun::star::script::ModuleType::CLASS
)
146 OSL_TRACE("COdeGen::save() classmodule processing");
147 rMod
.bIsProxyModule
= true;
148 p
->SetFlag( SbiImageFlags::CLASSMODULE
);
149 GetSbData()->pClassFac
->AddClassModule( &rMod
);
151 nIfaceCount
= pParser
->aIfaceVector
.size();
152 if( !rMod
.pClassData
)
153 rMod
.pClassData
= new SbClassData
;
156 for( int i
= 0 ; i
< nIfaceCount
; i
++ )
158 const OUString
& rIfaceName
= pParser
->aIfaceVector
[i
];
159 SbxVariable
* pIfaceVar
= new SbxVariable( SbxVARIANT
);
160 pIfaceVar
->SetName( rIfaceName
);
161 SbxArray
* pIfaces
= rMod
.pClassData
->mxIfaces
;
162 pIfaces
->Insert( pIfaceVar
, pIfaces
->Count() );
166 rMod
.pClassData
->maRequiredTypes
= pParser
->aRequiredTypes
;
170 GetSbData()->pClassFac
->RemoveClassModule( &rMod
);
171 // Only a ClassModule can revert to Normal
172 if ( rMod
.mnType
== com::sun::star::script::ModuleType::CLASS
)
174 rMod
.mnType
= com::sun::star::script::ModuleType::NORMAL
;
176 rMod
.bIsProxyModule
= false;
180 if( pParser
->HasGlobalCode() )
182 p
->SetFlag( SbiImageFlags::INITCODE
);
185 for( SbiSymDef
* pDef
= pParser
->aPublics
.First(); pDef
;
186 pDef
= pParser
->aPublics
.Next() )
188 SbiProcDef
* pProc
= pDef
->GetProcDef();
189 if( pProc
&& pProc
->IsDefined() )
191 OUString aProcName
= pProc
->GetName();
192 OUString aIfaceProcName
;
194 sal_uInt16 nPassCount
= 1;
197 int nPropPrefixFound
= aProcName
.indexOf(OUString("Property "));
198 OUString aPureProcName
= aProcName
;
199 OUString aPropPrefix
;
200 if( nPropPrefixFound
== 0 )
202 aPropPrefix
= aProcName
.copy( 0, 13 ); // 13 == Len( "Property ?et " )
203 aPureProcName
= aProcName
.copy( 13 );
205 for( int i
= 0 ; i
< nIfaceCount
; i
++ )
207 const OUString
& rIfaceName
= pParser
->aIfaceVector
[i
];
208 int nFound
= aPureProcName
.indexOf( rIfaceName
);
209 if( nFound
== 0 && '_' == aPureProcName
[rIfaceName
.getLength()] )
211 if( nPropPrefixFound
== 0 )
213 aIfaceProcName
+= aPropPrefix
;
215 aIfaceProcName
+= aPureProcName
.copy( rIfaceName
.getLength() + 1 );
216 aIfaceName
= rIfaceName
;
222 SbMethod
* pMeth
= NULL
;
223 for( sal_uInt16 nPass
= 0 ; nPass
< nPassCount
; nPass
++ )
227 aProcName
= aIfaceProcName
;
229 PropertyMode ePropMode
= pProc
->getPropertyMode();
230 if( ePropMode
!= PROPERTY_MODE_NONE
)
232 SbxDataType ePropType
= SbxEMPTY
;
235 case PROPERTY_MODE_GET
:
236 ePropType
= pProc
->GetType();
238 case PROPERTY_MODE_LET
:
240 // type == type of first parameter
241 ePropType
= SbxVARIANT
; // Default
242 SbiSymPool
* pPool
= &pProc
->GetParams();
243 if( pPool
->GetSize() > 1 )
245 SbiSymDef
* pPar
= pPool
->Get( 1 );
248 ePropType
= pPar
->GetType();
253 case PROPERTY_MODE_SET
:
254 ePropType
= SbxOBJECT
;
257 OSL_FAIL("Illegal PropertyMode");
260 OUString aPropName
= pProc
->GetPropName();
263 aPropName
= aPropName
.copy( aIfaceName
.getLength() + 1 );
265 OSL_TRACE("*** getProcedureProperty for thing %s",
266 OUStringToOString( aPropName
,RTL_TEXTENCODING_UTF8
).getStr() );
267 rMod
.GetProcedureProperty( aPropName
, ePropType
);
271 rMod
.GetIfaceMapperMethod( aProcName
, pMeth
);
275 pMeth
= rMod
.GetMethod( aProcName
, pProc
->GetType() );
277 if( !pProc
->IsPublic() )
279 pMeth
->SetFlag( SBX_PRIVATE
);
281 // Declare? -> Hidden
282 if( !pProc
->GetLib().isEmpty())
284 pMeth
->SetFlag( SBX_HIDDEN
);
286 pMeth
->nStart
= pProc
->GetAddr();
287 pMeth
->nLine1
= pProc
->GetLine1();
288 pMeth
->nLine2
= pProc
->GetLine2();
290 SbxInfo
* pInfo
= pMeth
->GetInfo();
291 OUString aHelpFile
, aComment
;
292 sal_uInt32 nHelpId
= 0;
295 // Rescue the additional data
296 aHelpFile
= pInfo
->GetHelpFile();
297 aComment
= pInfo
->GetComment();
298 nHelpId
= pInfo
->GetHelpId();
300 // And reestablish the parameter list
301 pInfo
= new SbxInfo( aHelpFile
, nHelpId
);
302 pInfo
->SetComment( aComment
);
303 SbiSymPool
* pPool
= &pProc
->GetParams();
304 // The first element is always the value of the function!
305 for( sal_uInt16 i
= 1; i
< pPool
->GetSize(); i
++ )
307 SbiSymDef
* pPar
= pPool
->Get( i
);
308 SbxDataType t
= pPar
->GetType();
309 if( !pPar
->IsByVal() )
311 t
= (SbxDataType
) ( t
| SbxBYREF
);
313 if( pPar
->GetDims() )
315 t
= (SbxDataType
) ( t
| SbxARRAY
);
317 // #33677 hand-over an Optional-Info
318 SbxFlagBits nFlags
= SBX_READ
;
319 if( pPar
->IsOptional() )
321 nFlags
|= SBX_OPTIONAL
;
323 pInfo
->AddParam( pPar
->GetName(), t
, nFlags
);
325 sal_uInt32 nUserData
= 0;
326 sal_uInt16 nDefaultId
= pPar
->GetDefaultId();
329 nUserData
|= nDefaultId
;
331 if( pPar
->IsParamArray() )
333 nUserData
|= PARAM_INFO_PARAMARRAY
;
335 if( pPar
->IsWithBrackets() )
337 nUserData
|= PARAM_INFO_WITHBRACKETS
;
339 SbxParamInfo
* pParam
= NULL
;
342 pParam
= const_cast<SbxParamInfo
*>(pInfo
->GetParam( i
));
346 pParam
->nUserData
= nUserData
;
349 pMeth
->SetInfo( pInfo
);
355 p
->AddCode( aCode
.GetBuffer(), aCode
.GetSize() );
357 // The global StringPool. 0 is not occupied.
358 SbiStringPool
* pPool
= &pParser
->aGblStrings
;
359 sal_uInt16 nSize
= pPool
->GetSize();
360 p
->MakeStrings( nSize
);
362 for( i
= 1; i
<= nSize
; i
++ )
364 p
->AddString( pPool
->Find( i
) );
367 sal_uInt16 nCount
= pParser
->rTypeArray
->Count();
368 for (i
= 0; i
< nCount
; i
++)
370 p
->AddType(static_cast<SbxObject
*>(pParser
->rTypeArray
->Get(i
)));
372 // Insert enum objects
373 nCount
= pParser
->rEnumArray
->Count();
374 for (i
= 0; i
< nCount
; i
++)
376 p
->AddEnum(static_cast<SbxObject
*>(pParser
->rEnumArray
->Get(i
)));
386 rMod
.EndDefinitions();
393 virtual ~PCodeVisitor();
395 virtual void start( sal_uInt8
* pStart
) = 0;
396 virtual void processOpCode0( SbiOpcode eOp
) = 0;
397 virtual void processOpCode1( SbiOpcode eOp
, T nOp1
) = 0;
398 virtual void processOpCode2( SbiOpcode eOp
, T nOp1
, T nOp2
) = 0;
399 virtual bool processParams() = 0;
400 virtual void end() = 0;
403 template <class T
> PCodeVisitor
< T
>::~PCodeVisitor()
407 class PCodeBufferWalker
412 static T
readParam( sal_uInt8
*& pCode
)
414 short nBytes
= sizeof( T
);
416 for ( int i
=0; i
<nBytes
; ++i
)
417 nOp1
|= *pCode
++ << ( i
* 8);
421 PCodeBufferWalker( sal_uInt8
* pCode
, T nBytes
): m_nBytes( nBytes
), m_pCode( pCode
)
424 void visitBuffer( PCodeVisitor
< T
>& visitor
)
426 sal_uInt8
* pCode
= m_pCode
;
429 sal_uInt8
* pEnd
= pCode
+ m_nBytes
;
430 visitor
.start( m_pCode
);
431 T nOp1
= 0, nOp2
= 0;
432 for( ; pCode
< pEnd
; )
434 SbiOpcode eOp
= (SbiOpcode
)(*pCode
++);
436 if ( eOp
<= SbOP0_END
)
437 visitor
.processOpCode0( eOp
);
438 else if( eOp
>= SbOP1_START
&& eOp
<= SbOP1_END
)
440 if ( visitor
.processParams() )
441 nOp1
= readParam( pCode
);
443 pCode
+= sizeof( T
);
444 visitor
.processOpCode1( eOp
, nOp1
);
446 else if( eOp
>= SbOP2_START
&& eOp
<= SbOP2_END
)
448 if ( visitor
.processParams() )
450 nOp1
= readParam( pCode
);
451 nOp2
= readParam( pCode
);
454 pCode
+= ( sizeof( T
) * 2 );
455 visitor
.processOpCode2( eOp
, nOp1
, nOp2
);
462 template < class T
, class S
>
463 class OffSetAccumulator
: public PCodeVisitor
< T
>
466 T m_nNumSingleParams
;
467 T m_nNumDoubleParams
;
470 OffSetAccumulator() : m_nNumOp0(0), m_nNumSingleParams(0), m_nNumDoubleParams(0){}
471 virtual void start( sal_uInt8
* /*pStart*/ ){}
472 virtual void processOpCode0( SbiOpcode
/*eOp*/ ){ ++m_nNumOp0
; }
473 virtual void processOpCode1( SbiOpcode
/*eOp*/, T
/*nOp1*/ ){ ++m_nNumSingleParams
; }
474 virtual void processOpCode2( SbiOpcode
/*eOp*/, T
/*nOp1*/, T
/*nOp2*/ ) { ++m_nNumDoubleParams
; }
479 static const S max
= std::numeric_limits
< S
>::max();
480 result
= m_nNumOp0
+ ( ( sizeof(S
) + 1 ) * m_nNumSingleParams
) + ( (( sizeof(S
) * 2 )+ 1 ) * m_nNumDoubleParams
);
481 return std::min(static_cast<T
>(max
), result
);
483 virtual bool processParams(){ return false; }
488 template < class T
, class S
>
490 class BufferTransformer
: public PCodeVisitor
< T
>
493 SbiBuffer m_ConvertedBuf
;
495 BufferTransformer():m_pStart(NULL
), m_ConvertedBuf( NULL
, 1024 ) {}
496 virtual void start( sal_uInt8
* pStart
){ m_pStart
= pStart
; }
497 virtual void processOpCode0( SbiOpcode eOp
)
499 m_ConvertedBuf
+= (sal_uInt8
)eOp
;
501 virtual void processOpCode1( SbiOpcode eOp
, T nOp1
)
503 m_ConvertedBuf
+= (sal_uInt8
)eOp
;
514 nOp1
= static_cast<T
>( convertBufferOffSet(m_pStart
, nOp1
) );
518 nOp1
= static_cast<T
>( convertBufferOffSet(m_pStart
, nOp1
) );
524 m_ConvertedBuf
+= static_cast<S
>(nOp1
);
526 virtual void processOpCode2( SbiOpcode eOp
, T nOp1
, T nOp2
)
528 m_ConvertedBuf
+= (sal_uInt8
)eOp
;
529 if ( eOp
== _CASEIS
)
531 nOp1
= static_cast<T
>( convertBufferOffSet(m_pStart
, nOp1
) );
532 m_ConvertedBuf
+= static_cast<S
>(nOp1
);
533 m_ConvertedBuf
+= static_cast<S
>(nOp2
);
536 virtual bool processParams(){ return true; }
537 virtual void end() {}
538 // yeuch, careful here, you can only call
539 // GetBuffer on the returned SbiBuffer once, also
540 // you (as the caller) get to own the memory
543 return m_ConvertedBuf
;
545 static S
convertBufferOffSet( sal_uInt8
* pStart
, T nOp1
)
547 PCodeBufferWalker
< T
> aBuff( pStart
, nOp1
);
548 OffSetAccumulator
< T
, S
> aVisitor
;
549 aBuff
.visitBuffer( aVisitor
);
550 return aVisitor
.offset();
555 SbiCodeGen::calcNewOffSet( sal_uInt8
* pCode
, sal_uInt16 nOffset
)
557 return BufferTransformer
< sal_uInt16
, sal_uInt32
>::convertBufferOffSet( pCode
, nOffset
);
561 SbiCodeGen::calcLegacyOffSet( sal_uInt8
* pCode
, sal_uInt32 nOffset
)
563 return BufferTransformer
< sal_uInt32
, sal_uInt16
>::convertBufferOffSet( pCode
, nOffset
);
566 template <class T
, class S
>
568 PCodeBuffConvertor
<T
,S
>::convert()
570 PCodeBufferWalker
< T
> aBuf( m_pStart
, m_nSize
);
571 BufferTransformer
< T
, S
> aTrnsfrmer
;
572 aBuf
.visitBuffer( aTrnsfrmer
);
573 m_pCnvtdBuf
= reinterpret_cast<sal_uInt8
*>(aTrnsfrmer
.buffer().GetBuffer());
574 m_nCnvtdSize
= static_cast<S
>( aTrnsfrmer
.buffer().GetSize() );
577 template class PCodeBuffConvertor
< sal_uInt16
, sal_uInt32
>;
578 template class PCodeBuffConvertor
< sal_uInt32
, sal_uInt16
>;
580 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */