Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include <basic/sbx.hxx>
22 : #include "sbcomp.hxx"
23 : #include "image.hxx"
24 : #include <limits>
25 : #include <algorithm>
26 : #include <com/sun/star/script/ModuleType.hpp>
27 :
28 : // nInc is the increment size of the buffers
29 :
30 8 : SbiCodeGen::SbiCodeGen( SbModule& r, SbiParser* p, short nInc )
31 8 : : rMod( r ), aCode( p, nInc )
32 : {
33 8 : pParser = p;
34 8 : bStmnt = false;
35 8 : nLine = 0;
36 8 : nCol = 0;
37 8 : nForLevel = 0;
38 8 : }
39 :
40 239 : sal_uInt32 SbiCodeGen::GetPC()
41 : {
42 239 : return aCode.GetSize();
43 : }
44 :
45 : // memorize the statement
46 :
47 59 : void SbiCodeGen::Statement()
48 : {
49 59 : bStmnt = true;
50 :
51 59 : nLine = pParser->GetLine();
52 59 : nCol = pParser->GetCol1();
53 :
54 : // #29955 Store the information of the for-loop-layer
55 : // in the uppper Byte of the column
56 59 : nCol = (nCol & 0xff) + 0x100 * nForLevel;
57 59 : }
58 :
59 : // Mark the beginning of a statement
60 :
61 239 : void SbiCodeGen::GenStmnt()
62 : {
63 239 : if( bStmnt )
64 : {
65 55 : bStmnt = false;
66 55 : Gen( _STMNT, nLine, nCol );
67 : }
68 239 : }
69 :
70 : // The Gen-Routines return the offset of the 1. operand,
71 : // so that jumps can sink their backchain there.
72 :
73 50 : sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode )
74 : {
75 : #ifdef DBG_UTIL
76 : if( eOpcode < SbOP0_START || eOpcode > SbOP0_END )
77 : pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE1" );
78 : #endif
79 50 : GenStmnt();
80 50 : aCode += (sal_uInt8) eOpcode;
81 50 : return GetPC();
82 : }
83 :
84 32 : sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode, sal_uInt32 nOpnd )
85 : {
86 : #ifdef DBG_UTIL
87 : if( eOpcode < SbOP1_START || eOpcode > SbOP1_END )
88 : pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE2" );
89 : #endif
90 32 : GenStmnt();
91 32 : aCode += (sal_uInt8) eOpcode;
92 32 : sal_uInt32 n = GetPC();
93 32 : aCode += nOpnd;
94 32 : return n;
95 : }
96 :
97 149 : sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode, sal_uInt32 nOpnd1, sal_uInt32 nOpnd2 )
98 : {
99 : #ifdef DBG_UTIL
100 : if( eOpcode < SbOP2_START || eOpcode > SbOP2_END )
101 : pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE3" );
102 : #endif
103 149 : GenStmnt();
104 149 : aCode += (sal_uInt8) eOpcode;
105 149 : sal_uInt32 n = GetPC();
106 149 : aCode += nOpnd1;
107 149 : aCode += nOpnd2;
108 149 : return n;
109 : }
110 :
111 : // Storing of the created image in the module
112 :
113 8 : void SbiCodeGen::Save()
114 : {
115 8 : SbiImage* p = new SbiImage;
116 8 : rMod.StartDefinitions();
117 : // OPTION BASE-Value:
118 8 : p->nDimBase = pParser->nBase;
119 : // OPTION take over the EXPLICIT-Flag
120 8 : if( pParser->bExplicit )
121 0 : p->SetFlag( SBIMG_EXPLICIT );
122 :
123 8 : int nIfaceCount = 0;
124 8 : if( rMod.mnType == com::sun::star::script::ModuleType::CLASS )
125 : {
126 : OSL_TRACE("COdeGen::save() classmodule processing");
127 0 : rMod.bIsProxyModule = true;
128 0 : p->SetFlag( SBIMG_CLASSMODULE );
129 0 : GetSbData()->pClassFac->AddClassModule( &rMod );
130 :
131 0 : nIfaceCount = pParser->aIfaceVector.size();
132 0 : if( !rMod.pClassData )
133 0 : rMod.pClassData = new SbClassData;
134 0 : if( nIfaceCount )
135 : {
136 0 : for( int i = 0 ; i < nIfaceCount ; i++ )
137 : {
138 0 : const OUString& rIfaceName = pParser->aIfaceVector[i];
139 0 : SbxVariable* pIfaceVar = new SbxVariable( SbxVARIANT );
140 0 : pIfaceVar->SetName( rIfaceName );
141 0 : SbxArray* pIfaces = rMod.pClassData->mxIfaces;
142 0 : pIfaces->Insert( pIfaceVar, pIfaces->Count() );
143 : }
144 : }
145 :
146 0 : rMod.pClassData->maRequiredTypes = pParser->aRequiredTypes;
147 : }
148 : else
149 : {
150 8 : GetSbData()->pClassFac->RemoveClassModule( &rMod );
151 : // Only a ClassModule can revert to Normal
152 8 : if ( rMod.mnType == com::sun::star::script::ModuleType::CLASS )
153 : {
154 0 : rMod.mnType = com::sun::star::script::ModuleType::NORMAL;
155 : }
156 8 : rMod.bIsProxyModule = false;
157 : }
158 :
159 : // GlobalCode-Flag
160 8 : if( pParser->HasGlobalCode() )
161 : {
162 0 : p->SetFlag( SBIMG_INITCODE );
163 : }
164 : // Die Entrypoints:
165 16 : for( SbiSymDef* pDef = pParser->aPublics.First(); pDef;
166 8 : pDef = pParser->aPublics.Next() )
167 : {
168 8 : SbiProcDef* pProc = pDef->GetProcDef();
169 8 : if( pProc && pProc->IsDefined() )
170 : {
171 8 : OUString aProcName = pProc->GetName();
172 8 : OUString aIfaceProcName;
173 8 : OUString aIfaceName;
174 8 : sal_uInt16 nPassCount = 1;
175 8 : if( nIfaceCount )
176 : {
177 0 : int nPropPrefixFound = aProcName.indexOf(OUString("Property "));
178 0 : OUString aPureProcName = aProcName;
179 0 : OUString aPropPrefix;
180 0 : if( nPropPrefixFound == 0 )
181 : {
182 0 : aPropPrefix = aProcName.copy( 0, 13 ); // 13 == Len( "Property ?et " )
183 0 : aPureProcName = aProcName.copy( 13 );
184 : }
185 0 : for( int i = 0 ; i < nIfaceCount ; i++ )
186 : {
187 0 : const OUString& rIfaceName = pParser->aIfaceVector[i];
188 0 : int nFound = aPureProcName.indexOf( rIfaceName );
189 0 : if( nFound == 0 && '_' == aPureProcName[rIfaceName.getLength()] )
190 : {
191 0 : if( nPropPrefixFound == 0 )
192 : {
193 0 : aIfaceProcName += aPropPrefix;
194 : }
195 0 : aIfaceProcName += aPureProcName.copy( rIfaceName.getLength() + 1 );
196 0 : aIfaceName = rIfaceName;
197 0 : nPassCount = 2;
198 0 : break;
199 : }
200 0 : }
201 : }
202 8 : SbMethod* pMeth = NULL;
203 16 : for( sal_uInt16 nPass = 0 ; nPass < nPassCount ; nPass++ )
204 : {
205 8 : if( nPass == 1 )
206 : {
207 0 : aProcName = aIfaceProcName;
208 : }
209 8 : PropertyMode ePropMode = pProc->getPropertyMode();
210 8 : if( ePropMode != PROPERTY_MODE_NONE )
211 : {
212 0 : SbxDataType ePropType = SbxEMPTY;
213 0 : switch( ePropMode )
214 : {
215 : case PROPERTY_MODE_GET:
216 0 : ePropType = pProc->GetType();
217 0 : break;
218 : case PROPERTY_MODE_LET:
219 : {
220 : // type == type of first parameter
221 0 : ePropType = SbxVARIANT; // Default
222 0 : SbiSymPool* pPool = &pProc->GetParams();
223 0 : if( pPool->GetSize() > 1 )
224 : {
225 0 : SbiSymDef* pPar = pPool->Get( 1 );
226 0 : if( pPar )
227 : {
228 0 : ePropType = pPar->GetType();
229 : }
230 : }
231 0 : break;
232 : }
233 : case PROPERTY_MODE_SET:
234 0 : ePropType = SbxOBJECT;
235 0 : break;
236 : case PROPERTY_MODE_NONE:
237 : OSL_FAIL( "Illegal PropertyMode PROPERTY_MODE_NONE" );
238 0 : break;
239 : }
240 0 : OUString aPropName = pProc->GetPropName();
241 0 : if( nPass == 1 )
242 : {
243 0 : aPropName = aPropName.copy( aIfaceName.getLength() + 1 );
244 : }
245 : OSL_TRACE("*** getProcedureProperty for thing %s",
246 : rtl::OUStringToOString( aPropName,RTL_TEXTENCODING_UTF8 ).getStr() );
247 0 : rMod.GetProcedureProperty( aPropName, ePropType );
248 : }
249 8 : if( nPass == 1 )
250 : {
251 0 : rMod.GetIfaceMapperMethod( aProcName, pMeth );
252 : }
253 : else
254 : {
255 8 : pMeth = rMod.GetMethod( aProcName, pProc->GetType() );
256 :
257 8 : if( !pProc->IsPublic() )
258 : {
259 0 : pMeth->SetFlag( SBX_PRIVATE );
260 : }
261 : // Declare? -> Hidden
262 8 : if( !pProc->GetLib().isEmpty())
263 : {
264 0 : pMeth->SetFlag( SBX_HIDDEN );
265 : }
266 8 : pMeth->nStart = pProc->GetAddr();
267 8 : pMeth->nLine1 = pProc->GetLine1();
268 8 : pMeth->nLine2 = pProc->GetLine2();
269 : // The parameter:
270 8 : SbxInfo* pInfo = pMeth->GetInfo();
271 8 : OUString aHelpFile, aComment;
272 8 : sal_uIntPtr nHelpId = 0;
273 8 : if( pInfo )
274 : {
275 : // Rescue the additional data
276 0 : aHelpFile = pInfo->GetHelpFile();
277 0 : aComment = pInfo->GetComment();
278 0 : nHelpId = pInfo->GetHelpId();
279 : }
280 : // And reestablish the parameter list
281 8 : pInfo = new SbxInfo( aHelpFile, nHelpId );
282 8 : pInfo->SetComment( aComment );
283 8 : SbiSymPool* pPool = &pProc->GetParams();
284 : // The first element is always the value of the function!
285 8 : for( sal_uInt16 i = 1; i < pPool->GetSize(); i++ )
286 : {
287 0 : SbiSymDef* pPar = pPool->Get( i );
288 0 : SbxDataType t = pPar->GetType();
289 0 : if( !pPar->IsByVal() )
290 : {
291 0 : t = (SbxDataType) ( t | SbxBYREF );
292 : }
293 0 : if( pPar->GetDims() )
294 : {
295 0 : t = (SbxDataType) ( t | SbxARRAY );
296 : }
297 : // #33677 hand-over an Optional-Info
298 0 : sal_uInt16 nFlags = SBX_READ;
299 0 : if( pPar->IsOptional() )
300 : {
301 0 : nFlags |= SBX_OPTIONAL;
302 : }
303 0 : pInfo->AddParam( pPar->GetName(), t, nFlags );
304 :
305 0 : sal_uInt32 nUserData = 0;
306 0 : sal_uInt16 nDefaultId = pPar->GetDefaultId();
307 0 : if( nDefaultId )
308 : {
309 0 : nUserData |= nDefaultId;
310 : }
311 0 : if( pPar->IsParamArray() )
312 : {
313 0 : nUserData |= PARAM_INFO_PARAMARRAY;
314 : }
315 0 : if( pPar->IsWithBrackets() )
316 : {
317 0 : nUserData |= PARAM_INFO_WITHBRACKETS;
318 : }
319 0 : if( nUserData )
320 : {
321 0 : SbxParamInfo* pParam = (SbxParamInfo*)pInfo->GetParam( i );
322 0 : pParam->nUserData = nUserData;
323 : }
324 : }
325 8 : pMeth->SetInfo( pInfo );
326 : }
327 8 : } // for( iPass...
328 : }
329 : }
330 : // The code
331 8 : p->AddCode( aCode.GetBuffer(), aCode.GetSize() );
332 :
333 : // The global StringPool. 0 is not occupied.
334 8 : SbiStringPool* pPool = &pParser->aGblStrings;
335 8 : sal_uInt16 nSize = pPool->GetSize();
336 8 : p->MakeStrings( nSize );
337 : sal_uInt16 i;
338 49 : for( i = 1; i <= nSize; i++ )
339 : {
340 41 : p->AddString( pPool->Find( i ) );
341 : }
342 : // Insert types
343 8 : sal_uInt16 nCount = pParser->rTypeArray->Count();
344 8 : for (i = 0; i < nCount; i++)
345 : {
346 0 : p->AddType((SbxObject *)pParser->rTypeArray->Get(i));
347 : }
348 : // Insert enum objects
349 8 : nCount = pParser->rEnumArray->Count();
350 8 : for (i = 0; i < nCount; i++)
351 : {
352 0 : p->AddEnum((SbxObject *)pParser->rEnumArray->Get(i));
353 : }
354 8 : if( !p->IsError() )
355 : {
356 8 : rMod.pImage = p;
357 : }
358 : else
359 : {
360 0 : delete p;
361 : }
362 8 : rMod.EndDefinitions();
363 8 : }
364 :
365 : template < class T >
366 0 : class PCodeVisitor
367 : {
368 : public:
369 : virtual ~PCodeVisitor();
370 :
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;
377 : };
378 :
379 0 : template <class T> PCodeVisitor< T >::~PCodeVisitor()
380 0 : {}
381 :
382 : template <class T>
383 : class PCodeBufferWalker
384 : {
385 : private:
386 : T m_nBytes;
387 : sal_uInt8* m_pCode;
388 0 : T readParam( sal_uInt8*& pCode )
389 : {
390 0 : short nBytes = sizeof( T );
391 0 : T nOp1=0;
392 0 : for ( int i=0; i<nBytes; ++i )
393 0 : nOp1 |= *pCode++ << ( i * 8);
394 0 : return nOp1;
395 : }
396 : public:
397 0 : PCodeBufferWalker( sal_uInt8* pCode, T nBytes ): m_nBytes( nBytes ), m_pCode( pCode )
398 : {
399 0 : }
400 0 : void visitBuffer( PCodeVisitor< T >& visitor )
401 : {
402 0 : sal_uInt8* pCode = m_pCode;
403 0 : if ( !pCode )
404 0 : return;
405 0 : sal_uInt8* pEnd = pCode + m_nBytes;
406 0 : visitor.start( m_pCode );
407 0 : T nOp1 = 0, nOp2 = 0;
408 0 : for( ; pCode < pEnd; )
409 : {
410 0 : SbiOpcode eOp = (SbiOpcode)(*pCode++);
411 :
412 0 : if ( eOp <= SbOP0_END )
413 0 : visitor.processOpCode0( eOp );
414 0 : else if( eOp >= SbOP1_START && eOp <= SbOP1_END )
415 : {
416 0 : if ( visitor.processParams() )
417 0 : nOp1 = readParam( pCode );
418 : else
419 0 : pCode += sizeof( T );
420 0 : visitor.processOpCode1( eOp, nOp1 );
421 : }
422 0 : else if( eOp >= SbOP2_START && eOp <= SbOP2_END )
423 : {
424 0 : if ( visitor.processParams() )
425 : {
426 0 : nOp1 = readParam( pCode );
427 0 : nOp2 = readParam( pCode );
428 : }
429 : else
430 0 : pCode += ( sizeof( T ) * 2 );
431 0 : visitor.processOpCode2( eOp, nOp1, nOp2 );
432 : }
433 : }
434 0 : visitor.end();
435 : }
436 : };
437 :
438 : template < class T, class S >
439 0 : class OffSetAccumulator : public PCodeVisitor< T >
440 : {
441 : T m_nNumOp0;
442 : T m_nNumSingleParams;
443 : T m_nNumDoubleParams;
444 : public:
445 :
446 0 : OffSetAccumulator() : m_nNumOp0(0), m_nNumSingleParams(0), m_nNumDoubleParams(0){}
447 0 : virtual void start( sal_uInt8* /*pStart*/ ){}
448 0 : virtual void processOpCode0( SbiOpcode /*eOp*/ ){ ++m_nNumOp0; }
449 0 : virtual void processOpCode1( SbiOpcode /*eOp*/, T /*nOp1*/ ){ ++m_nNumSingleParams; }
450 0 : virtual void processOpCode2( SbiOpcode /*eOp*/, T /*nOp1*/, T /*nOp2*/ ) { ++m_nNumDoubleParams; }
451 0 : virtual void end(){}
452 0 : S offset()
453 : {
454 0 : T result = 0 ;
455 : static const S max = std::numeric_limits< S >::max();
456 0 : result = m_nNumOp0 + ( ( sizeof(S) + 1 ) * m_nNumSingleParams ) + ( (( sizeof(S) * 2 )+ 1 ) * m_nNumDoubleParams );
457 0 : return std::min(static_cast<T>(max), result);
458 : }
459 0 : virtual bool processParams(){ return false; }
460 : };
461 :
462 :
463 :
464 : template < class T, class S >
465 :
466 0 : class BufferTransformer : public PCodeVisitor< T >
467 : {
468 : sal_uInt8* m_pStart;
469 : SbiBuffer m_ConvertedBuf;
470 : public:
471 0 : BufferTransformer():m_pStart(NULL), m_ConvertedBuf( NULL, 1024 ) {}
472 0 : virtual void start( sal_uInt8* pStart ){ m_pStart = pStart; }
473 0 : virtual void processOpCode0( SbiOpcode eOp )
474 : {
475 0 : m_ConvertedBuf += (sal_uInt8)eOp;
476 0 : }
477 0 : virtual void processOpCode1( SbiOpcode eOp, T nOp1 )
478 : {
479 0 : m_ConvertedBuf += (sal_uInt8)eOp;
480 0 : switch( eOp )
481 : {
482 : case _JUMP:
483 : case _JUMPT:
484 : case _JUMPF:
485 : case _GOSUB:
486 : case _CASEIS:
487 : case _RETURN:
488 : case _ERRHDL:
489 : case _TESTFOR:
490 0 : nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
491 0 : break;
492 : case _RESUME:
493 0 : if ( nOp1 > 1 )
494 0 : nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
495 0 : break;
496 : default:
497 0 : break; //
498 :
499 : }
500 0 : m_ConvertedBuf += (S)nOp1;
501 0 : }
502 0 : virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 )
503 : {
504 0 : m_ConvertedBuf += (sal_uInt8)eOp;
505 0 : if ( eOp == _CASEIS )
506 0 : if ( nOp1 )
507 0 : nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
508 0 : m_ConvertedBuf += (S)nOp1;
509 0 : m_ConvertedBuf += (S)nOp2;
510 :
511 0 : }
512 0 : virtual bool processParams(){ return true; }
513 0 : 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
517 0 : SbiBuffer& buffer()
518 : {
519 0 : return m_ConvertedBuf;
520 : }
521 0 : static S convertBufferOffSet( sal_uInt8* pStart, T nOp1 )
522 : {
523 0 : PCodeBufferWalker< T > aBuff( pStart, nOp1);
524 0 : OffSetAccumulator< T, S > aVisitor;
525 0 : aBuff.visitBuffer( aVisitor );
526 0 : return aVisitor.offset();
527 : }
528 : };
529 :
530 : sal_uInt32
531 0 : SbiCodeGen::calcNewOffSet( sal_uInt8* pCode, sal_uInt16 nOffset )
532 : {
533 0 : return BufferTransformer< sal_uInt16, sal_uInt32 >::convertBufferOffSet( pCode, nOffset );
534 : }
535 :
536 : sal_uInt16
537 0 : SbiCodeGen::calcLegacyOffSet( sal_uInt8* pCode, sal_uInt32 nOffset )
538 : {
539 0 : return BufferTransformer< sal_uInt32, sal_uInt16 >::convertBufferOffSet( pCode, nOffset );
540 : }
541 :
542 : template <class T, class S>
543 : void
544 0 : PCodeBuffConvertor<T,S>::convert()
545 : {
546 0 : PCodeBufferWalker< T > aBuf( m_pStart, m_nSize );
547 0 : BufferTransformer< T, S > aTrnsfrmer;
548 0 : aBuf.visitBuffer( aTrnsfrmer );
549 0 : m_pCnvtdBuf = (sal_uInt8*)aTrnsfrmer.buffer().GetBuffer();
550 0 : m_nCnvtdSize = static_cast<S>( aTrnsfrmer.buffer().GetSize() );
551 0 : }
552 :
553 : template class PCodeBuffConvertor< sal_uInt16, sal_uInt32 >;
554 : template class PCodeBuffConvertor< sal_uInt32, sal_uInt16 >;
555 :
556 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|