xref: /aoo41x/main/basic/source/comp/codegen.cxx (revision e1f63238)
1*e1f63238SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*e1f63238SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*e1f63238SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*e1f63238SAndrew Rist  * distributed with this work for additional information
6*e1f63238SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*e1f63238SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*e1f63238SAndrew Rist  * "License"); you may not use this file except in compliance
9*e1f63238SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*e1f63238SAndrew Rist  *
11*e1f63238SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*e1f63238SAndrew Rist  *
13*e1f63238SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*e1f63238SAndrew Rist  * software distributed under the License is distributed on an
15*e1f63238SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*e1f63238SAndrew Rist  * KIND, either express or implied.  See the License for the
17*e1f63238SAndrew Rist  * specific language governing permissions and limitations
18*e1f63238SAndrew Rist  * under the License.
19*e1f63238SAndrew Rist  *
20*e1f63238SAndrew Rist  *************************************************************/
21*e1f63238SAndrew Rist 
22*e1f63238SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_basic.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <basic/sbx.hxx>
28cdf0e10cSrcweir #include "sbcomp.hxx"
29cdf0e10cSrcweir #include "image.hxx"
30cdf0e10cSrcweir #include <limits>
31cdf0e10cSrcweir #include <com/sun/star/script/ModuleType.hpp>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir // nInc ist die Inkrementgroesse der Puffer
34cdf0e10cSrcweir 
SbiCodeGen(SbModule & r,SbiParser * p,short nInc)35cdf0e10cSrcweir SbiCodeGen::SbiCodeGen( SbModule& r, SbiParser* p, short nInc )
36cdf0e10cSrcweir 		 : rMod( r ), aCode( p, nInc )
37cdf0e10cSrcweir {
38cdf0e10cSrcweir 	pParser = p;
39cdf0e10cSrcweir 	bStmnt = sal_False;
40cdf0e10cSrcweir 	nLine = 0;
41cdf0e10cSrcweir 	nCol = 0;
42cdf0e10cSrcweir 	nForLevel = 0;
43cdf0e10cSrcweir }
44cdf0e10cSrcweir 
GetPC()45cdf0e10cSrcweir sal_uInt32 SbiCodeGen::GetPC()
46cdf0e10cSrcweir {
47cdf0e10cSrcweir 	return aCode.GetSize();
48cdf0e10cSrcweir }
49cdf0e10cSrcweir 
50cdf0e10cSrcweir // Statement merken
51cdf0e10cSrcweir 
Statement()52cdf0e10cSrcweir void SbiCodeGen::Statement()
53cdf0e10cSrcweir {
54cdf0e10cSrcweir 	bStmnt = sal_True;
55cdf0e10cSrcweir 
56cdf0e10cSrcweir 	nLine = pParser->GetLine();
57cdf0e10cSrcweir 	nCol  = pParser->GetCol1();
58cdf0e10cSrcweir 
59cdf0e10cSrcweir 	// #29955 Information der for-Schleifen-Ebene
60cdf0e10cSrcweir 	// in oberen Byte der Spalte speichern
61cdf0e10cSrcweir 	nCol = (nCol & 0xff) + 0x100 * nForLevel;
62cdf0e10cSrcweir }
63cdf0e10cSrcweir 
64cdf0e10cSrcweir // Anfang eines Statements markieren
65cdf0e10cSrcweir 
GenStmnt()66cdf0e10cSrcweir void SbiCodeGen::GenStmnt()
67cdf0e10cSrcweir {
68cdf0e10cSrcweir 	if( bStmnt )
69cdf0e10cSrcweir 	{
70cdf0e10cSrcweir 		bStmnt = sal_False;
71cdf0e10cSrcweir 		Gen( _STMNT, nLine, nCol );
72cdf0e10cSrcweir 	}
73cdf0e10cSrcweir }
74cdf0e10cSrcweir 
75cdf0e10cSrcweir // Die Gen-Routinen returnen den Offset des 1. Operanden,
76cdf0e10cSrcweir // damit Jumps dort ihr Backchain versenken koennen
77cdf0e10cSrcweir 
Gen(SbiOpcode eOpcode)78cdf0e10cSrcweir sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode )
79cdf0e10cSrcweir {
80cdf0e10cSrcweir #ifdef DBG_UTIL
81cdf0e10cSrcweir 	if( eOpcode < SbOP0_START || eOpcode > SbOP0_END )
82cdf0e10cSrcweir 		pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE1" );
83cdf0e10cSrcweir #endif
84cdf0e10cSrcweir 	GenStmnt();
85cdf0e10cSrcweir 	aCode += (sal_uInt8) eOpcode;
86cdf0e10cSrcweir 	return GetPC();
87cdf0e10cSrcweir }
88cdf0e10cSrcweir 
Gen(SbiOpcode eOpcode,sal_uInt32 nOpnd)89cdf0e10cSrcweir sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode, sal_uInt32 nOpnd )
90cdf0e10cSrcweir {
91cdf0e10cSrcweir #ifdef DBG_UTIL
92cdf0e10cSrcweir 	if( eOpcode < SbOP1_START || eOpcode > SbOP1_END )
93cdf0e10cSrcweir 		pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE2" );
94cdf0e10cSrcweir #endif
95cdf0e10cSrcweir 	GenStmnt();
96cdf0e10cSrcweir 	aCode += (sal_uInt8) eOpcode;
97cdf0e10cSrcweir 	sal_uInt32 n = GetPC();
98cdf0e10cSrcweir 	aCode += nOpnd;
99cdf0e10cSrcweir 	return n;
100cdf0e10cSrcweir }
101cdf0e10cSrcweir 
Gen(SbiOpcode eOpcode,sal_uInt32 nOpnd1,sal_uInt32 nOpnd2)102cdf0e10cSrcweir sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode, sal_uInt32 nOpnd1, sal_uInt32 nOpnd2 )
103cdf0e10cSrcweir {
104cdf0e10cSrcweir #ifdef DBG_UTIL
105cdf0e10cSrcweir 	if( eOpcode < SbOP2_START || eOpcode > SbOP2_END )
106cdf0e10cSrcweir 		pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE3" );
107cdf0e10cSrcweir #endif
108cdf0e10cSrcweir 	GenStmnt();
109cdf0e10cSrcweir 	aCode += (sal_uInt8) eOpcode;
110cdf0e10cSrcweir 	sal_uInt32 n = GetPC();
111cdf0e10cSrcweir 	aCode += nOpnd1;
112cdf0e10cSrcweir 	aCode += nOpnd2;
113cdf0e10cSrcweir 	return n;
114cdf0e10cSrcweir }
115cdf0e10cSrcweir 
116cdf0e10cSrcweir // Abspeichern des erzeugten Images im Modul
117cdf0e10cSrcweir 
Save()118cdf0e10cSrcweir void SbiCodeGen::Save()
119cdf0e10cSrcweir {
120cdf0e10cSrcweir 	SbiImage* p = new SbiImage;
121cdf0e10cSrcweir 	rMod.StartDefinitions();
122cdf0e10cSrcweir 	// OPTION BASE-Wert:
123cdf0e10cSrcweir 	p->nDimBase = pParser->nBase;
124cdf0e10cSrcweir 	// OPTION EXPLICIT-Flag uebernehmen
125cdf0e10cSrcweir 	if( pParser->bExplicit )
126cdf0e10cSrcweir 		p->SetFlag( SBIMG_EXPLICIT );
127cdf0e10cSrcweir 
128cdf0e10cSrcweir 	int nIfaceCount = 0;
129cdf0e10cSrcweir 	if( rMod.mnType == com::sun::star::script::ModuleType::CLASS )
130cdf0e10cSrcweir 	{
131cdf0e10cSrcweir                 OSL_TRACE("COdeGen::save() classmodule processing");
132cdf0e10cSrcweir 		rMod.bIsProxyModule = true;
133cdf0e10cSrcweir 		p->SetFlag( SBIMG_CLASSMODULE );
134cdf0e10cSrcweir 		pCLASSFAC->AddClassModule( &rMod );
135cdf0e10cSrcweir 
136cdf0e10cSrcweir 		nIfaceCount = pParser->aIfaceVector.size();
137cdf0e10cSrcweir 		if( !rMod.pClassData )
138cdf0e10cSrcweir 			rMod.pClassData = new SbClassData;
139cdf0e10cSrcweir 		if( nIfaceCount )
140cdf0e10cSrcweir 		{
141cdf0e10cSrcweir 			for( int i = 0 ; i < nIfaceCount ; i++ )
142cdf0e10cSrcweir 			{
143cdf0e10cSrcweir 				const String& rIfaceName = pParser->aIfaceVector[i];
144cdf0e10cSrcweir 				SbxVariable* pIfaceVar = new SbxVariable( SbxVARIANT );
145cdf0e10cSrcweir 				pIfaceVar->SetName( rIfaceName );
146cdf0e10cSrcweir 				SbxArray* pIfaces = rMod.pClassData->mxIfaces;
147cdf0e10cSrcweir 				pIfaces->Insert( pIfaceVar, pIfaces->Count() );
148cdf0e10cSrcweir 			}
149cdf0e10cSrcweir 		}
150cdf0e10cSrcweir 
151cdf0e10cSrcweir 		rMod.pClassData->maRequiredTypes = pParser->aRequiredTypes;
152cdf0e10cSrcweir 	}
153cdf0e10cSrcweir 	else
154cdf0e10cSrcweir 	{
155cdf0e10cSrcweir 		pCLASSFAC->RemoveClassModule( &rMod );
156cdf0e10cSrcweir 		// Only a ClassModule can revert to Normal
157cdf0e10cSrcweir                 if ( rMod.mnType == com::sun::star::script::ModuleType::CLASS )
158cdf0e10cSrcweir 			rMod.mnType = com::sun::star::script::ModuleType::NORMAL;
159cdf0e10cSrcweir 		rMod.bIsProxyModule = false;
160cdf0e10cSrcweir 	}
161cdf0e10cSrcweir 
162cdf0e10cSrcweir 	if( pParser->bText )
163cdf0e10cSrcweir 		p->SetFlag( SBIMG_COMPARETEXT );
164cdf0e10cSrcweir 	// GlobalCode-Flag
165cdf0e10cSrcweir 	if( pParser->HasGlobalCode() )
166cdf0e10cSrcweir 		p->SetFlag( SBIMG_INITCODE );
167cdf0e10cSrcweir 	// Die Entrypoints:
168cdf0e10cSrcweir 	for( SbiSymDef* pDef = pParser->aPublics.First(); pDef;
169cdf0e10cSrcweir 				   pDef = pParser->aPublics.Next() )
170cdf0e10cSrcweir 	{
171cdf0e10cSrcweir 		SbiProcDef* pProc = pDef->GetProcDef();
172cdf0e10cSrcweir 		if( pProc && pProc->IsDefined() )
173cdf0e10cSrcweir 		{
174cdf0e10cSrcweir 			String aProcName = pProc->GetName();
175cdf0e10cSrcweir 			String aIfaceProcName;
176cdf0e10cSrcweir 			String aIfaceName;
177cdf0e10cSrcweir 			sal_uInt16 nPassCount = 1;
178cdf0e10cSrcweir 			if( nIfaceCount )
179cdf0e10cSrcweir 			{
180cdf0e10cSrcweir 				int nPropPrefixFound =
181cdf0e10cSrcweir 					aProcName.Search( String( RTL_CONSTASCII_USTRINGPARAM("Property ") ) );
182cdf0e10cSrcweir 				String aPureProcName = aProcName;
183cdf0e10cSrcweir 				String aPropPrefix;
184cdf0e10cSrcweir 				if( nPropPrefixFound == 0 )
185cdf0e10cSrcweir 				{
186cdf0e10cSrcweir 					aPropPrefix = aProcName.Copy( 0, 13 );		// 13 == Len( "Property ?et " )
187cdf0e10cSrcweir 					aPureProcName = aProcName.Copy( 13 );
188cdf0e10cSrcweir 				}
189cdf0e10cSrcweir 				for( int i = 0 ; i < nIfaceCount ; i++ )
190cdf0e10cSrcweir 				{
191cdf0e10cSrcweir 					const String& rIfaceName = pParser->aIfaceVector[i];
192cdf0e10cSrcweir 					int nFound = aPureProcName.Search( rIfaceName );
193cdf0e10cSrcweir 					if( nFound == 0 && '_' == aPureProcName.GetChar( rIfaceName.Len() ) )
194cdf0e10cSrcweir 					{
195cdf0e10cSrcweir 						if( nPropPrefixFound == 0 )
196cdf0e10cSrcweir 							aIfaceProcName += aPropPrefix;
197cdf0e10cSrcweir 						aIfaceProcName += aPureProcName.Copy( rIfaceName.Len() + 1 );
198cdf0e10cSrcweir 						aIfaceName = rIfaceName;
199cdf0e10cSrcweir 						nPassCount = 2;
200cdf0e10cSrcweir 						break;
201cdf0e10cSrcweir 					}
202cdf0e10cSrcweir 				}
203cdf0e10cSrcweir 			}
204cdf0e10cSrcweir 			SbMethod* pMeth = NULL;
205cdf0e10cSrcweir 			for( sal_uInt16 nPass = 0 ; nPass < nPassCount ; nPass++ )
206cdf0e10cSrcweir 			{
207cdf0e10cSrcweir 				if( nPass == 1 )
208cdf0e10cSrcweir 					aProcName = aIfaceProcName;
209cdf0e10cSrcweir 
210cdf0e10cSrcweir 				PropertyMode ePropMode = pProc->getPropertyMode();
211cdf0e10cSrcweir 				if( ePropMode != PROPERTY_MODE_NONE )
212cdf0e10cSrcweir 				{
213cdf0e10cSrcweir 					SbxDataType ePropType = SbxEMPTY;
214cdf0e10cSrcweir 					switch( ePropMode )
215cdf0e10cSrcweir 					{
216cdf0e10cSrcweir 						case PROPERTY_MODE_GET:
217cdf0e10cSrcweir 							ePropType = pProc->GetType();
218cdf0e10cSrcweir 							break;
219cdf0e10cSrcweir 						case PROPERTY_MODE_LET:
220cdf0e10cSrcweir 						{
221cdf0e10cSrcweir 							// type == type of first parameter
222cdf0e10cSrcweir 							ePropType = SbxVARIANT;		// Default
223cdf0e10cSrcweir 							SbiSymPool* pPool = &pProc->GetParams();
224cdf0e10cSrcweir 							if( pPool->GetSize() > 1 )
225cdf0e10cSrcweir 							{
226cdf0e10cSrcweir 								SbiSymDef* pPar = pPool->Get( 1 );
227cdf0e10cSrcweir 								if( pPar )
228cdf0e10cSrcweir 									ePropType = pPar->GetType();
229cdf0e10cSrcweir 							}
230cdf0e10cSrcweir 							break;
231cdf0e10cSrcweir 						}
232cdf0e10cSrcweir 						case PROPERTY_MODE_SET:
233cdf0e10cSrcweir 							ePropType = SbxOBJECT;
234cdf0e10cSrcweir 							break;
235cdf0e10cSrcweir 						case PROPERTY_MODE_NONE:
236cdf0e10cSrcweir 							DBG_ERROR( "Illegal PropertyMode PROPERTY_MODE_NONE" );
237cdf0e10cSrcweir 							break;
238cdf0e10cSrcweir 					}
239cdf0e10cSrcweir 					String aPropName = pProc->GetPropName();
240cdf0e10cSrcweir 					if( nPass == 1 )
241cdf0e10cSrcweir 						aPropName = aPropName.Copy( aIfaceName.Len() + 1 );
242cdf0e10cSrcweir 					SbProcedureProperty* pProcedureProperty = NULL;
243cdf0e10cSrcweir 					pProcedureProperty = rMod.GetProcedureProperty( aPropName, ePropType );
244cdf0e10cSrcweir 				}
245cdf0e10cSrcweir 				if( nPass == 1 )
246cdf0e10cSrcweir 				{
247cdf0e10cSrcweir 					SbIfaceMapperMethod* pMapperMeth = NULL;
248cdf0e10cSrcweir 					pMapperMeth = rMod.GetIfaceMapperMethod( aProcName, pMeth );
249cdf0e10cSrcweir 				}
250cdf0e10cSrcweir 				else
251cdf0e10cSrcweir 				{
252cdf0e10cSrcweir 					pMeth = rMod.GetMethod( aProcName, pProc->GetType() );
253cdf0e10cSrcweir 
254cdf0e10cSrcweir 					// #110004
255cdf0e10cSrcweir 					if( !pProc->IsPublic() )
256cdf0e10cSrcweir 						pMeth->SetFlag( SBX_PRIVATE );
257cdf0e10cSrcweir 
258cdf0e10cSrcweir 					// Declare? -> Hidden
259cdf0e10cSrcweir 					if( pProc->GetLib().Len() > 0 )
260cdf0e10cSrcweir 						pMeth->SetFlag( SBX_HIDDEN );
261cdf0e10cSrcweir 
262cdf0e10cSrcweir 					pMeth->nStart = pProc->GetAddr();
263cdf0e10cSrcweir 					pMeth->nLine1 = pProc->GetLine1();
264cdf0e10cSrcweir 					pMeth->nLine2 = pProc->GetLine2();
265cdf0e10cSrcweir 					// Die Parameter:
266cdf0e10cSrcweir 					SbxInfo* pInfo = pMeth->GetInfo();
267cdf0e10cSrcweir 					String aHelpFile, aComment;
268cdf0e10cSrcweir 					sal_uIntPtr nHelpId = 0;
269cdf0e10cSrcweir 					if( pInfo )
270cdf0e10cSrcweir 					{
271cdf0e10cSrcweir 						// Die Zusatzdaten retten
272cdf0e10cSrcweir 						aHelpFile = pInfo->GetHelpFile();
273cdf0e10cSrcweir 						aComment  = pInfo->GetComment();
274cdf0e10cSrcweir 						nHelpId	  = pInfo->GetHelpId();
275cdf0e10cSrcweir 					}
276cdf0e10cSrcweir 					// Und die Parameterliste neu aufbauen
277cdf0e10cSrcweir 					pInfo = new SbxInfo( aHelpFile, nHelpId );
278cdf0e10cSrcweir 					pInfo->SetComment( aComment );
279cdf0e10cSrcweir 					SbiSymPool* pPool = &pProc->GetParams();
280cdf0e10cSrcweir 					// Das erste Element ist immer der Funktionswert!
281cdf0e10cSrcweir 					for( sal_uInt16 i = 1; i < pPool->GetSize(); i++ )
282cdf0e10cSrcweir 					{
283cdf0e10cSrcweir 						SbiSymDef* pPar = pPool->Get( i );
284cdf0e10cSrcweir 						SbxDataType t = pPar->GetType();
285cdf0e10cSrcweir 						if( !pPar->IsByVal() )
286cdf0e10cSrcweir 							t = (SbxDataType) ( t | SbxBYREF );
287cdf0e10cSrcweir 						if( pPar->GetDims() )
288cdf0e10cSrcweir 							t = (SbxDataType) ( t | SbxARRAY );
289cdf0e10cSrcweir 						// #33677 Optional-Info durchreichen
290cdf0e10cSrcweir 						sal_uInt16 nFlags = SBX_READ;
291cdf0e10cSrcweir 						if( pPar->IsOptional() )
292cdf0e10cSrcweir 							nFlags |= SBX_OPTIONAL;
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 						pInfo->AddParam( pPar->GetName(), t, nFlags );
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 						sal_uInt32 nUserData = 0;
297cdf0e10cSrcweir 						sal_uInt16 nDefaultId = pPar->GetDefaultId();
298cdf0e10cSrcweir 						if( nDefaultId )
299cdf0e10cSrcweir 							nUserData |= nDefaultId;
300cdf0e10cSrcweir 						if( pPar->IsParamArray() )
301cdf0e10cSrcweir 							nUserData |= PARAM_INFO_PARAMARRAY;
302cdf0e10cSrcweir 						if( pPar->IsWithBrackets() )
303cdf0e10cSrcweir 							nUserData |= PARAM_INFO_WITHBRACKETS;
304cdf0e10cSrcweir 						if( nUserData )
305cdf0e10cSrcweir 						{
306cdf0e10cSrcweir 							SbxParamInfo* pParam = (SbxParamInfo*)pInfo->GetParam( i );
307cdf0e10cSrcweir 							pParam->nUserData = nUserData;
308cdf0e10cSrcweir 						}
309cdf0e10cSrcweir 					}
310cdf0e10cSrcweir 					pMeth->SetInfo( pInfo );
311cdf0e10cSrcweir 				}
312cdf0e10cSrcweir 
313cdf0e10cSrcweir 			}	// for( iPass...
314cdf0e10cSrcweir 		}
315cdf0e10cSrcweir 	}
316cdf0e10cSrcweir 	// Der Code
317cdf0e10cSrcweir 	p->AddCode( aCode.GetBuffer(), aCode.GetSize() );
318cdf0e10cSrcweir 
319cdf0e10cSrcweir 	// Der globale StringPool. 0 ist nicht belegt.
320cdf0e10cSrcweir 	SbiStringPool* pPool = &pParser->aGblStrings;
321cdf0e10cSrcweir 	sal_uInt16 nSize = pPool->GetSize();
322cdf0e10cSrcweir 	p->MakeStrings( nSize );
323cdf0e10cSrcweir 	sal_uInt16 i;
324cdf0e10cSrcweir 	for( i = 1; i <= nSize; i++ )
325cdf0e10cSrcweir 		p->AddString( pPool->Find( i ) );
326cdf0e10cSrcweir 
327cdf0e10cSrcweir 	// Typen einfuegen
328cdf0e10cSrcweir 	sal_uInt16 nCount = pParser->rTypeArray->Count();
329cdf0e10cSrcweir 	for (i = 0; i < nCount; i++)
330cdf0e10cSrcweir 		 p->AddType((SbxObject *)pParser->rTypeArray->Get(i));
331cdf0e10cSrcweir 
332cdf0e10cSrcweir 	// Insert enum objects
333cdf0e10cSrcweir 	nCount = pParser->rEnumArray->Count();
334cdf0e10cSrcweir 	for (i = 0; i < nCount; i++)
335cdf0e10cSrcweir 		 p->AddEnum((SbxObject *)pParser->rEnumArray->Get(i));
336cdf0e10cSrcweir 
337cdf0e10cSrcweir 	if( !p->IsError() )
338cdf0e10cSrcweir 		rMod.pImage = p;
339cdf0e10cSrcweir 	else
340cdf0e10cSrcweir 		delete p;
341cdf0e10cSrcweir 
342cdf0e10cSrcweir 	rMod.EndDefinitions();
343cdf0e10cSrcweir }
344cdf0e10cSrcweir 
345cdf0e10cSrcweir template < class T >
346cdf0e10cSrcweir class PCodeVisitor
347cdf0e10cSrcweir {
348cdf0e10cSrcweir public:
349cdf0e10cSrcweir 	virtual ~PCodeVisitor();
350cdf0e10cSrcweir 
351cdf0e10cSrcweir 	virtual void start( sal_uInt8* pStart ) = 0;
352cdf0e10cSrcweir 	virtual void processOpCode0( SbiOpcode eOp ) = 0;
353cdf0e10cSrcweir 	virtual void processOpCode1( SbiOpcode eOp, T nOp1 ) = 0;
354cdf0e10cSrcweir 	virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 ) = 0;
355cdf0e10cSrcweir 	virtual bool processParams() = 0;
356cdf0e10cSrcweir 	virtual void end() = 0;
357cdf0e10cSrcweir };
358cdf0e10cSrcweir 
~PCodeVisitor()359cdf0e10cSrcweir template <class T> PCodeVisitor< T >::~PCodeVisitor()
360cdf0e10cSrcweir {}
361cdf0e10cSrcweir 
362cdf0e10cSrcweir template <class T>
363cdf0e10cSrcweir class PCodeBufferWalker
364cdf0e10cSrcweir {
365cdf0e10cSrcweir private:
366cdf0e10cSrcweir 	T  m_nBytes;
367cdf0e10cSrcweir 	sal_uInt8* m_pCode;
readParam(sal_uInt8 * & pCode)368cdf0e10cSrcweir 	T readParam( sal_uInt8*& pCode )
369cdf0e10cSrcweir 	{
370cdf0e10cSrcweir 		short nBytes = sizeof( T );
371cdf0e10cSrcweir 		T nOp1=0;
372cdf0e10cSrcweir 		for ( int i=0; i<nBytes; ++i )
373cdf0e10cSrcweir 			nOp1 |= *pCode++ << ( i * 8);
374cdf0e10cSrcweir 		return nOp1;
375cdf0e10cSrcweir 	}
376cdf0e10cSrcweir public:
PCodeBufferWalker(sal_uInt8 * pCode,T nBytes)377cdf0e10cSrcweir 	PCodeBufferWalker( sal_uInt8* pCode, T nBytes ): m_nBytes( nBytes ), m_pCode( pCode )
378cdf0e10cSrcweir 	{
379cdf0e10cSrcweir 	}
visitBuffer(PCodeVisitor<T> & visitor)380cdf0e10cSrcweir 	void visitBuffer( PCodeVisitor< T >& visitor )
381cdf0e10cSrcweir 	{
382cdf0e10cSrcweir 		sal_uInt8* pCode = m_pCode;
383cdf0e10cSrcweir 		if ( !pCode )
384cdf0e10cSrcweir 			return;
385cdf0e10cSrcweir 		sal_uInt8* pEnd = pCode + m_nBytes;
386cdf0e10cSrcweir 		visitor.start( m_pCode );
387cdf0e10cSrcweir 		T nOp1 = 0, nOp2 = 0;
388cdf0e10cSrcweir 		for( ; pCode < pEnd; )
389cdf0e10cSrcweir 		{
390cdf0e10cSrcweir 			SbiOpcode eOp = (SbiOpcode)(*pCode++);
391cdf0e10cSrcweir 
392cdf0e10cSrcweir 			if ( eOp <= SbOP0_END )
393cdf0e10cSrcweir 				visitor.processOpCode0( eOp );
394cdf0e10cSrcweir 			else if( eOp >= SbOP1_START && eOp <= SbOP1_END )
395cdf0e10cSrcweir 			{
396cdf0e10cSrcweir 				if ( visitor.processParams() )
397cdf0e10cSrcweir 					nOp1 = readParam( pCode );
398cdf0e10cSrcweir 				else
399cdf0e10cSrcweir 					pCode += sizeof( T );
400cdf0e10cSrcweir 				visitor.processOpCode1( eOp, nOp1 );
401cdf0e10cSrcweir 			}
402cdf0e10cSrcweir 			else if( eOp >= SbOP2_START && eOp <= SbOP2_END )
403cdf0e10cSrcweir 			{
404cdf0e10cSrcweir 				if ( visitor.processParams() )
405cdf0e10cSrcweir 				{
406cdf0e10cSrcweir 					nOp1 = readParam( pCode );
407cdf0e10cSrcweir 					nOp2 = readParam( pCode );
408cdf0e10cSrcweir 				}
409cdf0e10cSrcweir 				else
410cdf0e10cSrcweir 					pCode += ( sizeof( T ) * 2 );
411cdf0e10cSrcweir 				visitor.processOpCode2( eOp, nOp1, nOp2 );
412cdf0e10cSrcweir 			}
413cdf0e10cSrcweir 		}
414cdf0e10cSrcweir 		visitor.end();
415cdf0e10cSrcweir 	}
416cdf0e10cSrcweir };
417cdf0e10cSrcweir 
418cdf0e10cSrcweir template < class T, class S >
419cdf0e10cSrcweir class OffSetAccumulator : public PCodeVisitor< T >
420cdf0e10cSrcweir {
421cdf0e10cSrcweir 	T m_nNumOp0;
422cdf0e10cSrcweir 	T m_nNumSingleParams;
423cdf0e10cSrcweir 	T m_nNumDoubleParams;
424cdf0e10cSrcweir public:
425cdf0e10cSrcweir 
OffSetAccumulator()426cdf0e10cSrcweir 	OffSetAccumulator() : m_nNumOp0(0), m_nNumSingleParams(0), m_nNumDoubleParams(0){}
start(sal_uInt8 *)427cdf0e10cSrcweir 	virtual void start( sal_uInt8* /*pStart*/ ){}
processOpCode0(SbiOpcode)428cdf0e10cSrcweir 	virtual void processOpCode0( SbiOpcode /*eOp*/ ){ ++m_nNumOp0; }
processOpCode1(SbiOpcode,T)429cdf0e10cSrcweir 	virtual void processOpCode1( SbiOpcode /*eOp*/, T /*nOp1*/ ){  ++m_nNumSingleParams; }
processOpCode2(SbiOpcode,T,T)430cdf0e10cSrcweir 	virtual void processOpCode2( SbiOpcode /*eOp*/, T /*nOp1*/, T /*nOp2*/ ) { ++m_nNumDoubleParams; }
end()431cdf0e10cSrcweir 	virtual void end(){}
offset()432cdf0e10cSrcweir 	S offset()
433cdf0e10cSrcweir 	{
434cdf0e10cSrcweir 		T result = 0 ;
435cdf0e10cSrcweir 		static const S max = std::numeric_limits< S >::max();
436cdf0e10cSrcweir 		result = m_nNumOp0 + ( ( sizeof(S) + 1 ) * m_nNumSingleParams ) + ( (( sizeof(S) * 2 )+ 1 )  * m_nNumDoubleParams );
437cdf0e10cSrcweir 		if ( result > max )
438cdf0e10cSrcweir 			return max;
439cdf0e10cSrcweir 
440cdf0e10cSrcweir 		return static_cast<S>(result);
441cdf0e10cSrcweir 	}
processParams()442cdf0e10cSrcweir    virtual bool processParams(){ return false; }
443cdf0e10cSrcweir };
444cdf0e10cSrcweir 
445cdf0e10cSrcweir 
446cdf0e10cSrcweir 
447cdf0e10cSrcweir template < class T, class S >
448cdf0e10cSrcweir 
449cdf0e10cSrcweir class BufferTransformer : public PCodeVisitor< T >
450cdf0e10cSrcweir {
451cdf0e10cSrcweir 	sal_uInt8* m_pStart;
452cdf0e10cSrcweir 	SbiBuffer m_ConvertedBuf;
453cdf0e10cSrcweir public:
BufferTransformer()454cdf0e10cSrcweir 	BufferTransformer():m_pStart(NULL), m_ConvertedBuf( NULL, 1024 ) {}
start(sal_uInt8 * pStart)455cdf0e10cSrcweir 	virtual void start( sal_uInt8* pStart ){ m_pStart = pStart; }
processOpCode0(SbiOpcode eOp)456cdf0e10cSrcweir 	virtual void processOpCode0( SbiOpcode eOp )
457cdf0e10cSrcweir 	{
458cdf0e10cSrcweir 		m_ConvertedBuf += (sal_uInt8)eOp;
459cdf0e10cSrcweir 	}
processOpCode1(SbiOpcode eOp,T nOp1)460cdf0e10cSrcweir 	virtual void processOpCode1( SbiOpcode eOp, T nOp1 )
461cdf0e10cSrcweir 	{
462cdf0e10cSrcweir 		m_ConvertedBuf += (sal_uInt8)eOp;
463cdf0e10cSrcweir 		switch( eOp )
464cdf0e10cSrcweir 		{
465cdf0e10cSrcweir 			case _JUMP:
466cdf0e10cSrcweir 			case _JUMPT:
467cdf0e10cSrcweir 			case _JUMPF:
468cdf0e10cSrcweir 			case _GOSUB:
469cdf0e10cSrcweir 			case _CASEIS:
470cdf0e10cSrcweir 			case _RETURN:
471cdf0e10cSrcweir 			case _ERRHDL:
472cdf0e10cSrcweir 			case _TESTFOR:
473cdf0e10cSrcweir 				nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
474cdf0e10cSrcweir 				break;
475cdf0e10cSrcweir 			case _RESUME:
476cdf0e10cSrcweir 				if ( nOp1 > 1 )
477cdf0e10cSrcweir 					nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
478cdf0e10cSrcweir 				break;
479cdf0e10cSrcweir 			default:
480cdf0e10cSrcweir 				break; //
481cdf0e10cSrcweir 
482cdf0e10cSrcweir 		}
483cdf0e10cSrcweir 		m_ConvertedBuf += (S)nOp1;
484cdf0e10cSrcweir 	}
processOpCode2(SbiOpcode eOp,T nOp1,T nOp2)485cdf0e10cSrcweir 	virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 )
486cdf0e10cSrcweir 	{
487cdf0e10cSrcweir 		m_ConvertedBuf += (sal_uInt8)eOp;
488cdf0e10cSrcweir 		if ( eOp == _CASEIS )
489cdf0e10cSrcweir 				if ( nOp1 )
490cdf0e10cSrcweir 					nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
491cdf0e10cSrcweir 		m_ConvertedBuf += (S)nOp1;
492cdf0e10cSrcweir 		m_ConvertedBuf += (S)nOp2;
493cdf0e10cSrcweir 
494cdf0e10cSrcweir 	}
processParams()495cdf0e10cSrcweir 	virtual bool processParams(){ return true; }
end()496cdf0e10cSrcweir 	virtual void end() {}
497cdf0e10cSrcweir 	// yeuch, careful here, you can only call
498cdf0e10cSrcweir 	// GetBuffer on the returned SbiBuffer once, also
499cdf0e10cSrcweir 	// you (as the caller) get to own the memory
buffer()500cdf0e10cSrcweir 	SbiBuffer& buffer()
501cdf0e10cSrcweir 	{
502cdf0e10cSrcweir 		return m_ConvertedBuf;
503cdf0e10cSrcweir 	}
convertBufferOffSet(sal_uInt8 * pStart,T nOp1)504cdf0e10cSrcweir 	static S convertBufferOffSet( sal_uInt8* pStart, T nOp1 )
505cdf0e10cSrcweir 	{
506cdf0e10cSrcweir 		PCodeBufferWalker< T > aBuff( pStart, nOp1);
507cdf0e10cSrcweir 		OffSetAccumulator< T, S > aVisitor;
508cdf0e10cSrcweir 		aBuff.visitBuffer( aVisitor );
509cdf0e10cSrcweir 		return aVisitor.offset();
510cdf0e10cSrcweir 	}
511cdf0e10cSrcweir };
512cdf0e10cSrcweir 
513cdf0e10cSrcweir sal_uInt32
calcNewOffSet(sal_uInt8 * pCode,sal_uInt16 nOffset)514cdf0e10cSrcweir SbiCodeGen::calcNewOffSet( sal_uInt8* pCode, sal_uInt16 nOffset )
515cdf0e10cSrcweir {
516cdf0e10cSrcweir 	return BufferTransformer< sal_uInt16, sal_uInt32 >::convertBufferOffSet( pCode, nOffset );
517cdf0e10cSrcweir }
518cdf0e10cSrcweir 
519cdf0e10cSrcweir sal_uInt16
calcLegacyOffSet(sal_uInt8 * pCode,sal_uInt32 nOffset)520cdf0e10cSrcweir SbiCodeGen::calcLegacyOffSet( sal_uInt8* pCode, sal_uInt32 nOffset )
521cdf0e10cSrcweir {
522cdf0e10cSrcweir 	return BufferTransformer< sal_uInt32, sal_uInt16 >::convertBufferOffSet( pCode, nOffset );
523cdf0e10cSrcweir }
524cdf0e10cSrcweir 
525cdf0e10cSrcweir template <class T, class S>
526cdf0e10cSrcweir void
convert()527cdf0e10cSrcweir PCodeBuffConvertor<T,S>::convert()
528cdf0e10cSrcweir {
529cdf0e10cSrcweir 	PCodeBufferWalker< T > aBuf( m_pStart, m_nSize );
530cdf0e10cSrcweir 	BufferTransformer< T, S > aTrnsfrmer;
531cdf0e10cSrcweir 	aBuf.visitBuffer( aTrnsfrmer );
532cdf0e10cSrcweir 	m_pCnvtdBuf = (sal_uInt8*)aTrnsfrmer.buffer().GetBuffer();
533cdf0e10cSrcweir 	m_nCnvtdSize = static_cast<S>( aTrnsfrmer.buffer().GetSize() );
534cdf0e10cSrcweir }
535cdf0e10cSrcweir 
536cdf0e10cSrcweir template class PCodeBuffConvertor< sal_uInt16, sal_uInt32 >;
537cdf0e10cSrcweir template class PCodeBuffConvertor< sal_uInt32, sal_uInt16 >;
538