merge the formfield patch from ooo-build
[ooovba.git] / bridges / source / cpp_uno / gcc3_linux_m68k / uno2cpp.cxx
blob951fc7f9711cb88a05afd5898600cf1afd19c669
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: uno2cpp.cxx,v $
10 * $Revision: 1.2 $
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 #include <malloc.h>
32 #include <rtl/alloc.h>
34 #include <com/sun/star/uno/genfunc.hxx>
35 #include "com/sun/star/uno/RuntimeException.hpp"
36 #include <uno/data.h>
38 #include <bridges/cpp_uno/shared/bridge.hxx>
39 #include <bridges/cpp_uno/shared/types.hxx>
40 #include <bridges/cpp_uno/shared/unointerfaceproxy.hxx>
41 #include <bridges/cpp_uno/shared/vtables.hxx>
43 #include "share.hxx"
45 #include <stdio.h>
46 #include <string.h>
48 using namespace ::rtl;
49 using namespace ::com::sun::star::uno;
51 void MapReturn(long d0, long d1, typelib_TypeClass eReturnType, long *pRegisterReturn)
53 register float fret asm("fp0");
54 register double dret asm("fp0");
56 switch( eReturnType )
58 case typelib_TypeClass_HYPER:
59 case typelib_TypeClass_UNSIGNED_HYPER:
60 pRegisterReturn[1] = d1;
61 case typelib_TypeClass_LONG:
62 case typelib_TypeClass_UNSIGNED_LONG:
63 case typelib_TypeClass_ENUM:
64 case typelib_TypeClass_CHAR:
65 case typelib_TypeClass_SHORT:
66 case typelib_TypeClass_UNSIGNED_SHORT:
67 case typelib_TypeClass_BOOLEAN:
68 case typelib_TypeClass_BYTE:
69 pRegisterReturn[0] = d0;
70 break;
71 case typelib_TypeClass_FLOAT:
72 *(float*)pRegisterReturn = fret;
73 break;
74 case typelib_TypeClass_DOUBLE:
75 *(double*)pRegisterReturn = dret;
76 break;
77 default:
78 break;
82 namespace
84 //================================================================
86 void callVirtualMethod(
87 void * pThis,
88 sal_Int32 nVtableIndex,
89 void * pRegisterReturn,
90 typelib_TypeClass eReturnType,
91 sal_uInt32 *pStack,
92 sal_uInt32 nStack) __attribute__((noinline));
94 void callVirtualMethod(
95 void * pThis,
96 sal_Int32 nVtableIndex,
97 void * pRegisterReturn,
98 typelib_TypeClass eReturnType,
99 sal_uInt32 *pStack,
100 sal_uInt32 nStack)
102 // never called
103 if (! pThis)
104 CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
106 if ( nStack )
108 // m68k stack is either 2 or 4 bytes aligned, doesn't really matter as
109 // we deal in 4 byte units anyway
110 sal_uInt32 nStackBytes = nStack * sizeof(sal_uInt32);
111 sal_uInt32 *stack = (sal_uInt32 *) __builtin_alloca( nStackBytes );
112 memcpy( stack, pStack, nStackBytes );
115 #ifdef CMC_DEBUG
116 // Let's figure out what is really going on here
118 fprintf( stderr, "\nStack (%d): ", nStack );
119 for ( unsigned int i = 0; i < nStack; ++i )
120 fprintf( stderr, "0x%lx, ", pStack[i] );
121 fprintf( stderr, "\n" );
122 fprintf( stderr, "pRegisterReturn is %p\n", pRegisterReturn);
124 #endif
126 sal_uInt32 pMethod = *((sal_uInt32*)pThis);
127 pMethod += 4 * nVtableIndex;
128 pMethod = *((sal_uInt32 *)pMethod);
130 typedef long (*FunctionCall )();
131 FunctionCall pFunc = (FunctionCall)pMethod;
133 //stick the return area into r8 for big struct returning
134 asm volatile("movel %0,%%a1" : : "m"(pRegisterReturn) : );
136 long d0 = (*pFunc)();
138 register long d1 asm("d1");
140 MapReturn(d0, d1, eReturnType, (long*)pRegisterReturn);
144 #define INSERT_INT32( pSV, pDS )\
145 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
147 #define INSERT_INT64( pSV, pDS )\
148 INSERT_INT32( pSV, pDS ) \
149 INSERT_INT32( ((sal_uInt32*)pSV)+1, pDS )
151 #define INSERT_FLOAT( pSV, pDS ) \
152 INSERT_INT32( pSV, pDS )
154 #define INSERT_DOUBLE( pSV, pDS ) \
155 INSERT_INT64( pSV, pDS )
157 #define INSERT_INT16( pSV, pDS ) \
158 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
160 #define INSERT_INT8( pSV, pDS ) \
161 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
163 namespace {
164 //=======================================================================
165 static void cpp_call(
166 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
167 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
168 typelib_TypeDescriptionReference * pReturnTypeRef,
169 sal_Int32 nParams, typelib_MethodParameter * pParams,
170 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
173 // max space for: [complex ret ptr], values|ptr ...
174 sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca(
175 sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
176 sal_uInt32 * pStackStart = pStack;
178 // return
179 typelib_TypeDescription * pReturnTypeDescr = 0;
180 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
181 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
183 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
185 if (pReturnTypeDescr)
188 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
190 pCppReturn = pUnoReturn; // direct way for simple types
192 else
194 // complex return via ptr
195 pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
196 ? __builtin_alloca( pReturnTypeDescr->nSize )
197 : pUnoReturn); // direct way
199 // INSERT_INT32( &pCppReturn, pStack );
202 // push this
203 void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
204 + aVtableSlot.offset;
205 INSERT_INT32( &pAdjustedThisPtr, pStack );
207 // stack space
208 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
209 // args
210 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
211 // indizes of values this have to be converted (interface conversion cpp<=>uno)
212 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
213 // type descriptions for reconversions
214 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
216 sal_Int32 nTempIndizes = 0;
218 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
220 const typelib_MethodParameter & rParam = pParams[nPos];
221 typelib_TypeDescription * pParamTypeDescr = 0;
222 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
224 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
226 // uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos],
227 uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos],
228 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
230 switch (pParamTypeDescr->eTypeClass)
232 case typelib_TypeClass_HYPER:
233 case typelib_TypeClass_UNSIGNED_HYPER:
234 #ifdef CMC_DEBUG
235 fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]);
236 #endif
237 INSERT_INT64( pCppArgs[nPos], pStack );
238 break;
239 case typelib_TypeClass_LONG:
240 case typelib_TypeClass_UNSIGNED_LONG:
241 case typelib_TypeClass_ENUM:
242 #ifdef CMC_DEBUG
243 fprintf(stderr, "long is %x\n", pCppArgs[nPos]);
244 #endif
245 INSERT_INT32( pCppArgs[nPos], pStack );
246 break;
247 case typelib_TypeClass_SHORT:
248 case typelib_TypeClass_CHAR:
249 case typelib_TypeClass_UNSIGNED_SHORT:
250 INSERT_INT16( pCppArgs[nPos], pStack );
251 break;
252 case typelib_TypeClass_BOOLEAN:
253 case typelib_TypeClass_BYTE:
254 INSERT_INT8( pCppArgs[nPos], pStack );
255 break;
256 case typelib_TypeClass_FLOAT:
257 INSERT_FLOAT( pCppArgs[nPos], pStack );
258 break;
259 case typelib_TypeClass_DOUBLE:
260 INSERT_DOUBLE( pCppArgs[nPos], pStack );
261 break;
263 // no longer needed
264 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
266 else // ptr to complex value | ref
268 if (! rParam.bIn) // is pure out
270 // cpp out is constructed mem, uno out is not!
271 uno_constructData(
272 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
273 pParamTypeDescr );
274 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
275 // will be released at reconversion
276 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
278 // is in/inout
279 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
281 uno_copyAndConvertData(
282 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
283 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
285 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
286 // will be released at reconversion
287 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
289 else // direct way
291 pCppArgs[nPos] = pUnoArgs[nPos];
292 // no longer needed
293 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
295 INSERT_INT32( &(pCppArgs[nPos]), pStack );
301 callVirtualMethod(
302 pAdjustedThisPtr, aVtableSlot.index,
303 pCppReturn, pReturnTypeDescr->eTypeClass,
304 pStackStart,
305 (pStack - pStackStart));
307 // NO exception occured...
308 *ppUnoExc = 0;
310 // reconvert temporary params
311 for ( ; nTempIndizes--; )
313 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
314 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
316 if (pParams[nIndex].bIn)
318 if (pParams[nIndex].bOut) // inout
320 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
321 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
322 pThis->getBridge()->getCpp2Uno() );
325 else // pure out
327 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
328 pThis->getBridge()->getCpp2Uno() );
330 // destroy temp cpp param => cpp: every param was constructed
331 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
333 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
335 // return value
336 if (pCppReturn && pUnoReturn != pCppReturn)
338 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
339 pThis->getBridge()->getCpp2Uno() );
340 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
343 catch (...)
345 // fill uno exception
346 fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
348 // temporary params
349 for ( ; nTempIndizes--; )
351 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
352 // destroy temp cpp param => cpp: every param was constructed
353 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
354 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
357 // return type
358 if (pReturnTypeDescr)
359 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
364 namespace bridges { namespace cpp_uno { namespace shared {
366 void unoInterfaceProxyDispatch(
367 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
368 void * pReturn, void * pArgs[], uno_Any ** ppException )
370 // is my surrogate
371 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
372 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
373 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
375 switch (pMemberDescr->eTypeClass)
377 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
379 // determine vtable call index
380 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
381 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
383 VtableSlot aVtableSlot(
384 getVtableSlot(
385 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>
386 (pMemberDescr)));
388 if (pReturn)
390 // dependent dispatch
391 cpp_call(
392 pThis, aVtableSlot,
393 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
394 0, 0, // no params
395 pReturn, pArgs, ppException );
397 else
399 // is SET
400 typelib_MethodParameter aParam;
401 aParam.pTypeRef =
402 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
403 aParam.bIn = sal_True;
404 aParam.bOut = sal_False;
406 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
407 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
408 typelib_typedescriptionreference_new(
409 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
411 // dependent dispatch
412 aVtableSlot.index += 1;
413 cpp_call(
414 pThis, aVtableSlot, // get, then set method
415 pReturnTypeRef,
416 1, &aParam,
417 pReturn, pArgs, ppException );
419 typelib_typedescriptionreference_release( pReturnTypeRef );
422 break;
424 case typelib_TypeClass_INTERFACE_METHOD:
426 // determine vtable call index
427 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
428 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
430 VtableSlot aVtableSlot(
431 getVtableSlot(
432 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>
433 (pMemberDescr)));
435 switch (aVtableSlot.index)
437 // standard calls
438 case 1: // acquire uno interface
439 (*pUnoI->acquire)( pUnoI );
440 *ppException = 0;
441 break;
442 case 2: // release uno interface
443 (*pUnoI->release)( pUnoI );
444 *ppException = 0;
445 break;
446 case 0: // queryInterface() opt
448 typelib_TypeDescription * pTD = 0;
449 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
450 if (pTD)
452 uno_Interface * pInterface = 0;
453 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
454 pThis->getBridge()->getUnoEnv(),
455 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
457 if (pInterface)
459 ::uno_any_construct(
460 reinterpret_cast< uno_Any * >( pReturn ),
461 &pInterface, pTD, 0 );
462 (*pInterface->release)( pInterface );
463 TYPELIB_DANGER_RELEASE( pTD );
464 *ppException = 0;
465 break;
467 TYPELIB_DANGER_RELEASE( pTD );
469 } // else perform queryInterface()
470 default:
471 // dependent dispatch
472 cpp_call(
473 pThis, aVtableSlot,
474 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
475 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
476 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
477 pReturn, pArgs, ppException );
479 break;
481 default:
483 ::com::sun::star::uno::RuntimeException aExc(
484 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
485 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
487 Type const & rExcType = ::getCppuType( &aExc );
488 // binary identical null reference
489 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
494 } } }
496 /* vi:set tabstop=4 shiftwidth=4 expandtab: */