nss: upgrade to release 3.73
[LibreOffice.git] / bridges / source / cpp_uno / gcc3_linux_arm / uno2cpp.cxx
blobb71ab2acbb0b89c08eb869a7c3dc78a238f7c1e4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <malloc.h>
21 #include <rtl/alloc.h>
23 #include <com/sun/star/uno/genfunc.hxx>
24 #include <com/sun/star/uno/Exception.hpp>
25 #include "com/sun/star/uno/RuntimeException.hpp"
26 #include <o3tl/runtimetooustring.hxx>
27 #include <uno/data.h>
29 #include <bridge.hxx>
30 #include <types.hxx>
31 #include <unointerfaceproxy.hxx>
32 #include <vtables.hxx>
34 #include "share.hxx"
36 #include <exception>
37 #include <stdio.h>
38 #include <string.h>
39 #include <typeinfo>
42 * Based on http://gcc.gnu.org/PR41443
43 * References to __SOFTFP__ are incorrect for EABI; the __SOFTFP__ code
44 * should be used for *soft-float ABI* whether or not VFP is enabled,
45 * and __SOFTFP__ does specifically mean soft-float not soft-float ABI.
47 * Changing the conditionals to __SOFTFP__ || __ARM_EABI__ then
48 * -mfloat-abi=softfp should work. -mfloat-abi=hard won't; that would
49 * need both a new macro to identify the hard-VFP ABI.
51 #if !defined(__ARM_EABI__) && !defined(__SOFTFP__)
52 #error Not Implemented
55 some possibly handy code to detect that we have VFP registers
58 #include <sys/types.h>
59 #include <sys/stat.h>
60 #include <fcntl.h>
61 #include <unistd.h>
62 #include <elf.h>
64 #define HWCAP_ARM_VFP 64
66 int hasVFP()
68 int fd = open ("/proc/self/auxv", O_RDONLY);
69 if (fd == -1)
70 return -1;
72 int ret = -1;
74 Elf32_auxv_t buf[128];
75 ssize_t n;
76 while ((ret == -1) && ((n = read(fd, buf, sizeof (buf))) > 0))
78 for (int i = 0; i < 128; ++i)
80 if (buf[i].a_type == AT_HWCAP)
82 ret = (buf[i].a_un.a_val & HWCAP_ARM_VFP) ? true : false;
83 break;
85 else if (buf[i].a_type == AT_NULL)
87 ret = -2;
88 break;
93 close (fd);
94 return ret;
97 #endif
99 using namespace ::com::sun::star::uno;
101 namespace arm
103 bool is_complex_struct(const typelib_TypeDescription * type)
105 const typelib_CompoundTypeDescription * p
106 = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
107 for (sal_Int32 i = 0; i < p->nMembers; ++i)
109 if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT ||
110 p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
112 typelib_TypeDescription * t = 0;
113 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
114 bool b = is_complex_struct(t);
115 TYPELIB_DANGER_RELEASE(t);
116 if (b) {
117 return true;
120 else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
121 return true;
123 if (p->pBaseTypeDescription != 0)
124 return is_complex_struct(&p->pBaseTypeDescription->aBase);
125 return false;
128 #ifdef __ARM_PCS_VFP
129 bool is_float_only_struct(const typelib_TypeDescription * type)
131 const typelib_CompoundTypeDescription * p
132 = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
133 for (sal_Int32 i = 0; i < p->nMembers; ++i)
135 if (p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_FLOAT &&
136 p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_DOUBLE)
137 return false;
139 return true;
141 #endif
142 bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
144 if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
145 return false;
146 else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
148 typelib_TypeDescription * pTypeDescr = 0;
149 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
151 //A Composite Type not larger than 4 bytes is returned in r0
152 bool bRet = pTypeDescr->nSize > 4 || is_complex_struct(pTypeDescr);
154 #ifdef __ARM_PCS_VFP
155 // In the VFP ABI, structs with only float/double values that fit in
156 // 16 bytes are returned in registers
157 if( pTypeDescr->nSize <= 16 && is_float_only_struct(pTypeDescr))
158 bRet = false;
159 #endif
161 TYPELIB_DANGER_RELEASE( pTypeDescr );
162 return bRet;
164 return true;
168 void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference * pReturnType, sal_uInt32* pRegisterReturn)
170 switch( pReturnType->eTypeClass )
172 case typelib_TypeClass_HYPER:
173 case typelib_TypeClass_UNSIGNED_HYPER:
174 pRegisterReturn[1] = r1;
175 [[fallthrough]];
176 case typelib_TypeClass_LONG:
177 case typelib_TypeClass_UNSIGNED_LONG:
178 case typelib_TypeClass_ENUM:
179 case typelib_TypeClass_CHAR:
180 case typelib_TypeClass_SHORT:
181 case typelib_TypeClass_UNSIGNED_SHORT:
182 case typelib_TypeClass_BOOLEAN:
183 case typelib_TypeClass_BYTE:
184 pRegisterReturn[0] = r0;
185 break;
186 case typelib_TypeClass_FLOAT:
187 #if !defined(__ARM_PCS_VFP) && (defined(__ARM_EABI__) || defined(__SOFTFP__))
188 pRegisterReturn[0] = r0;
189 #else
190 register float fret asm("s0");
191 *(float*)pRegisterReturn = fret;
192 #endif
193 break;
194 case typelib_TypeClass_DOUBLE:
195 #if !defined(__ARM_PCS_VFP) && (defined(__ARM_EABI__) || defined(__SOFTFP__))
196 pRegisterReturn[1] = r1;
197 pRegisterReturn[0] = r0;
198 #else
199 register double dret asm("d0");
200 *(double*)pRegisterReturn = dret;
201 #endif
202 break;
203 case typelib_TypeClass_STRUCT:
204 case typelib_TypeClass_EXCEPTION:
206 if (!arm::return_in_hidden_param(pReturnType))
207 pRegisterReturn[0] = r0;
208 break;
210 default:
211 break;
215 namespace
218 void callVirtualMethod(
219 void * pThis,
220 sal_Int32 nVtableIndex,
221 void * pRegisterReturn,
222 typelib_TypeDescriptionReference * pReturnType,
223 sal_uInt32 *pStack,
224 sal_uInt32 nStack,
225 sal_uInt32 *pGPR,
226 sal_uInt32 nGPR,
227 double *pFPR) __attribute__((noinline));
229 void callVirtualMethod(
230 void * pThis,
231 sal_Int32 nVtableIndex,
232 void * pRegisterReturn,
233 typelib_TypeDescriptionReference * pReturnType,
234 sal_uInt32 *pStack,
235 sal_uInt32 nStack,
236 sal_uInt32 *pGPR,
237 sal_uInt32 nGPR,
238 double *pFPR)
240 // never called
241 if (! pThis)
242 CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
244 if ( nStack )
246 // 8-bytes aligned
247 sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 8;
248 sal_uInt32 *stack = (sal_uInt32 *) __builtin_alloca( nStackBytes );
249 memcpy( stack, pStack, nStackBytes );
252 // Should not happen, but...
253 if ( nGPR > arm::MAX_GPR_REGS )
254 nGPR = arm::MAX_GPR_REGS;
256 sal_uInt32 pMethod = *((sal_uInt32*)pThis);
257 pMethod += 4 * nVtableIndex;
258 pMethod = *((sal_uInt32 *)pMethod);
260 //Return registers
261 sal_uInt32 r0;
262 sal_uInt32 r1;
264 __asm__ __volatile__ (
265 //Fill in general purpose register arguments
266 "ldr r4, %[pgpr]\n\t"
267 "ldmia r4, {r0-r3}\n\t"
269 #ifdef __ARM_PCS_VFP
270 //Fill in VFP register arguments as double precision values
271 "ldr r4, %[pfpr]\n\t"
272 "vldmia r4, {d0-d7}\n\t"
273 #endif
274 //Make the call
275 "ldr r5, %[pmethod]\n\t"
276 #ifndef __ARM_ARCH_4T__
277 "blx r5\n\t"
278 #else
279 "mov lr, pc ; bx r5\n\t"
280 #endif
282 //Fill in return values
283 "mov %[r0], r0\n\t"
284 "mov %[r1], r1\n\t"
285 : [r0]"=r" (r0), [r1]"=r" (r1)
286 : [pmethod]"m" (pMethod), [pgpr]"m" (pGPR), [pfpr]"m" (pFPR)
287 : "r0", "r1", "r2", "r3", "r4", "r5");
289 MapReturn(r0, r1, pReturnType, (sal_uInt32*)pRegisterReturn);
293 #define INSERT_INT32( pSV, nr, pGPR, pDS ) \
294 if ( nr < arm::MAX_GPR_REGS ) \
295 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
296 else \
297 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
299 #ifdef __ARM_EABI__
300 #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart ) \
301 if ( (nr < arm::MAX_GPR_REGS) && (nr % 2) ) \
303 ++nr; \
305 if ( nr < arm::MAX_GPR_REGS ) \
307 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
308 pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \
310 else \
312 if ( (pDS - pStart) % 2) \
314 ++pDS; \
316 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \
317 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \
319 #else
320 #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart ) \
321 INSERT_INT32( pSV, nr, pGPR, pDS ) \
322 INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS )
323 #endif
325 #ifdef __ARM_PCS_VFP
326 // Since single and double arguments share the same register bank the filling of the
327 // registers is not always linear. Single values go to the first available single register,
328 // while doubles need to have an 8 byte alignment, so only go into double registers starting
329 // at every other single register. For ex a float, double, float sequence will fill registers
330 // s0, d1, and s1, actually corresponding to the linear order s0,s1, d1.
332 // These use the single/double register array and counters and ignore the pGPR argument
333 // nSR and nDR are the number of single and double precision registers that are no longer
334 // available
335 #define INSERT_FLOAT( pSV, nr, pGPR, pDS ) \
336 if (nSR % 2 == 0) {\
337 nSR = 2*nDR; \
339 if ( nSR < arm::MAX_FPR_REGS*2 ) {\
340 pSPR[nSR++] = *reinterpret_cast<float *>( pSV ); \
341 if ((nSR % 2 == 1) && (nSR > 2*nDR)) {\
342 nDR++; \
345 else \
347 *pDS++ = *reinterpret_cast<float *>( pSV );\
349 #define INSERT_DOUBLE( pSV, nr, pGPR, pDS, pStart ) \
350 if ( nDR < arm::MAX_FPR_REGS ) { \
351 pFPR[nDR++] = *reinterpret_cast<double *>( pSV ); \
353 else\
355 if ( (pDS - pStart) % 2) \
357 ++pDS; \
359 *(double *)pDS = *reinterpret_cast<double *>( pSV );\
360 pDS += 2;\
362 #else
363 #define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \
364 INSERT_INT32( pSV, nr, pGPR, pDS )
366 #define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart ) \
367 INSERT_INT64( pSV, nr, pGPR, pDS, pStart )
368 #endif
370 #define INSERT_INT16( pSV, nr, pGPR, pDS ) \
371 if ( nr < arm::MAX_GPR_REGS ) \
372 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
373 else \
374 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
376 #define INSERT_INT8( pSV, nr, pGPR, pDS ) \
377 if ( nr < arm::MAX_GPR_REGS ) \
378 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
379 else \
380 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
382 namespace {
384 static void cpp_call(
385 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
386 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
387 typelib_TypeDescriptionReference * pReturnTypeRef,
388 sal_Int32 nParams, typelib_MethodParameter * pParams,
389 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
391 // max space for: [complex ret ptr], values|ptr ...
392 sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca(
393 sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
394 sal_uInt32 * pStackStart = pStack;
396 sal_uInt32 pGPR[arm::MAX_GPR_REGS];
397 sal_uInt32 nGPR = 0;
399 // storage and counters for single and double precision VFP registers
400 double pFPR[arm::MAX_FPR_REGS];
401 #ifdef __ARM_PCS_VFP
402 sal_uInt32 nDR = 0;
403 float *pSPR = reinterpret_cast< float *>(&pFPR);
404 sal_uInt32 nSR = 0;
405 #endif
407 // return
408 typelib_TypeDescription * pReturnTypeDescr = 0;
409 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
410 assert(pReturnTypeDescr);
412 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
414 if (pReturnTypeDescr)
416 bool bSimpleReturn = !arm::return_in_hidden_param( pReturnTypeRef );
418 if (bSimpleReturn)
419 pCppReturn = pUnoReturn; // direct way for simple types
420 else
422 // complex return via ptr
423 pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
424 ? __builtin_alloca( pReturnTypeDescr->nSize )
425 : pUnoReturn); // direct way
427 INSERT_INT32( &pCppReturn, nGPR, pGPR, pStack );
430 // push this
431 void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
432 + aVtableSlot.offset;
433 INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack );
435 // stack space
436 static_assert(sizeof(void *) == sizeof(sal_Int32), "### unexpected size!");
437 // args
438 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
439 // indices of values this have to be converted (interface conversion cpp<=>uno)
440 sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams);
441 // type descriptions for reconversions
442 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
444 sal_Int32 nTempIndices = 0;
446 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
448 const typelib_MethodParameter & rParam = pParams[nPos];
449 typelib_TypeDescription * pParamTypeDescr = 0;
450 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
452 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
454 // uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos],
455 uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos],
456 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
458 switch (pParamTypeDescr->eTypeClass)
460 case typelib_TypeClass_HYPER:
461 case typelib_TypeClass_UNSIGNED_HYPER:
462 #if OSL_DEBUG_LEVEL > 2
463 fprintf(stderr, "hyper is %p\n", pCppArgs[nPos]);
464 #endif
465 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart );
466 break;
467 case typelib_TypeClass_LONG:
468 case typelib_TypeClass_UNSIGNED_LONG:
469 case typelib_TypeClass_ENUM:
470 #if OSL_DEBUG_LEVEL > 2
471 fprintf(stderr, "long is %p\n", pCppArgs[nPos]);
472 #endif
473 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
474 break;
475 case typelib_TypeClass_SHORT:
476 case typelib_TypeClass_CHAR:
477 case typelib_TypeClass_UNSIGNED_SHORT:
478 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
479 break;
480 case typelib_TypeClass_BOOLEAN:
481 case typelib_TypeClass_BYTE:
482 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
483 break;
484 case typelib_TypeClass_FLOAT:
485 INSERT_FLOAT( pCppArgs[nPos], nGPR, pGPR, pStack );
486 break;
487 case typelib_TypeClass_DOUBLE:
488 INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart );
489 break;
490 default:
491 break;
493 // no longer needed
494 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
496 else // ptr to complex value | ref
498 if (! rParam.bIn) // is pure out
500 // cpp out is constructed mem, uno out is not!
501 uno_constructData(
502 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
503 pParamTypeDescr );
504 pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
505 // will be released at reconversion
506 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
508 // is in/inout
509 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
511 uno_copyAndConvertData(
512 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
513 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
515 pTempIndices[nTempIndices] = nPos; // has to be reconverted
516 // will be released at reconversion
517 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
519 else // direct way
521 pCppArgs[nPos] = pUnoArgs[nPos];
522 // no longer needed
523 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
525 INSERT_INT32( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
531 try {
532 callVirtualMethod(
533 pAdjustedThisPtr, aVtableSlot.index,
534 pCppReturn, pReturnTypeRef,
535 pStackStart,
536 (pStack - pStackStart),
537 pGPR, nGPR,
538 pFPR);
539 } catch (css::uno::Exception &) {
540 throw;
541 } catch (std::exception & e) {
542 throw css::uno::RuntimeException(
543 "C++ code threw " + o3tl::runtimeToOUString(typeid(e).name()) + ": "
544 + o3tl::runtimeToOUString(e.what()));
545 } catch (...) {
546 throw css::uno::RuntimeException("C++ code threw unknown exception");
549 // NO exception occurred...
550 *ppUnoExc = 0;
552 // reconvert temporary params
553 for ( ; nTempIndices--; )
555 sal_Int32 nIndex = pTempIndices[nTempIndices];
556 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
558 if (pParams[nIndex].bIn)
560 if (pParams[nIndex].bOut) // inout
562 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
563 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
564 pThis->getBridge()->getCpp2Uno() );
567 else // pure out
569 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
570 pThis->getBridge()->getCpp2Uno() );
572 // destroy temp cpp param => cpp: every param was constructed
573 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
575 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
577 // return value
578 if (pCppReturn && pUnoReturn != pCppReturn)
580 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
581 pThis->getBridge()->getCpp2Uno() );
582 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
585 catch (...)
587 // fill uno exception
588 CPPU_CURRENT_NAMESPACE::fillUnoException(*ppUnoExc, pThis->getBridge()->getCpp2Uno());
590 // temporary params
591 for ( ; nTempIndices--; )
593 sal_Int32 nIndex = pTempIndices[nTempIndices];
594 // destroy temp cpp param => cpp: every param was constructed
595 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release );
596 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
599 // return type
600 if (pReturnTypeDescr)
601 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
606 namespace bridges::cpp_uno::shared {
608 void unoInterfaceProxyDispatch(
609 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
610 void * pReturn, void * pArgs[], uno_Any ** ppException )
612 // is my surrogate
613 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
614 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
615 #if OSL_DEBUG_LEVEL > 0
616 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
617 #endif
619 switch (pMemberDescr->eTypeClass)
621 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
623 #if OSL_DEBUG_LEVEL > 0
624 // determine vtable call index
625 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
626 assert(nMemberPos < pTypeDescr->nAllMembers);
627 #endif
629 VtableSlot aVtableSlot(
630 getVtableSlot(
631 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>
632 (pMemberDescr)));
634 if (pReturn)
636 // dependent dispatch
637 cpp_call(
638 pThis, aVtableSlot,
639 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
640 0, 0, // no params
641 pReturn, pArgs, ppException );
643 else
645 // is SET
646 typelib_MethodParameter aParam;
647 aParam.pTypeRef =
648 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
649 aParam.bIn = sal_True;
650 aParam.bOut = sal_False;
652 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
653 OUString aVoidName("void");
654 typelib_typedescriptionreference_new(
655 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
657 // dependent dispatch
658 aVtableSlot.index += 1;
659 cpp_call(
660 pThis, aVtableSlot, // get, then set method
661 pReturnTypeRef,
662 1, &aParam,
663 pReturn, pArgs, ppException );
665 typelib_typedescriptionreference_release( pReturnTypeRef );
668 break;
670 case typelib_TypeClass_INTERFACE_METHOD:
672 #if OSL_DEBUG_LEVEL > 0
673 // determine vtable call index
674 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
675 assert(nMemberPos < pTypeDescr->nAllMembers);
676 #endif
678 VtableSlot aVtableSlot(
679 getVtableSlot(
680 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>
681 (pMemberDescr)));
683 switch (aVtableSlot.index)
685 // standard calls
686 case 1: // acquire uno interface
687 (*pUnoI->acquire)( pUnoI );
688 *ppException = 0;
689 break;
690 case 2: // release uno interface
691 (*pUnoI->release)( pUnoI );
692 *ppException = 0;
693 break;
694 case 0: // queryInterface() opt
696 typelib_TypeDescription * pTD = 0;
697 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
698 if (pTD)
700 uno_Interface * pInterface = 0;
701 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
702 pThis->getBridge()->getUnoEnv(),
703 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
705 if (pInterface)
707 ::uno_any_construct(
708 reinterpret_cast< uno_Any * >( pReturn ),
709 &pInterface, pTD, 0 );
710 (*pInterface->release)( pInterface );
711 TYPELIB_DANGER_RELEASE( pTD );
712 *ppException = 0;
713 break;
715 TYPELIB_DANGER_RELEASE( pTD );
717 } [[fallthrough]]; // else perform queryInterface()
718 default:
719 // dependent dispatch
720 cpp_call(
721 pThis, aVtableSlot,
722 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
723 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
724 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
725 pReturn, pArgs, ppException );
727 break;
729 default:
731 ::com::sun::star::uno::RuntimeException aExc(
732 "illegal member type description!",
733 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
735 Type const & rExcType = cppu::UnoType<decltype(aExc)>::get();
736 // binary identical null reference
737 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
744 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */